From bff1148d206e08f9d6b7ad88248380d476720e0c Mon Sep 17 00:00:00 2001 From: kingchenc Date: Mon, 1 Jun 2026 02:02:19 +0200 Subject: [PATCH] ci(sync-about): fix docs version-sync clone collision + webpage npm race (#104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci(sync-about): fix docs version-sync clone collision + webpage npm race Two real release-time bugs surfaced by the v0.4.0 release, where the docs "Published versions" table never updated and the marketing-site Cloudflare build failed: 1. docs version sync never ran. The "Sync docs version (wickra-docs)" step cloned into a directory literally named `docs`, but on a tag push the job checks out the wickra repo at the workspace root, which already contains a top-level `docs/` directory. `git clone … docs` therefore failed with "destination path 'docs' already exists", silenced by `2>/dev/null` and misreported as a missing-token warning, so the docs version table stayed at the previous release. Clone into `docs-ver` instead (mirrors the `docs-count` dir the count step already uses); it collides with nothing in the repo. 2. webpage build broke on a version race. The "Sync webpage version" step bumps package.json's `wickra-wasm` pin to the released version and pushes immediately, but release.yml publishes wickra-wasm to npm in parallel on the same tag and finishes minutes later. Cloudflare's `npm clean-install` then hit `ETARGET: No matching version found for wickra-wasm@^0.4.0`. Poll npm for wickra-wasm@ (up to ~15 min) before committing; if it never appears the step skips with a warning rather than pushing a build-breaking commit. Both steps were designed to mirror each other across docs/webpage; these fixes restore that symmetry so every release self-heals both sites. * ci(sync-about): regenerate webpage package-lock on version bump Third v0.4.0 release-sync defect: the webpage version step seds package.json's wickra-wasm pin but never touched package-lock.json, so even after wickra-wasm went live on npm the Cloudflare build still failed with `npm ci` EUSAGE: "lock file's wickra-wasm@0.3.1 does not satisfy wickra-wasm@0.4.0". After the package.json sed, run `npm install --package-lock-only` so the lockfile (version + resolved + integrity) matches the new pin; commit package-lock.json alongside package.json. The earlier npm-wait already guarantees the version is resolvable. Guarded: if the regen fails the step skips the whole commit rather than push a package.json/lock mismatch. The live site was unblocked out-of-band by a matching lockfile commit on the webpage repo; this makes it self-heal on every future release. --- .github/workflows/sync-about.yml | 46 +++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync-about.yml b/.github/workflows/sync-about.yml index f9c65de7..0ada6887 100644 --- a/.github/workflows/sync-about.yml +++ b/.github/workflows/sync-about.yml @@ -331,11 +331,19 @@ jobs: echo "::warning::tag '${GITHUB_REF}' is not a plain vMAJOR.MINOR.PATCH release; skipping docs version sync." exit 0 fi - if ! git clone "https://x-access-token:${GH_TOKEN}@github.com/wickra-lib/wickra-docs.git" docs 2>/dev/null; then + # Clone into `docs-ver`, NOT `docs`: on a tag push this job checks out + # the wickra repo at the workspace root, which already contains a + # top-level `docs/` directory, so `git clone … docs` fails with + # "destination path 'docs' already exists" — silently, because of the + # 2>/dev/null below — and the version sync never runs (this is exactly + # why v0.4.0 did not bump the docs table). `docs-ver` mirrors the + # `docs-count` dir used by the count step above and collides with + # nothing in the repo. + if ! git clone "https://x-access-token:${GH_TOKEN}@github.com/wickra-lib/wickra-docs.git" docs-ver 2>/dev/null; then echo "::warning::cannot clone wickra-lib/wickra-docs — ABOUT_SYNC_TOKEN likely lacks write on that repo (findings P10.0a). Skipping docs version sync." exit 0 fi - cd docs + cd docs-ver # Published-versions table rows (crates.io / PyPI / npm): replace only the # version number, leaving the trailing padding + pipe intact. The '.' in # the quickstart pattern matches the literal backtick around the version @@ -403,6 +411,26 @@ jobs: echo "::warning::tag '${GITHUB_REF}' is not a plain vMAJOR.MINOR.PATCH release; skipping webpage version sync." exit 0 fi + # The webpage pins wickra-wasm to the released version in package.json, + # and its Cloudflare Pages build runs `npm clean-install`. release.yml + # publishes wickra-wasm to npm in parallel on this same tag and finishes + # minutes later, so committing the bump immediately would point the site + # at a version npm cannot resolve yet (ETARGET) and break the build — + # exactly what happened on v0.4.0. Wait until wickra-wasm@$version is + # actually live on npm before committing; if it never appears (the wasm + # publish failed), skip rather than push a build-breaking commit. + echo "Waiting for wickra-wasm@${version} on npm before bumping the webpage..." + attempts=0 + until npm view "wickra-wasm@${version}" version >/dev/null 2>&1; do + attempts=$((attempts + 1)) + if [ "$attempts" -ge 30 ]; then + echo "::warning::wickra-wasm@${version} not on npm after ~15 min; skipping webpage version sync to avoid a broken Cloudflare build." + exit 0 + fi + echo " not on npm yet (attempt ${attempts}/30); waiting 30s..." + sleep 30 + done + echo "wickra-wasm@${version} is live on npm; proceeding with the webpage version bump." if ! git clone "https://x-access-token:${GH_TOKEN}@github.com/wickra-lib/webpage.git" webpage-ver 2>/dev/null; then echo "::warning::cannot clone wickra-lib/webpage — ABOUT_SYNC_TOKEN likely lacks write (findings P10.0a). Skipping webpage version sync." exit 0 @@ -415,13 +443,25 @@ jobs: sed -i -E "s/(Latest:\*\* \[.wickra(-wasm)? )[0-9]+\.[0-9]+\.[0-9]+/\1${version}/" api/*.md sed -i -E "s/(text: .v)[0-9]+\.[0-9]+\.[0-9]+/\1${version}/" .vitepress/config.ts sed -i -E "s/(.wickra-wasm.: .\^)[0-9]+\.[0-9]+\.[0-9]+/\1${version}/" package.json + # Keep package-lock.json in sync with the package.json bump. The site's + # Cloudflare build runs `npm clean-install` (npm ci), which hard-fails + # with EUSAGE if the lockfile still pins the previous wickra-wasm — + # editing package.json alone is not enough. The npm-wait above already + # proved wickra-wasm@$version is resolvable, so --package-lock-only + # regenerates the lock (version + resolved + integrity) without fetching + # node_modules. Guard it: if the regen fails, skip the whole commit so we + # never push a package.json/lock mismatch that would break the build. + if ! npm install --package-lock-only --no-audit --no-fund; then + echo "::warning::could not regenerate package-lock.json for wickra-wasm@${version}; skipping webpage version sync to avoid a lockfile-drift build break." + exit 0 + fi if git diff --quiet; then echo "Webpage version already at ${version}." exit 0 fi git config user.name "wickra-bot" git config user.email "wickra-bot@users.noreply.github.com" - git add api/*.md .vitepress/config.ts package.json + git add api/*.md .vitepress/config.ts package.json package-lock.json git commit -m "chore: sync published version to ${version}" if ! git push 2>/dev/null; then echo "::warning::push to wickra-lib/webpage failed — ABOUT_SYNC_TOKEN likely lacks write (findings P10.0a)."