"""Repository contracts for immutable CI execution dependencies.""" from __future__ import annotations import re from pathlib import Path ROOT = Path(__file__).parents[1] WORKFLOW = ROOT / ".github" / "workflows" / "ci.yml" MANIFEST = ROOT / "ci" / "digests.txt" ACTION_REF = re.compile( r"^\s*uses:\s*([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+)@([0-9a-f]{40})\s+#\s+(\S+)\s*$", ) def _manifest_entries() -> dict[tuple[str, str], tuple[str, str]]: entries: dict[tuple[str, str], tuple[str, str]] = {} for line in MANIFEST.read_text(encoding="utf-8").splitlines(): if not line or line.startswith("#"): continue kind, name, pin, version, _date, _rationale = line.split(maxsplit=5) entries[(kind, name)] = (pin, version) return entries def test_every_external_action_is_sha_pinned_and_manifested(): entries = _manifest_entries() uses_lines = [ line for line in WORKFLOW.read_text(encoding="utf-8").splitlines() if "uses:" in line and "uses: ./" not in line ] assert uses_lines for line in uses_lines: match = ACTION_REF.match(line) assert match is not None, f"external action is not SHA-pinned with a version comment: {line}" name, pin, version = match.groups() assert entries[("action", name)] == (pin, version) def test_actionlint_version_and_checksum_match_manifest(): workflow = WORKFLOW.read_text(encoding="utf-8") pin, version = _manifest_entries()[("tool", "rhysd/actionlint")] assert f'ACTIONLINT_VERSION: "{version.removeprefix("v")}"' in workflow assert f'ACTIONLINT_SHA256: "{pin.removeprefix("sha256:")}"' in workflow def test_uv_and_gitleaks_pins_match_manifest(): workflow = WORKFLOW.read_text(encoding="utf-8") entries = _manifest_entries() uv_pin, uv_version = entries[("tool", "astral-sh/uv")] gitleaks_pin, gitleaks_version = entries[("tool", "gitleaks/gitleaks")] assert uv_pin == f"pypi:{uv_version.removeprefix('v')}" assert f'UV_VERSION: "{uv_version.removeprefix("v")}"' in workflow assert f'GITLEAKS_VERSION: "{gitleaks_version.removeprefix("v")}"' in workflow assert f'GITLEAKS_SHA256: "{gitleaks_pin.removeprefix("sha256:")}"' in workflow def test_ci_requires_the_committed_lock_and_strict_policy_gate(): workflow = WORKFLOW.read_text(encoding="utf-8") assert "uv lock --check" in workflow assert "uv sync --locked" in workflow assert "scripts/check_supply_chain_policy.py audit" in workflow assert "scripts/check_supply_chain_policy.py secrets" in workflow assert "scripts/check_supply_chain_policy.py licenses" in workflow supply_chain_job = workflow.split(" supply-chain:\n", maxsplit=1)[1] assert "|| true" not in supply_chain_job