From 827d99c100eecd388f9b4e148638ca9fa5f6f340 Mon Sep 17 00:00:00 2001 From: Jayanth Komarraju Date: Wed, 12 Aug 2026 14:04:05 -0500 Subject: [PATCH] Make the registry-propagation retry loop in the release smoke actually retry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.2.0 published correctly to both registries and the smoke job still failed, for a reason that had nothing to do with the packages. PyPI had not propagated `tx402==0.2.0` when attempt 1 ran — exactly the race the retry loop exists for. But `uv venv` had already created `.venv` before `uv pip install` failed, so attempts 2 through 5 died at `uv venv` with "a virtual environment already exists", and the `&&` chain short-circuited before the install was ever retried. A loop written to survive propagation lag could not survive its own first failure. `uv venv --clear` recreates the environment each round, so a retry is actually a retry. Both loops also ran off the end when every attempt failed, leaving the next command to report the problem. That is why the log's headline was `Failed to spawn: tx402 — No such file or directory` rather than "the package never appeared", which is what actually happened. Each loop now fails explicitly and names the registry and version. Verified by reproducing it: a second plain `uv venv` reports "already exists", and `uv venv --clear` succeeds. --- .github/workflows/release.yml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97fb6af..822d699 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -394,11 +394,19 @@ jobs: set -euo pipefail version="${GITHUB_REF_NAME#v}" # Registry propagation is not instantaneous; retry rather than fail on a race. + # Exhausting the retries is a FAILURE, not something to fall through: the old loop + # ran off the end and let the next command produce the error, which reported a + # missing binary instead of "the package never appeared". + installed="" for attempt in 1 2 3 4 5; do - npm install --no-save "tx402@$version" && break + if npm install --no-save "tx402@$version"; then installed=yes; break; fi echo "attempt $attempt failed, waiting" sleep 20 done + if [ -z "$installed" ]; then + echo "::error::tx402@$version did not become installable from npm after 5 attempts." + exit 1 + fi npx --yes "tx402@$version" --version node -e "import('tx402').then(m => { if (typeof m.createTx402Client !== 'function') throw new Error('missing export'); console.log('npm ok'); })" @@ -406,11 +414,22 @@ jobs: run: | set -euo pipefail version="${GITHUB_REF_NAME#v}" + # `--clear` is load-bearing, and 0.2.0 is why. PyPI had not propagated yet, so + # attempt 1's `uv pip install` failed AFTER `uv venv` had already created `.venv`. + # Every later attempt then died at `uv venv` — "a virtual environment already + # exists" — so the `&&` chain short-circuited and the install was never retried + # even once. The retry loop that existed precisely for propagation lag could not + # survive its own first failure. Recreating the environment each time fixes it. + installed="" for attempt in 1 2 3 4 5; do - uv venv && uv pip install "tx402==$version" && break + if uv venv --clear && uv pip install "tx402==$version"; then installed=yes; break; fi echo "attempt $attempt failed, waiting" sleep 20 done + if [ -z "$installed" ]; then + echo "::error::tx402==$version did not become installable from PyPI after 5 attempts." + exit 1 + fi uv run tx402 --version uv run python -c "import tx402; print('pypi ok', tx402.PACKAGE_NAME)"