Milestone 318 step 8 — extension CalVer, and the #3190 mitigation's first main build #241

Merged
bvandeusen merged 3 commits from dev into main 2026-08-29 13:53:59 -04:00
Showing only changes of commit 1a941e900b - Show all commits
+72 -2
View File
@@ -34,6 +34,15 @@ is genuinely the commit those paths last changed in.
emit. Two nearly-identical formats are more dangerous than two obviously
different ones, and the only thing keeping them identical is a test.
**The extension is the one exception, and it is a rendering exception only.**
AMO's version grammar forbids a leading zero, so the extension emits the same
numbers unpadded — `2026.8.29.201` where the family says `2026.08.29.0201`
(#3138, milestone 318 step 8). Rule 148 defines comparison as numeric per
dot-segment, under which the two are equal, so this is pinned in both
directions below: the extension must satisfy AMO's grammar, and every artifact
must derive the same NUMBERS its own commit stamps. An exception left as "the
extension is different" would drift into being differently different.
The identity-TAG tests this file used to hold are gone with the tag. There is
no longer a `CHANNELLED` list to drift (the channel is which tag you inspect),
and no `identity` subcommand to refuse an unqualified call.
@@ -57,6 +66,26 @@ _REVISION = re.compile(r"^[0-9a-f]{12}$")
# YYYY.MM.DD.HHMM, every segment zero-padded to its full width.
_VERSION = re.compile(r"^\d{4}\.\d{2}\.\d{2}\.\d{4}$")
# The artifacts that cannot use the padded rendering. Exactly one, and the
# reason is external: `packaging.sh` derives the extension's version and AMO
# refuses to sign a padded one.
AMO_UNPADDED = frozenset({"extension"})
# Mozilla's published grammar for addons.mozilla.org, transcribed from MDN's
# manifest.json/version page. A segment is the single digit `0` or starts 1-9,
# and there are at most four. This is the constraint the exception exists for,
# so it is what the exception is tested against — `2026.08.29.0201` fails it.
_AMO = re.compile(r"^(0|[1-9][0-9]{0,8})(\.(0|[1-9][0-9]{0,8})){0,3}$")
# YYYY.M.D.HHMM — four segments, none of them zero-padded.
_UNPADDED = re.compile(r"^\d{4}(\.(0|[1-9]\d*)){3}$")
def segments(value: str) -> tuple[int, ...]:
"""A version as the numbers it denotes, which is how rule 148 says to
compare one. `2026.08.29.0201` and `2026.8.29.201` are one value here."""
return tuple(int(part) for part in value.split("."))
# Everything here goes through artifacts.sh rather than importing a sibling
# test module. That is the interface build.yml actually calls, so the tests
@@ -126,7 +155,7 @@ def test_revision_is_a_legal_label_value_and_is_stable(artifact):
assert first == revision(artifact), "revision is not stable across calls"
@pytest.mark.parametrize("artifact", ARTIFACTS)
@pytest.mark.parametrize("artifact", sorted(set(ARTIFACTS) - AMO_UNPADDED))
def test_version_is_zero_padded_calver(artifact):
"""The family shape, pinned.
@@ -148,6 +177,31 @@ def test_version_is_zero_padded_calver(artifact):
)
@pytest.mark.parametrize("artifact", sorted(AMO_UNPADDED))
def test_the_unpadded_artifacts_derive_something_amo_will_sign(artifact):
"""The other half of the family shape: the documented exception, tested
against the constraint that justifies it rather than against itself.
A padded value passes `_UNPADDED` on any date with no leading zeros, so
that pattern alone would let a regression sit unnoticed until the first
single-digit month — at which point the failure is a burned AMO version,
not a red lane. AMO's grammar is the assertion that fires immediately.
"""
value = artifacts("version", artifact).strip()
assert _AMO.match(value), (
f"{artifact} derives {value!r}, which AMO refuses: a segment must be "
f"the single digit `0` or start 1-9, and there are at most four. "
f"Almost certainly a zero-padded segment — the family pads and this "
f"artifact must not (#3138). AMO 409s on re-signing, so a version it "
f"rejects is burned."
)
assert _UNPADDED.match(value), (
f"{artifact} derives {value!r}, which is not YYYY.M.D.HHMM. AMO would "
f"also accept the pre-318 `1.0.<minutes>`, and that orders below every "
f"ext-2026.* release already signed."
)
@pytest.mark.parametrize("artifact", ARTIFACTS)
def test_version_and_revision_describe_the_same_commit(artifact):
"""They are derived independently and must not be able to disagree.
@@ -162,5 +216,21 @@ def test_version_and_revision_describe_the_same_commit(artifact):
capture_output=True, text=True, check=True, cwd=ROOT,
env={"TZ": "UTC", "PATH": os.environ.get("PATH", "")},
).stdout.strip()
assert artifacts("version", artifact).strip() == stamped
derived = artifacts("version", artifact).strip()
# Compared as NUMBERS, which is how rule 148 defines comparison and the
# only way one assertion can cover both renderings. This is what makes the
# extension's exception cosmetic rather than semantic: it must denote
# exactly the value its own commit stamps, whatever the padding.
assert segments(derived) == segments(stamped), (
f"{artifact} derives {derived!r}, but its newest shipped commit "
f"{sha[:12]} is {stamped!r}. The instance would name one commit while "
f"carrying another's bytes."
)
if artifact not in AMO_UNPADDED:
assert derived == stamped, (
f"{artifact} derives {derived!r} where the family shape is "
f"{stamped!r} — same numbers, wrong rendering. Only the artifacts "
f"in AMO_UNPADDED may differ here."
)
assert sha.startswith(revision(artifact))