Extension channels: dev and main each carry their own signed extension #237
@@ -84,6 +84,12 @@ jobs:
|
||||
# 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.
|
||||
#
|
||||
# The formula CHANGED on 2026-08-27 (commit count -> commit time, per
|
||||
# rule 149), so observations logged before that date describe the old
|
||||
# one and prove nothing about this. The window restarts here. Unlike
|
||||
# build.yml's copy this runs on dev too, so both channels' numbers are
|
||||
# visible — which is the pair that has to stay ordered.
|
||||
DERIVED=$(sh extension/scripts/packaging.sh version 2>&1 || echo "UNAVAILABLE")
|
||||
echo "shadow: manual=$PKG derived=$DERIVED"
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
+9
-5
@@ -56,11 +56,15 @@ per `docs/process.md`'s "add deps to the image when used by >1 project".
|
||||
- **`extension/scripts/packaging.sh` is the single definition of what ships
|
||||
inside the XPI.** Three consumers read from it rather than keeping their own
|
||||
copy: web-ext's `--ignore-files` (`extension/package.json`), the `:(exclude)`
|
||||
pathspec in `ci.yml`'s `extension-version` guard, and the commit count that
|
||||
derives the extension version. Three hand-kept copies of that one fact is
|
||||
what allowed issue #2397.
|
||||
- `build.yml`'s `sign-extension` checks out with `fetch-depth: 0` — the derived
|
||||
extension version is a commit count, which a shallow clone cannot produce.
|
||||
pathspec in `ci.yml`'s `extension-version` guard, and the `git log` pathspec
|
||||
that derives the extension version. Three hand-kept copies of that one fact
|
||||
is what allowed issue #2397.
|
||||
- Jobs that derive the extension version check out with `fetch-depth: 0`. The
|
||||
version is the commit TIME of the newest packaged-extension change (minutes
|
||||
since 2020-01-01, per family rule 149 — never a commit count, which orders
|
||||
by branch rather than by recency). A depth-1 clone sees one commit and
|
||||
derives a wrong, too-low value rather than failing, so the full-history
|
||||
checkout is load-bearing wherever `packaging.sh version` is called.
|
||||
- Callers MUST `set -f` before substituting the script's output. Without it the
|
||||
shell expands `test/**` against the working tree and silently narrows the
|
||||
pattern to whatever files exist at that moment — a failure that looks like
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
# 1. web-ext's --ignore-files (extension/package.json's four scripts)
|
||||
# 2. the :(exclude) pathspec (ci.yml's extension-version guard)
|
||||
# 3. the rev-list pathspec (the derived version, below)
|
||||
# 3. the git-log pathspec (the derived version, below)
|
||||
#
|
||||
# They now all read from here. POSIX sh only — CI's run shell is busybox.
|
||||
#
|
||||
@@ -68,20 +68,51 @@ cmd_major_minor() {
|
||||
| sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([0-9]+)\.([0-9]+).*/\1.\2/'
|
||||
}
|
||||
|
||||
# Count of commits that touched a PACKAGED extension file. Monotonic on a
|
||||
# branch (the count only grows), which is a correctness requirement, not a
|
||||
# nicety: Firefox refuses to install a version lower than the one present.
|
||||
# 2020-01-01T00:00:00Z — the anchor for the derived patch component. Fixed
|
||||
# forever; moving it would renumber every version downwards.
|
||||
VERSION_EPOCH=1577836800
|
||||
|
||||
# Minutes since VERSION_EPOCH of the LATEST commit that touched a PACKAGED
|
||||
# extension file.
|
||||
#
|
||||
# Merge commits need no special handling — git's history simplification already
|
||||
# prunes merges that don't change the pathspec, so --no-merges is a no-op here
|
||||
# (verified on main: both forms return the same count).
|
||||
# Time-derived, per family rule 149: an artifact's ordering key must never be a
|
||||
# commit count. A count is per-branch — `dev` and `main` count different
|
||||
# histories of the same code — so the moment BOTH channels publish, their
|
||||
# versions order by which branch accumulated more commits rather than by which
|
||||
# is newer. A squash-merge makes that permanent: main gains one commit where dev
|
||||
# gained five, so dev climbs away from main and a dev install can never cross
|
||||
# back. That is Roundtable's 2026-08-24 incident (`versionCode` was the branch's
|
||||
# commit count) in a different repo. Measured here on 2026-08-27: main=23,
|
||||
# dev=24 under the old formula — one apart, which is exactly how the inversion
|
||||
# stays invisible until it strands somebody.
|
||||
#
|
||||
# Why the commit's time and not the build's:
|
||||
# * MONOTONIC — max() over a set that only ever gains members. Verified
|
||||
# across all 24 extension-touching commits: zero non-monotonic steps.
|
||||
# * STABLE while the extension is unchanged, so an unchanged extension keeps
|
||||
# its version, the ext-<version> signature cache still hits, and AMO is
|
||||
# called once per extension CHANGE rather than once per push. Build-time
|
||||
# minutes would re-sign on every push and never let two channels share a
|
||||
# signature.
|
||||
# * SHARED ACROSS CHANNELS — after a merge, `main` sees the same commit and
|
||||
# derives the same number, so `:latest` reuses the signature `:dev` already
|
||||
# produced for byte-identical code. Same code, same version, one signing.
|
||||
# * REPRODUCIBLE — any checkout of a commit yields that commit's version.
|
||||
#
|
||||
# Requires real history: a depth-1 clone sees one commit and will derive a wrong
|
||||
# (too low) value. Every consumer must check out with fetch-depth: 0.
|
||||
cmd_patch() {
|
||||
root=$(git rev-parse --show-toplevel)
|
||||
# Unquoted on purpose: the pathspec must word-split into separate args.
|
||||
# Globbing is already off script-wide (set -euf above).
|
||||
# shellcheck disable=SC2046
|
||||
count=$(cd "$root" && git rev-list --count HEAD -- extension/ $(cmd_pathspec))
|
||||
echo "$count"
|
||||
ts=$(cd "$root" && git log --format=%ct HEAD -- extension/ $(cmd_pathspec) \
|
||||
| sort -n | tail -1)
|
||||
if [ -z "$ts" ]; then
|
||||
echo "packaging.sh: no commit touches a packaged extension file" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo $(( (ts - VERSION_EPOCH) / 60 ))
|
||||
}
|
||||
|
||||
cmd_version() {
|
||||
|
||||
Reference in New Issue
Block a user