From 84ffa2da6cf60c454ddf42fa13fad136aee9b170 Mon Sep 17 00:00:00 2001 From: claude-ceo-assistant Date: Sun, 10 May 2026 19:51:18 -0700 Subject: [PATCH] fix(ci): cascade wait-step SHA capture leaked pip stdout (4th defect) Run 5196 (2026-05-11 02:46Z, first-ever successful publish) succeeded the publish job but failed the cascade job at the wait-for-PyPI- propagation step: ::error::PyPI propagated 0.1.130 but wheel content SHA256 mismatch. ::error::Expected: 536b123816f3c7fb54690b80be482b28cabd1874690e9e93d8586af3864c7fba ::error::Got: Collecting molecule-ai-workspace-runtime==0.1.130 ::error::Fastly may be serving stale content. Refusing to fan out cascade. The 'Got:' is pip's own stdout, not a SHA. Root cause: HASH=$(python -m pip download ... 2>/dev/null && sha256sum ... | awk ...) The shell pipeline captures BOTH commands' stdout into $HASH. `2>/dev/null` only silences stderr, not stdout. pip download writes 'Collecting ...' to stdout by default, so it leaks into HASH ahead of sha256sum's output. Fix: split into two steps, redirect pip stdout to /dev/null explicitly, capture only sha256sum's output into HASH. Impact: cascade-to-8-template-repos failed, but PyPI publish itself succeeded. Users (workspace-template-* maintainers) can pin manually via 'docker build --build-arg RUNTIME_VERSION=X.Y.Z' until cascade is healed. hongming-pc is doing exactly this for the plugins_registry rollout. 4th and likely last workflow defect after #353, #355, #357. Refs: #351, #353, #355, #357, #348 Q3 --- .gitea/workflows/publish-runtime.yml | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.gitea/workflows/publish-runtime.yml b/.gitea/workflows/publish-runtime.yml index cefd9259..fe46e812 100644 --- a/.gitea/workflows/publish-runtime.yml +++ b/.gitea/workflows/publish-runtime.yml @@ -207,13 +207,23 @@ jobs: # Stage (b): download wheel + SHA256 compare against what we built. # Catches Fastly stale-content serving old bytes under a new version URL. - HASH=$(python -m pip download \ - --no-deps \ - --no-cache-dir \ - --dest /tmp/wheel-probe \ - "molecule-ai-workspace-runtime==${RUNTIME_VERSION}" \ - 2>/dev/null \ - && sha256sum /tmp/wheel-probe/*.whl | awk '{print $1}') + # + # Caught run 5196 (first-ever successful publish, 2026-05-11): the + # previous one-liner `HASH=$(pip download ... && sha256sum ...)` + # captured pip's stdout (`Collecting molecule-ai-workspace-runtime + # ==X.Y.Z`) into HASH, then the SHA comparison failed against the + # leaked `Collecting...` string. `2>/dev/null` silences stderr but + # NOT stdout; pip writes its progress to stdout by default. + # Fix: split into two steps, silence pip's stdout explicitly, capture + # only sha256sum's output into HASH. + python -m pip download \ + --no-deps \ + --no-cache-dir \ + --dest /tmp/wheel-probe \ + --quiet \ + "molecule-ai-workspace-runtime==${RUNTIME_VERSION}" \ + >/dev/null 2>&1 + HASH=$(sha256sum /tmp/wheel-probe/*.whl | awk '{print $1}') if [ "$HASH" != "$EXPECTED_SHA256" ]; then echo "::error::PyPI propagated $RUNTIME_VERSION but wheel content SHA256 mismatch." echo "::error::Expected: $EXPECTED_SHA256"