From c9a77d1dd279db42efa24d8ef108a41e36fe5a92 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 13 Jul 2026 17:03:51 +0100 Subject: [PATCH] fix: make immutable release gate executable Keep the administrator-only repository setting check in the dispatcher contract and retain the workflow-token-readable postpublication immutable assertion. Signed-off-by: Your Name --- .github/workflows/policy-release.yml | 7 ------- docs/policy-release-and-upgrades.md | 2 +- tests/test_policy_release.py | 3 +++ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/policy-release.yml b/.github/workflows/policy-release.yml index d6f8d91..2a0d4f0 100644 --- a/.github/workflows/policy-release.yml +++ b/.github/workflows/policy-release.yml @@ -45,13 +45,6 @@ jobs: with: ref: ${{ github.ref }} - - name: Require repository immutable-release enforcement - env: - GH_TOKEN: ${{ github.token }} - run: | - enabled="$(gh api "repos/${GITHUB_REPOSITORY}/immutable-releases" --jq '.enabled')" - [[ "$enabled" == "true" ]] || { echo "Immutable releases must be enabled before publication." >&2; exit 1; } - - name: Enforce upgrade gate and release evidence env: GH_TOKEN: ${{ github.token }} diff --git a/docs/policy-release-and-upgrades.md b/docs/policy-release-and-upgrades.md index e1d978b..81393c4 100644 --- a/docs/policy-release-and-upgrades.md +++ b/docs/policy-release-and-upgrades.md @@ -27,6 +27,6 @@ The standalone published verifier runs without a repository checkout: python3 verify_policy_release.py --output . --verify-only ``` -Publish by enabling GitHub immutable releases, creating an exact tag, and dispatching `Publish Policy Release` against that tag with the governing issue and previous version. Minor releases require the number of an approved, merged PR whose merge commit is the tagged commit and whose approval is from a non-author reviewer. Major releases also require existing repository-relative ADR and migration-guide files at that commit. The workflow confirms the previous release, derives and enforces the upgrade gate, runs the full policy suite, notifies the issue and repository-dispatch channel, refuses overwrite, publishes all assets, downloads them into a clean directory, runs the standalone verifier, verifies GitHub reports the release immutable, and records postpublication evidence. GitHub's repository endpoint is the authoritative preflight check for immutable-release enforcement. [GitHub REST API](https://docs.github.com/en/rest/repos/repos#check-if-immutable-releases-are-enabled-for-a-repository) +Publish by enabling GitHub immutable releases, verifying that setting with an administrator-capable token, creating an exact tag, and dispatching `Publish Policy Release` against that tag with the governing issue and previous version. Minor releases require the number of an approved, merged PR whose merge commit is the tagged commit and whose approval is from a non-author reviewer. Major releases also require existing repository-relative ADR and migration-guide files at that commit. The workflow confirms the previous release, derives and enforces the upgrade gate, runs the full policy suite, notifies the issue and repository-dispatch channel, refuses overwrite, publishes all assets, downloads them into a clean directory, runs the standalone verifier, verifies GitHub reports the release immutable, and records postpublication evidence. GitHub's repository endpoint is the authoritative preflight check, but it requires repository Administration permission and therefore cannot be queried by the workflow's built-in `GITHUB_TOKEN`; the dispatcher must perform that check before creating the tag. [GitHub REST API](https://docs.github.com/en/rest/repos/repos#check-if-immutable-releases-are-enabled-for-a-repository) Release publication is a material action. Notify through the governing release issue and configured mechanism, then continue when gates pass unless a defined human hard stop applies. diff --git a/tests/test_policy_release.py b/tests/test_policy_release.py index cdd1b5f..58d690f 100644 --- a/tests/test_policy_release.py +++ b/tests/test_policy_release.py @@ -97,6 +97,9 @@ def test_malformed_manifests_fail_deterministically(self) -> None: def test_publication_workflow_authenticates_release_evidence(self) -> None: workflow = (ROOT / ".github" / "workflows" / "policy-release.yml").read_text() self.assertIn("pull-requests: read", workflow) + self.assertNotIn('repos/${GITHUB_REPOSITORY}/immutable-releases', workflow) + self.assertIn("releases/tags/${TAG}", workflow) + self.assertIn('[[ "$immutable" == "true" ]]', workflow) self.assertIn('gh pr view "$REVIEW" --json author,mergeCommit,reviewDecision,state', workflow) self.assertIn('.mergeCommit.oid', workflow) self.assertIn('.user.login != $author', workflow)