ci(extension): shadow the derived version + verify real XPI contents
CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
CI / frontend-build (push) Successful in 21s
extension / lint (push) Failing after 28s
CI / backend-lint-and-test (push) Successful in 47s
CI / integration (push) Successful in 4m1s

Milestone #271 steps 2 and 3. Neither changes what gets published.

STEP 2 -- shadow mode.

build.yml's sign-extension and ci.yml's extension-version guard now log the
version that WOULD be derived from git history alongside the hand-maintained
one. Nothing reads the derived value, and neither site can fail because of it.

This exists because `web-ext sign` is one-shot per version: AMO 409s on a
repeat, so a wrong formula burns a real version number that cannot be
reclaimed. Comparing the two across real builds is the only way to validate it
at zero cost. sign-extension runs on main only, so main pushes are the sole
source of truth for whether the derived number moves exactly when the shipped
extension changes -- the dev-side log is a convenience, not the evidence.

sign-extension now checks out with fetch-depth: 0. The derived version is a
commit count and a depth-1 clone cannot produce one.

STEP 3 -- XPI content verification.

Every other packaging assertion checks our declaration against itself. This is
the first that asks web-ext what it ACTUALLY wrote into the archive.

That assumption was both unverified and fragile: `test/**` only survives to
web-ext because callers `set -f` before substituting it, so losing that
quoting would silently start shipping dev files with no other signal. The step
builds the XPI and asserts test/, scripts/, vitest.config.js, package.json,
package-lock.json, README.md and node_modules are absent -- and, because an
over-matching exclusion would break the extension at runtime rather than at
build time, that manifest.json, all four lib/*.js and every UI directory are
present.

unzip is installed only when missing; node:24-bookworm-slim may not carry it.

Refs #2399, #2400

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-08-03 16:15:12 -04:00
parent 597b91d29b
commit 1c6452e10e
4 changed files with 83 additions and 0 deletions
+11
View File
@@ -77,6 +77,17 @@ jobs:
test -n "$PKG" || { echo "ERROR: no version found in extension/package.json"; exit 1; }
test -n "$MAN" || { echo "ERROR: no version found in extension/manifest.json"; exit 1; }
# --- shadow mode (milestone #271, step 2) -------------------------
# Informational ONLY: nothing below reads DERIVED, and this must never
# fail the job. `web-ext sign` is one-shot per version (AMO 409s on a
# repeat), so a wrong formula would burn a real version number that
# can't be reclaimed. Logging it against real pushes first is the only
# way to validate it at zero cost.
# Placed before every early-exit path so it reports on all runs.
DERIVED=$(sh extension/scripts/packaging.sh version 2>&1 || echo "UNAVAILABLE")
echo "shadow: manual=$PKG derived=$DERIVED"
# -----------------------------------------------------------------
# (1) Unconditional: the two version strings must agree. `web-ext sign`
# reads manifest.json (package.json sits in --ignore-files and isn't
# even inside the XPI), so AMO signs MAN and Firefox installs MAN.