"""`artifacts.sh revision` is what decides whether a build gets skipped. Milestone 318 step 3: each image carries its revision as an `fc.revision` label, and build.yml reads that label back off the moving channel tag. Equal to the derived revision means the bytes this push would produce are already published, so the build is skipped. That makes the revision load-bearing in a way a version string is not — it is compared for equality against a value stamped into a real published artifact. Both ways of getting it wrong are silent: * **it does not identify the content** — a revision that moves when the source did not (a HEAD-derived value, say) never matches, nothing is ever skipped, and the mechanism quietly buys nothing while every lane stays green. * **it identifies the wrong content** — a revision that holds still when the source DID change matches a stale label, the build is skipped, and the channel serves bytes that do not correspond to the commit. This is the dangerous direction, and it is what `test_artifact_paths.py` guards from the other side by pinning the path sets. This module owns the narrower claim: whatever the path sets say, the revision is genuinely the commit those paths last changed in. 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. """ from __future__ import annotations import re import subprocess import pytest from test_artifact_paths import ROOT, declared_paths ARTIFACTS = ("web", "ml", "agent", "extension") # 12 hex chars — the prefix build.yml stamps and compares. _REVISION = re.compile(r"^[0-9a-f]{12}$") def revision(artifact: str) -> str: return subprocess.run( ["sh", str(ROOT / "scripts" / "artifacts.sh"), "revision", artifact], capture_output=True, text=True, check=True, cwd=ROOT, ).stdout.strip() @pytest.mark.parametrize("artifact", ARTIFACTS) def test_revision_is_the_commit_its_own_shipped_files_last_changed_in(artifact): """The claim the whole skip decision rests on. Asked of git directly rather than of the script, so this fails if the derivation ever stops meaning what it says — deriving from HEAD, from a build clock, or from a path set it did not actually use. """ paths = declared_paths(artifact) expected = subprocess.run( ["git", "log", "--format=%H", "-1", "HEAD", "--", *paths], capture_output=True, text=True, check=True, cwd=ROOT, ).stdout.strip() assert expected, ( f"no commit in this history touches the {artifact} path set — the " f"derivation has nothing to stand on" ) assert expected.startswith(revision(artifact)), ( f"{artifact} derives {revision(artifact)!r}, but the newest commit " f"touching its shipped files is {expected[:12]!r}. The label stamped " f"into the image would not identify its own content." ) @pytest.mark.parametrize("artifact", ARTIFACTS) def test_revision_is_a_legal_label_value_and_is_stable(artifact): """It is stamped as a docker label and compared for string equality, so a stray newline or a varying value breaks the comparison rather than the build — the mechanism would simply stop hitting, silently.""" first = revision(artifact) assert _REVISION.match(first), f"{first!r} is not a 12-char hex revision" assert first == revision(artifact), "revision is not stable across calls" def test_an_artifact_whose_paths_did_not_change_keeps_its_revision(): """The property that makes skipping possible at all. The agent's set is disjoint from web's, so the two must be free to differ. Asserting they *are* different today would pin an accident of history — what matters is that the derivation is per-artifact rather than global, so this asserts each artifact's revision is drawn from its own path set. """ seen = {a: revision(a) for a in ARTIFACTS} for artifact, rev in seen.items(): touched = subprocess.run( ["git", "log", "--format=%H", "-1", "HEAD", "--", *declared_paths(artifact)], capture_output=True, text=True, check=True, cwd=ROOT, ).stdout.strip() assert touched.startswith(rev), ( f"{artifact}'s revision {rev!r} is not the newest commit touching " f"its own paths — the derivation is not per-artifact" )