From 97f3b6b1ae303c972387508557a3d54ea621a702 Mon Sep 17 00:00:00 2001 From: Andraxion Date: Wed, 29 Jul 2026 16:39:21 -0400 Subject: [PATCH] Verify legacy tag in fresh-clone gate --- tests/test_milestone5_fresh_clone.py | 81 ++++++++++++++++++++++++++++ tools/milestone5_fresh_clone.py | 57 +++++++++++++++++++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/tests/test_milestone5_fresh_clone.py b/tests/test_milestone5_fresh_clone.py index 2724d91..812d378 100644 --- a/tests/test_milestone5_fresh_clone.py +++ b/tests/test_milestone5_fresh_clone.py @@ -1,11 +1,21 @@ from __future__ import annotations +import subprocess +import tempfile import unittest +from pathlib import Path from tools.milestone5_fresh_clone import ( COMMIT_PATTERN, + EXPECTED_LEGACY_TAG_COMMIT, + EXPECTED_LEGACY_TAG_OBJECT, EXPECTED_ORIGINS, + LEGACY_MIGRATION_TAG, PUBLIC_REPOSITORY, + ROOT, + FreshCloneError, + obtain_legacy_tag, + validate_legacy_tag, ) @@ -24,6 +34,77 @@ class Milestone5FreshCloneTests(unittest.TestCase): with self.subTest(invalid=invalid): self.assertIsNone(COMMIT_PATTERN.fullmatch(invalid)) + def test_frozen_legacy_tag_identity_is_exact(self) -> None: + self.assertEqual("v1.0.0", LEGACY_MIGRATION_TAG) + self.assertEqual( + EXPECTED_LEGACY_TAG_OBJECT, + subprocess.run( + ["git", "rev-parse", LEGACY_MIGRATION_TAG], + cwd=ROOT, + check=True, + capture_output=True, + text=True, + ).stdout.strip(), + ) + self.assertEqual( + EXPECTED_LEGACY_TAG_COMMIT, + subprocess.run( + ["git", "rev-parse", f"{LEGACY_MIGRATION_TAG}^{{commit}}"], + cwd=ROOT, + check=True, + capture_output=True, + text=True, + ).stdout.strip(), + ) + + def test_tagless_clone_obtains_and_verifies_only_frozen_legacy_tag(self) -> None: + with tempfile.TemporaryDirectory() as directory_name: + clone = Path(directory_name) / "clone" + subprocess.run( + ["git", "clone", "--no-tags", str(ROOT), str(clone)], + check=True, + capture_output=True, + text=True, + ) + initial_tags = subprocess.run( + ["git", "tag", "--list"], + cwd=clone, + check=True, + capture_output=True, + text=True, + ).stdout.splitlines() + self.assertEqual([], initial_tags) + + _, tag_object, tag_commit = obtain_legacy_tag(clone) + + self.assertEqual(EXPECTED_LEGACY_TAG_OBJECT, tag_object) + self.assertEqual(EXPECTED_LEGACY_TAG_COMMIT, tag_commit) + fetched_tags = subprocess.run( + ["git", "tag", "--list"], + cwd=clone, + check=True, + capture_output=True, + text=True, + ).stdout.splitlines() + self.assertEqual([LEGACY_MIGRATION_TAG], fetched_tags) + + def test_legacy_tag_validation_rejects_substitution(self) -> None: + valid = { + "object_type": "tag", + "tag_object": EXPECTED_LEGACY_TAG_OBJECT, + "tag_commit": EXPECTED_LEGACY_TAG_COMMIT, + } + invalid_cases = ( + ("lightweight tag", {"object_type": "commit"}), + ("moved tag object", {"tag_object": "a" * 40}), + ("moved tag commit", {"tag_commit": "b" * 40}), + ) + for label, replacement in invalid_cases: + with self.subTest(label=label): + values = valid | replacement + with self.assertRaises(FreshCloneError): + validate_legacy_tag(**values) + if __name__ == "__main__": unittest.main() diff --git a/tools/milestone5_fresh_clone.py b/tools/milestone5_fresh_clone.py index 02703da..889377d 100644 --- a/tools/milestone5_fresh_clone.py +++ b/tools/milestone5_fresh_clone.py @@ -22,6 +22,10 @@ EXPECTED_ORIGINS = { } COMMIT_PATTERN = re.compile(r"^[0-9a-f]{40}$") COMMAND_TIMEOUT_SECONDS = 30 * 60 +LEGACY_MIGRATION_TAG = "v1.0.0" +LEGACY_MIGRATION_TAG_REF = f"refs/tags/{LEGACY_MIGRATION_TAG}" +EXPECTED_LEGACY_TAG_OBJECT = "2d7d306a37da89f1c860c7f0be161c45386acf61" +EXPECTED_LEGACY_TAG_COMMIT = "593c173b453236a6872d0a4e88e7a51a67a21cde" class FreshCloneError(RuntimeError): @@ -77,6 +81,50 @@ def _digest(value: str) -> str: return hashlib.sha256(value.encode("utf-8")).hexdigest() +def validate_legacy_tag(*, object_type: str, tag_object: str, tag_commit: str) -> None: + if object_type != "tag": + raise FreshCloneError(f"{LEGACY_MIGRATION_TAG} is not an annotated tag") + if tag_object != EXPECTED_LEGACY_TAG_OBJECT: + raise FreshCloneError( + f"{LEGACY_MIGRATION_TAG} tag object does not match the frozen release" + ) + if tag_commit != EXPECTED_LEGACY_TAG_COMMIT: + raise FreshCloneError(f"{LEGACY_MIGRATION_TAG} commit does not match the frozen release") + + +def obtain_legacy_tag( + clone: Path, +) -> tuple[subprocess.CompletedProcess[str], str, str]: + fetch = _run( + [ + "git", + "fetch", + "--no-tags", + "origin", + f"{LEGACY_MIGRATION_TAG_REF}:{LEGACY_MIGRATION_TAG_REF}", + ], + cwd=clone, + ) + object_type = _run( + ["git", "cat-file", "-t", LEGACY_MIGRATION_TAG_REF], + cwd=clone, + ).stdout.strip() + tag_object = _run( + ["git", "rev-parse", LEGACY_MIGRATION_TAG_REF], + cwd=clone, + ).stdout.strip() + tag_commit = _run( + ["git", "rev-parse", f"{LEGACY_MIGRATION_TAG_REF}^{{commit}}"], + cwd=clone, + ).stdout.strip() + validate_legacy_tag( + object_type=object_type, + tag_object=tag_object, + tag_commit=tag_commit, + ) + return fetch, tag_object, tag_commit + + def run_fresh_clone_gate(commit: str) -> dict[str, object]: """Clone the public successor anonymously and run its complete release gate.""" @@ -95,6 +143,7 @@ def run_fresh_clone_gate(commit: str) -> dict[str, object]: checked_out = _run(["git", "rev-parse", "HEAD"], cwd=clone).stdout.strip() if checked_out != commit: raise FreshCloneError("Anonymous clone did not check out the requested commit") + tag_fetch, tag_object, tag_commit = obtain_legacy_tag(clone) fsck = _run(["git", "fsck", "--full"], cwd=clone) environment = dict(os.environ) environment["UV_LINK_MODE"] = "copy" @@ -111,15 +160,21 @@ def run_fresh_clone_gate(commit: str) -> dict[str, object]: ).stdout.strip() elapsed_ms = round((time.perf_counter_ns() - started) / 1_000_000, 3) return { - "schema_version": 1, + "schema_version": 2, "repository": PUBLIC_REPOSITORY, "authentication": "anonymous_https", "commit": commit, + "legacy_migration_tag": { + "name": LEGACY_MIGRATION_TAG, + "annotated_tag_object": tag_object, + "commit": tag_commit, + }, "clean_after_gate": True, "version_surface": version, "elapsed_ms": elapsed_ms, "logs": { "clone_sha256": _digest(clone_result.stdout + clone_result.stderr), + "legacy_tag_fetch_sha256": _digest(tag_fetch.stdout + tag_fetch.stderr), "fsck_sha256": _digest(fsck.stdout + fsck.stderr), "sync_sha256": _digest(sync.stdout + sync.stderr), "npm_sha256": _digest(npm.stdout + npm.stderr),