From 3ebfbd9728fa022ed7cbc91c88cf05bc2556d91d Mon Sep 17 00:00:00 2001 From: Sylvain Cau Date: Sat, 22 Aug 2026 13:37:02 -0700 Subject: [PATCH] ci: wait out npm's registry propagation before installing the published SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `publish-plugins` rewrites each plugin's SDK dependency from `file:` to the version `publish-sdk` has just pushed, then reinstalls. That install has to resolve the SDK from the registry seconds after it was published, and npm's registry is eventually consistent across CDN edges, so it intermittently fails with "no matching version" and a manual re-run fixes it. Adds two guards, because one is not enough: - Poll `npm view` until the version is visible, up to five minutes, before attempting the install. - Retry `npm install` up to five times anyway. `npm view` and `npm install` do not necessarily hit the same CDN edge, so the poll succeeding does not prove the install will resolve. `--prefer-online` revalidates rather than trusting a 404 cached by the failed attempt. The version is exported through GITHUB_ENV so the poll can see what the rewrite step computed. This does not remove the race, it waits it out. Building against the local `file:` SDK and rewriting the manifest only at publish time would remove it outright, since the bundle is identical either way, but that restructures a publish path that is awkward to test — this is the change that can be reasoned about when a release is half out. Not verifiable in CI: `publish-plugins` only runs on a release. --- .github/workflows/build.yml | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29967e01..ba2f45fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -604,14 +604,44 @@ jobs: jq --arg v "^$SDK_VERSION" '.dependencies["@ashdev/codex-plugin-sdk"] = $v' package.json > tmp.json mv tmp.json package.json cat package.json | grep -A2 '"dependencies"' - # The step above rewrites the SDK dependency (file: -> published version), - # which desyncs the committed lockfile. npm ci would fail here, so this - # publish-only step must use npm install to regenerate the lockfile. + echo "SDK_VERSION=$SDK_VERSION" >> "$GITHUB_ENV" + # npm's registry is eventually consistent: the version `publish-sdk` just + # pushed can take a minute to appear on every CDN edge, so installing it + # immediately fails with "no matching version" and a manual re-run fixes + # it. Wait for the version to become visible before asking for it. + - name: Wait for the published SDK to be resolvable + run: | + for attempt in $(seq 1 30); do + if [ -n "$(npm view "@ashdev/codex-plugin-sdk@$SDK_VERSION" version 2>/dev/null)" ]; then + echo "SDK $SDK_VERSION resolvable after attempt $attempt" + exit 0 + fi + echo "attempt $attempt/30: $SDK_VERSION not visible yet, retrying in 10s" + sleep 10 + done + echo "::error::@ashdev/codex-plugin-sdk@$SDK_VERSION never became resolvable" + exit 1 + # The rewrite above desyncs the committed lockfile, so `npm ci` would fail + # and this publish-only step must regenerate it with `npm install`. + # + # Retried even though the step above waited: `npm view` and `npm install` + # do not necessarily hit the same CDN edge, so one seeing the version does + # not guarantee the other does. `--prefer-online` revalidates rather than + # trusting a cached 404 from the failed attempt. - name: Install plugin dependencies working-directory: plugins/${{ matrix.plugin }} run: | - rm -rf node_modules package-lock.json - npm install + for attempt in 1 2 3 4 5; do + rm -rf node_modules package-lock.json + if npm install --prefer-online; then + echo "npm install succeeded on attempt $attempt" + exit 0 + fi + echo "npm install failed on attempt $attempt/5, retrying in 15s" + sleep 15 + done + echo "::error::npm install failed after 5 attempts" + exit 1 - name: Build plugin working-directory: plugins/${{ matrix.plugin }} run: npm run build