fix(ci): bind backend candidates to exact main dispatch

This commit is contained in:
2026-09-27 10:28:48 -04:00
parent 6ec84f3e4d
commit 99b3a490ea
5 changed files with 95 additions and 14 deletions
+7
View File
@@ -11,6 +11,7 @@ on:
type: string
env:
BUILD_LANE: candidate
CARGO_TERM_COLOR: never
PYTHONDONTWRITEBYTECODE: '1'
EXPECTED_BUILD_SHA: ${{ inputs.expected_sha }}
@@ -29,6 +30,12 @@ jobs:
RUSTUP_HOME: ${{ runner.temp }}/rustup-backend-candidate
CARGO_HOME: ${{ runner.temp }}/cargo-backend-candidate
steps:
- name: Require exact main dispatch before checkout
run: |
test "$GITHUB_EVENT_NAME" = workflow_dispatch || { echo 'Candidate event must be workflow_dispatch.' >&2; exit 1; }
test "$GITHUB_REF" = refs/heads/main || { echo 'Candidate dispatch must select main.' >&2; exit 1; }
[[ "$EXPECTED_BUILD_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo 'Candidate expected_sha must be a full lowercase commit.' >&2; exit 1; }
test "$GITHUB_SHA" = "$EXPECTED_BUILD_SHA" || { echo 'Dispatch main moved from the reviewed expected_sha.' >&2; exit 1; }
- uses: actions/checkout@v4
with:
fetch-depth: 0
+1
View File
@@ -9,6 +9,7 @@ on:
branches: [main]
env:
BUILD_LANE: ci
CARGO_TERM_COLOR: never
PYTHONDONTWRITEBYTECODE: '1'
EXPECTED_BUILD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
+36 -12
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python3
"""Admit one reviewed canonical source or its exact Builds merge wrapper."""
import json
import os
from pathlib import Path
import re
import subprocess
import sys
@@ -11,7 +13,11 @@ class Refusal(ValueError):
def git(*args):
return subprocess.check_output(["git", *args], text=True, stderr=subprocess.PIPE).strip()
try:
return subprocess.check_output(["git", *args], text=True, stderr=subprocess.PIPE).strip()
except subprocess.CalledProcessError as error:
cause = " ".join((error.stderr or "Git returned no diagnostic").split())[:600]
raise Refusal(f"Git evidence failed (exit {error.returncode}): {cause}") from None
def commit(value, label):
@@ -48,16 +54,36 @@ def admit(source, expected_head=None, require_wrapper=False):
return {"source_commit": source, "build_commit": head, "source_tree": tree}
def main():
if os.environ.get("GITHUB_REPOSITORY") != "Builds/smirk-backend-core":
def build_context(environment):
if environment.get("GITHUB_REPOSITORY") != "Builds/smirk-backend-core":
raise Refusal("this workflow is admitted only on Builds/smirk-backend-core")
event = os.environ.get("GITHUB_EVENT_NAME")
expected = os.environ.get("EXPECTED_BUILD_SHA")
if not expected:
raise Refusal("this build requires the exact reviewed event or dispatch head")
if event not in {"push", "pull_request", "workflow_dispatch"}:
raise Refusal("this build event is not admitted")
wrapper = event != "pull_request"
event = environment.get("GITHUB_EVENT_NAME")
lane = environment.get("BUILD_LANE")
expected = commit(environment.get("EXPECTED_BUILD_SHA"), "expected event or dispatch SHA")
if lane == "candidate":
if event != "workflow_dispatch":
raise Refusal("candidate builds require workflow_dispatch")
elif lane == "ci":
if event not in {"push", "pull_request"}:
raise Refusal("fundless CI requires push or pull_request")
else:
raise Refusal("build lane is not admitted")
if event == "pull_request":
try:
payload = json.loads(Path(environment.get("GITHUB_EVENT_PATH", "")).read_text())
head = payload["pull_request"]["head"]["sha"]
base = payload["pull_request"]["base"]["ref"]
except (OSError, ValueError, KeyError, TypeError) as error:
raise Refusal(f"pull-request event evidence is unavailable: {type(error).__name__}") from None
if head != expected or base != "main":
raise Refusal("CI checkout does not match the exact main-targeted pull-request event head")
elif environment.get("GITHUB_REF") != "refs/heads/main" or environment.get("GITHUB_SHA") != expected:
raise Refusal("main event head must equal the reviewed full expected_sha")
return expected, event != "pull_request"
def main():
expected, wrapper = build_context(os.environ)
canonical = source_for_checkout(wrapper)
result = admit(canonical, expected, require_wrapper=wrapper)
print(f"Admitted canonical source {result['source_commit']} at Builds {result['build_commit']}")
@@ -68,5 +94,3 @@ if __name__ == "__main__":
main()
except Refusal as error:
sys.exit(f"Build source refused: {error}")
except subprocess.CalledProcessError:
sys.exit("Build source refused: Git could not resolve the reviewed source or checkout")
+4 -2
View File
@@ -40,8 +40,10 @@ def main():
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
os.chdir(ROOT)
admitted = source.admit(source.source_for_checkout(True),
os.environ.get("EXPECTED_BUILD_SHA", ""), require_wrapper=True)
expected, wrapper = source.build_context(os.environ)
if not wrapper or os.environ.get("BUILD_LANE") != "candidate":
raise source.Refusal("artifact staging requires the admitted candidate dispatch lane")
admitted = source.admit(source.source_for_checkout(True), expected, require_wrapper=True)
binary = ROOT / "target/x86_64-unknown-linux-gnu/release/smirk-backend-core"
required = elf_requirements(binary)
rustc = subprocess.check_output(["rustc", "--version"], text=True).strip()
+47
View File
@@ -101,6 +101,53 @@ class Admission(unittest.TestCase):
source.main()
class EventBoundary(unittest.TestCase):
def setUp(self):
self.head = "a" * 40
self.environment = {"GITHUB_REPOSITORY": "Builds/smirk-backend-core",
"BUILD_LANE": "candidate", "GITHUB_EVENT_NAME": "workflow_dispatch",
"GITHUB_REF": "refs/heads/main", "GITHUB_SHA": self.head,
"EXPECTED_BUILD_SHA": self.head}
def test_exact_dispatch_event_admitted(self):
self.assertEqual(source.build_context(self.environment), (self.head, True))
def test_bad_ref_event_sha_or_malformed_input_refused(self):
for key, value in (("GITHUB_REF", "refs/heads/topic"), ("GITHUB_EVENT_NAME", "push"),
("GITHUB_SHA", "b" * 40), ("EXPECTED_BUILD_SHA", "main"),
("EXPECTED_BUILD_SHA", "a" * 39), ("BUILD_LANE", "unknown")):
with self.subTest(key=key, value=value), self.assertRaises(source.Refusal):
source.build_context({**self.environment, key: value})
def test_push_requires_main_and_exact_event_sha(self):
env = {**self.environment, "BUILD_LANE": "ci", "GITHUB_EVENT_NAME": "push"}
self.assertEqual(source.build_context(env), (self.head, True))
with self.assertRaises(source.Refusal):
source.build_context({**env, "GITHUB_REF": "refs/heads/topic"})
def test_pr_binds_actual_event_head_and_target(self):
import json
with tempfile.TemporaryDirectory() as directory:
event = Path(directory) / "event.json"
event.write_text(json.dumps({"pull_request": {"head": {"sha": self.head}, "base": {"ref": "main"}}}))
env = {**self.environment, "BUILD_LANE": "ci", "GITHUB_EVENT_NAME": "pull_request",
"GITHUB_EVENT_PATH": str(event)}
self.assertEqual(source.build_context(env), (self.head, False))
with self.assertRaises(source.Refusal):
source.build_context({**env, "EXPECTED_BUILD_SHA": "b" * 40})
event.write_text(json.dumps({"pull_request": {"head": {"sha": self.head}, "base": {"ref": "topic"}}}))
with self.assertRaises(source.Refusal):
source.build_context(env)
def test_git_refusal_reports_bounded_underlying_cause(self):
failure = subprocess.CalledProcessError(128, ["git"], stderr="fatal: object unavailable " + "x" * 2000)
with patch.object(subprocess, "check_output", side_effect=failure):
with self.assertRaises(source.Refusal) as caught:
source.git("rev-parse", "HEAD")
self.assertIn("object unavailable", str(caught.exception))
self.assertLess(len(str(caught.exception)), 700)
class BinaryCompatibility(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix="smirk-elf-fixture-")