diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5c5cc5..0676a27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: ci on: push: - branches: [dev] + branches: [dev, main] pull_request: - branches: [dev] + branches: [dev, main] permissions: contents: read diff --git a/Makefile b/Makefile index cdfab81..a1494af 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ test-scripts: ## Run focused safety tests for operator-facing shell harnesses bash tests/scripts/m0_ocm_falsification_safety_test.sh bash tests/scripts/release_tag_identity_guide_test.sh bash tests/scripts/release_tag_policy_test.sh + bash tests/scripts/release_pr_gate_policy_test.sh perf: ## Enforce the warm-cache TUI p95 latency budget without race overhead go test -count=1 -run '^TestWarmViewP95UnderOneHundredMilliseconds$$' ./internal/tui diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 737a747..f98f9b2 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -110,9 +110,10 @@ slice is not a claim of the parent feature's future in-chart database, HA, or cl ## Maintainer release procedure 1. Merge the feature PR into `dev`, ensure the full CI and release-snapshot jobs are green, then - merge a reviewed `dev` to `main` release PR. `dev` is the durable integration source: never use - `--delete-branch` for this release PR. Automatic branch deletion is reserved for merged feature - branches. + open a `dev` to `main` release PR. The same full CI and release-snapshot jobs must be green on + that release PR before merging it, and the exact `main` push run must pass afterward. `dev` is + the durable integration source: never use `--delete-branch` for this release PR. Automatic + branch deletion is reserved for merged feature branches. 2. From an up-to-date `main`, run `make ci` and `make release-check`. The latter compares archive SHA-256 digests across two complete builds; SBOM creation timestamps and Sigstore signatures are intentionally not expected to be byte-for-byte reproducible. diff --git a/sessions/2026-07-14-e9-release-pr-ci-gate.md b/sessions/2026-07-14-e9-release-pr-ci-gate.md new file mode 100644 index 0000000..7bb65a8 --- /dev/null +++ b/sessions/2026-07-14-e9-release-pr-ci-gate.md @@ -0,0 +1,47 @@ +# E9 release-PR CI gate — 2026-07-14 + +Issue: #157 +Branch: `gnanirahulnutakki/ci/release-pr-gate` +Base: `origin/dev` at `42d395135b034bcfb531b5657f3eb01b95ea7bb5` + +## [G] Goal + +Require the complete Sith CI workflow for `dev` to `main` release PRs and for the exact resulting +`main` push, so a release boundary has independent build, reproducibility, security, and real +two-cluster evidence. + +## [S] Scope and safety + +- The change expands only the existing CI branch trigger allowlist from `dev` to `dev, main`. +- No job, pin, credential, artifact, release tag, or branch-protection policy is weakened or + removed. +- The maintainer guide requires green release-PR CI and exact post-merge `main` CI before tagging. + +## [A] Evidence + +- The hermetic release-PR policy test confirms CI listens to both push and pull-request events for + `dev` and `main`, and that the guide requires release-PR CI. +- Existing beta-tag policy test remains green. +- Final-diff `make ci` passed formatting, vet, lint, reachable-vulnerability scan, full Go race + suite, all shell policy tests, performance, subprocess E2E, and build. +- Final-diff `make release-check` passed two reproducible four-platform snapshots, archive/SBOM + verification, formula rendering, and digest comparison. +- Manual red-team review confirmed that the only workflow delta is adding `main` to the existing + `push` and `pull_request` branch allowlists. Existing jobs, permissions, pinned actions/tools, + concurrency, and `dev` coverage are unchanged. +- CodeRabbit accepted the uncommitted diff and reached analysis but returned no review in the + bounded attempt; it is not recorded as approval. Hosted PR CI, exact post-merge `dev` CI, and + proof that release PR #156 runs its own full CI after this lands remain pending. + +## [T] Test plan + +1. Run `make ci` and `make release-check` on the final diff. +2. Review that no trigger or workflow permission broadening was introduced and that all existing + job gates remain unchanged. +3. Land only after green PR CI and exact post-merge `dev` CI, then observe a new full CI run on + #156 before promoting `main`. + +## [C] Completion criteria + +#157 closes only after the resulting `dev` to `main` release PR has an independently green full CI +run and a later exact `main` push CI record is available for the beta release commit. diff --git a/tests/scripts/release_pr_gate_policy_test.sh b/tests/scripts/release_pr_gate_policy_test.sh new file mode 100755 index 0000000..56d91df --- /dev/null +++ b/tests/scripts/release_pr_gate_policy_test.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +workflow="${repo_root}/.github/workflows/ci.yml" +guide="${repo_root}/docs/RELEASE.md" + +if ! awk ' + /^ push:/ { section = "push"; next } + /^ pull_request:/ { section = "pull_request"; next } + /^ [A-Za-z_]/ { section = "" } + section == "push" && /branches: \[dev, main\]/ { push_ok = 1 } + section == "pull_request" && /branches: \[dev, main\]/ { pull_request_ok = 1 } + END { exit !(push_ok && pull_request_ok) } +' "${workflow}"; then + printf '[release-pr-gate] FAIL: ci must run on dev and main pushes and pull requests\n' >&2 + exit 1 +fi +printf '[release-pr-gate] PASS: ci runs on dev and main pushes and pull requests\n' + +if ! grep -Fq 'release PR before merging it' "${guide}"; then + printf '[release-pr-gate] FAIL: release guide does not require release-PR CI\n' >&2 + exit 1 +fi +printf '[release-pr-gate] PASS: release guide requires release-PR CI\n'