From 8785ca3e98d771b07d20c9fd189fdfeac525629c Mon Sep 17 00:00:00 2001 From: JohnnyVicious Date: Sun, 12 Apr 2026 16:04:40 +0200 Subject: [PATCH] fix(release): use a one-shot PR instead of pushing the bump to main directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release run 24308400583 failed because the previous workflow tried to `git push origin HEAD:main` and was rejected by the branch protection rule "Changes must be made through a pull request" (GH013): remote: error: GH013: Repository rule violations found for refs/heads/main. remote: - Changes must be made through a pull request. The bump commit and tag never reached origin (the worker's filesystem is gone), so there's nothing to clean up. This change replaces the direct-push step with a PR-mediated flow that satisfies the branch protection rule: 1. `Push the bump on a release branch` — checkout `release/v${version}`, commit the bumped manifests, push the branch. 2. `Open the release PR and merge it` — `gh pr create` against main with a descriptive title/body, then `gh pr merge --squash --delete-branch`. The change reaches main *through* a PR, which is what the rule wants, while the workflow remains fully automated. 3. `Tag the merged commit on main` — fetch + reset --hard origin/main to pick up the squash-merge commit, tag it, push the tag. 4. `Create GitHub release` — unchanged, still uses `gh release create --generate-notes`. Permissions: added `pull-requests: write` so the workflow can open and merge the release PR. `contents: write` is still needed for the tag push. Header comment updated to document the new flow. --- .github/workflows/release.yml | 50 ++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 264536d..df17a68 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,16 @@ name: Release # Manually-triggered release workflow. -# Runs `npm run bump-version ` to update every manifest, commits -# the bump on `main`, tags it, pushes, and creates a GitHub release with -# auto-generated notes assembled from PRs since the previous tag. +# Runs `npm run bump-version ` to update every manifest, then +# opens a one-shot release PR (because main is protected and rejects +# direct pushes — see GH013), squash-merges it, tags the merged commit, +# pushes the tag, and creates a GitHub release with auto-generated notes +# assembled from PRs since the previous tag. # # Usage: GitHub web UI → Actions → "Release" → "Run workflow" → enter the -# new semver (e.g. `1.0.1`). +# new semver (e.g. `1.0.1`). Or via CLI: +# +# gh workflow run release.yml -f version=1.0.1 on: workflow_dispatch: @@ -17,7 +21,8 @@ on: type: string permissions: - contents: write # commit + tag + release + contents: write # tag + release + pull-requests: write # open + merge the release PR (main is protected) jobs: release: @@ -77,14 +82,45 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - name: Commit, tag, and push + - name: Push the bump on a release branch run: | set -euo pipefail version="${{ inputs.version }}" + branch="release/v${version}" + git checkout -b "$branch" git add package.json package-lock.json plugins/opencode/.claude-plugin/plugin.json .claude-plugin/marketplace.json git commit -m "chore(release): v${version}" + git push origin "$branch" + + - name: Open the release PR and merge it + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + version="${{ inputs.version }}" + branch="release/v${version}" + # Direct pushes to main are blocked by the "Changes must be made + # through a pull request" branch protection rule, so the release + # workflow opens a one-shot PR and immediately squash-merges it. + # This still satisfies the rule (the change goes via a PR) while + # keeping the workflow fully automated. + pr_url=$(gh pr create \ + --base main \ + --head "$branch" \ + --title "chore(release): v${version}" \ + --body "Automated release PR generated by \`.github/workflows/release.yml\`. Bumps every version-bearing manifest to v${version}.") + echo "Created release PR: $pr_url" + gh pr merge "$pr_url" --squash --delete-branch + + - name: Tag the merged commit on main + run: | + set -euo pipefail + version="${{ inputs.version }}" + # Pick up the squash-merge commit that gh pr merge just created. + git fetch origin main + git checkout main + git reset --hard origin/main git tag -a "v${version}" -m "Release v${version}" - git push origin HEAD:main git push origin "v${version}" - name: Create GitHub release