diff --git a/.github/workflows/main-source-guard.yml b/.github/workflows/main-source-guard.yml deleted file mode 100644 index 4eb5d20f..00000000 --- a/.github/workflows/main-source-guard.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Main source guard - -# Make the job "only-release-into-main" a required status check on main. -on: - pull_request: - branches: [main] - types: [opened, reopened, synchronize, edited] - -permissions: - contents: read - -jobs: - only-release-into-main: - runs-on: ubuntu-latest - steps: - - name: Require head branch "release" - env: - HEAD_REF: ${{ github.head_ref }} - HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} - run: | - if [ "$HEAD_REF" != "release" ] || [ "$HEAD_REPO" != "${{ github.repository }}" ]; then - echo "::error::PRs into main must come from the release branch of this repository (got '$HEAD_REPO:$HEAD_REF')." - exit 1 - fi diff --git a/.github/workflows/release-sync.yml b/.github/workflows/release-sync.yml index d411bb2e..746a0b9d 100644 --- a/.github/workflows/release-sync.yml +++ b/.github/workflows/release-sync.yml @@ -10,7 +10,6 @@ on: permissions: contents: write pull-requests: write - statuses: write concurrency: group: release-sync @@ -51,17 +50,3 @@ jobs: else gh pr create --head release --base main --title "$title" --body "$body" fi - - # A PR opened with GITHUB_TOKEN triggers no workflows, so main-source-guard - # never runs on it. Report the guard's verdict for the release commit here: - # this job just generated it from develop, which is exactly what the guard - # requires. A status set with GITHUB_TOKEN satisfies a required check. - - name: Mark release as passing the main source guard - env: - GH_TOKEN: ${{ github.token }} - run: | - set -eu - if ! git rev-parse -q --verify refs/heads/release >/dev/null; then exit 0; fi - gh api "repos/${GITHUB_REPOSITORY}/statuses/$(git rev-parse release)" \ - -f state=success -f context=only-release-into-main \ - -f description="generated from develop ${GITHUB_SHA::7} by release-sync" diff --git a/tools/release/README.md b/tools/release/README.md index b3243cab..37abf63b 100644 --- a/tools/release/README.md +++ b/tools/release/README.md @@ -14,13 +14,12 @@ ignored and overwritten. The push uses `--force-with-lease` pinned to the remote sha the run observed. 2. The workflow opens (or updates) a pull request `release` -> `main` with the default `GITHUB_TOKEN`. This needs the repository setting *Actions -> General -> Allow GitHub - Actions to create and approve pull requests*. A PR opened with `GITHUB_TOKEN` - triggers no workflows, so `main-source-guard` would never run on it; the workflow - therefore sets the `only-release-into-main` commit status on the release commit - itself, which satisfies the required check. No PAT is needed; an optional + Actions to create and approve pull requests*. No PAT is needed; an optional `RELEASE_PR_TOKEN` secret is used for the PR step when present. -3. Merging that PR is the only way to change `main`. `main-source-guard.yml` fails - any PR into `main` whose head is not `release`. +3. Merging that PR is the only way to change `main`. Branch protection (below) makes `main` + PR-only and lets only administrators merge; the maintainer merges the `release` PR and + checks that its head is `release` (maintainer decision 2026-10-03: no source-branch + workflow, settings only). 4. On push to `main`, `pages.yml` deploys `docs/guide/` to GitHub Pages. ## What is dropped on release @@ -46,6 +45,5 @@ It refuses to run while `release` is checked out. tools/release/protect-main.sh # print what would be applied tools/release/protect-main.sh --apply # apply via gh api (needs admin) -This requires a pull request, blocks force-push and deletion. Classic protection cannot -restrict a PR's source branch, so add the check `only-release-into-main` as required -(the script does; the workflow must have run once first). +This requires a pull request (no approving review needed), blocks direct push, force-push and +deletion, leaves the branch unlocked, and restricts merging to administrators. diff --git a/tools/release/protect-main.sh b/tools/release/protect-main.sh index 5d3588f9..4bc6514d 100755 --- a/tools/release/protect-main.sh +++ b/tools/release/protect-main.sh @@ -14,12 +14,13 @@ done [ -n "$REPO" ] || REPO="{owner}/{repo}" # gh expands these placeholders from the current repo BODY='{ - "required_status_checks": {"strict": true, "contexts": ["only-release-into-main"]}, - "enforce_admins": true, + "required_status_checks": null, + "enforce_admins": false, "required_pull_request_reviews": {"required_approving_review_count": 0}, - "restrictions": null, + "restrictions": {"users": [], "teams": [], "apps": []}, "allow_force_pushes": false, - "allow_deletions": false + "allow_deletions": false, + "lock_branch": false }' CMD="gh api --method PUT repos/$REPO/branches/$BRANCH/protection --input -" @@ -29,6 +30,6 @@ if [ "$APPLY" -eq 1 ]; then else echo "[dry run] would run: $CMD" echo "$BODY" - echo "Re-run with --apply to apply. The check 'only-release-into-main' comes from .github/workflows/main-source-guard.yml;" - echo "it must have run once before GitHub accepts it as a required check." + echo "Re-run with --apply to apply (needs admin). 'restrictions' with empty lists means only" + echo "administrators may merge; it is accepted for organisation repositories only." fi