From 6780212370b146b05152ae5b806eeaee3cbffd25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Tue, 28 Apr 2026 12:54:21 +0200 Subject: [PATCH] Automatically unlock main branch after release publishes Adds a final step in the changeset-release job that flips the lockBranch field on the main branch protection rule back to false once a release publishes successfully. The pre-release lock is still applied manually; only the unlock is automated for now. The step requires a RELEASE_ADMIN_TOKEN secret (PAT or GitHub App installation token with admin permissions on branch protection). If the secret is not configured, the step warns and skips so it never blocks a release. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4695f9652a4..273b262ea85 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -170,6 +170,41 @@ jobs: --latest=legacy echo "Created release $TAG" + - name: Unlock main branch + if: steps.changesets.outputs.hasChangesets == 'false' && github.ref_name == 'main' + env: + ADMIN_TOKEN: ${{ secrets.RELEASE_ADMIN_TOKEN }} + run: | + set -euo pipefail + if [ -z "${ADMIN_TOKEN:-}" ]; then + echo "::warning::RELEASE_ADMIN_TOKEN not configured; skipping main branch unlock" + exit 0 + fi + + RULE_ID=$(GITHUB_TOKEN="$ADMIN_TOKEN" gh api graphql \ + -f query='query($owner: String!, $repo: String!) { + repository(owner: $owner, name: $repo) { + branchProtectionRules(first: 50) { nodes { id pattern } } + } + }' \ + -F owner="${GITHUB_REPOSITORY%/*}" \ + -F repo="${GITHUB_REPOSITORY#*/}" \ + --jq '.data.repository.branchProtectionRules.nodes[] | select(.pattern == "main") | .id') + + if [ -z "$RULE_ID" ]; then + echo "::warning::No branch protection rule found for main; skipping unlock" + exit 0 + fi + + GITHUB_TOKEN="$ADMIN_TOKEN" gh api graphql \ + -f query='mutation($id: ID!) { + updateBranchProtectionRule(input: { branchProtectionRuleId: $id, lockBranch: false }) { + branchProtectionRule { lockBranch } + } + }' \ + -f id="$RULE_ID" >/dev/null + echo "Unlocked main branch" + # Manual/Cron release job - runs on schedule or manual trigger with tag manual-cron-release: name: Manual & Cron Release