ci(sync-about): fix docs version-sync clone collision + webpage npm race (#104)

* 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@<version> (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.
This commit is contained in:
kingchenc
2026-06-01 02:02:19 +02:00
committed by GitHub
parent ebddc5e376
commit bff1148d20
+43 -3
View File
@@ -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)."