diff --git a/.github/workflows/bump-dev-version.yml b/.github/workflows/bump-dev-version.yml index a65656b..ebb8cd3 100644 --- a/.github/workflows/bump-dev-version.yml +++ b/.github/workflows/bump-dev-version.yml @@ -38,7 +38,11 @@ on: default on: the diff is always exactly one mechanical line and needs no review. Requires the repo to have Settings -> General -> "Allow auto-merge" enabled, and "Allow GitHub Actions to create and approve - pull requests" for the PR-open step itself. + pull requests" for the PR-open step itself. In a repo with required + status checks it also requires WORKFLOW_TOKEN: a GITHUB_TOKEN-authored + PR does not trigger the pull_request runs those checks need, so + without the token the required checks never report and auto-merge + blocks forever (see the warning step below). type: boolean default: true dry-run: @@ -85,6 +89,34 @@ jobs: old-version: ${{ steps.bump.outputs.old-version }} new-version: ${{ steps.bump.outputs.new-version }} steps: + - name: Warn if auto-merge cannot complete without WORKFLOW_TOKEN + # A GITHUB_TOKEN-authored PR does not trigger `pull_request` workflow + # runs -- GitHub suppresses them to prevent recursion -- so in a repo + # with required status checks those contexts never report, and native + # auto-merge blocks forever (the bump PR sits open on every merge until + # a human intervenes). WORKFLOW_TOKEN (a PAT or App token) authors the + # PR as a real user, whose `pull_request` runs are not suppressed, so + # the required checks report and auto-merge can complete. This warns + # rather than fails because the combination is only unreachable when the + # repo actually has required checks: a repo without them auto-merges + # fine on GITHUB_TOKEN, and failing here would break that legitimate + # config. Runs first, before any work, so the signal is visible up + # front rather than as a PR that silently never merges. + if: ${{ !inputs.dry-run && inputs.auto-merge }} + shell: bash + env: + WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} + run: | + if [ -n "$WORKFLOW_TOKEN" ]; then + exit 0 + fi + msg="auto-merge is enabled but WORKFLOW_TOKEN is not set. In a repo with required status checks, the bump PR is authored by the integrated GITHUB_TOKEN, whose pull_request runs GitHub suppresses -- so the required checks never report and native auto-merge blocks forever (the PR sits open on every merge). Required checks block manual merges too, so turning off auto-merge does not help. Set WORKFLOW_TOKEN (a PAT or App token) so the PR is authored by a real user whose checks run and report." + echo "::warning title=bump-dev-version::$msg" + { + echo "> [!WARNING]" + echo "> $msg" + } >> "$GITHUB_STEP_SUMMARY" + - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/README.md b/README.md index e1a9261..ce4d39f 100644 --- a/README.md +++ b/README.md @@ -150,9 +150,11 @@ that need to write must have the **caller** grant it on the calling job: - `bump-dev-version` (opens/auto-merges a PR) → grant `contents: write`, `pull-requests: write`, and the same "Allow GitHub Actions to create and approve pull requests" setting as above; enable "Allow auto-merge" too for - its default `auto-merge: true`. Add a `WORKFLOW_TOKEN` only to push to a - protected branch. `version-check` (read-only) → only `pull-requests: read`, - `contents: read`. + its default `auto-merge: true`. Add a `WORKFLOW_TOKEN` to push to a protected + branch, and -- when `auto-merge` runs against required status checks -- to let + the bump PR's checks run so it can merge at all (a `GITHUB_TOKEN`-authored PR's + checks never report; see the reference page). `version-check` (read-only) → + only `pull-requests: read`, `contents: read`. The stubs in [`examples/`](examples) already include the right `permissions:` blocks — copy them as-is. diff --git a/changelog.d/bump-dev-version-auto-merge-token-warning.fixed.md b/changelog.d/bump-dev-version-auto-merge-token-warning.fixed.md new file mode 100644 index 0000000..b15fc9b --- /dev/null +++ b/changelog.d/bump-dev-version-auto-merge-token-warning.fixed.md @@ -0,0 +1,10 @@ +- **`bump-dev-version` warns when `auto-merge` cannot complete** (#409). + A `GITHUB_TOKEN`-authored bump PR does not trigger the `pull_request` runs + that required status checks need, so in a repo with required checks native + `auto-merge` waits on conditions that never arrive and the PR sits open on + every merge. + The reusable workflow now emits a `::warning::` at the start of its run when + `auto-merge` is on and `WORKFLOW_TOKEN` is unset, and the caller stub and + reference page document that `WORKFLOW_TOKEN` is effectively required in that + case (it authors the PR as a real user, whose `pull_request` runs are not + suppressed). diff --git a/examples/bump-dev-version.yml b/examples/bump-dev-version.yml index e55ff12..a778156 100644 --- a/examples/bump-dev-version.yml +++ b/examples/bump-dev-version.yml @@ -22,6 +22,17 @@ jobs: # description-path: DESCRIPTION # default # auto-merge: true # default; set false to review by hand secrets: - # Set only if the bot must push to a protected branch; otherwise omit - # and the push falls back to GITHUB_TOKEN. + # A PAT or App token, needed for two independent reasons: + # 1. To push the bump commit when pr-branch is protected by a ruleset + # that blocks the integrated GITHUB_TOKEN. Without it, checkout and + # open-sync-pr fall back to GITHUB_TOKEN (the original reason -- the + # sibling open-sync-pr stubs document only this one). + # 2. To let auto-merge (the default) complete when the repo has required + # status checks. A GITHUB_TOKEN-authored bump PR does not trigger the + # pull_request runs those checks need, so they never report and the + # merge is blocked forever. Authoring the PR with a real user's token + # makes its checks run. Required checks block manual merges too, so + # turning off auto-merge does not avoid this. + # Omit the token only when neither applies: an unprotected pr-branch and + # no required checks. WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} diff --git a/website/permissions.qmd b/website/permissions.qmd index 64fe371..43b81e1 100644 --- a/website/permissions.qmd +++ b/website/permissions.qmd @@ -55,10 +55,14 @@ already include the right `permissions:` blocks; copy them as-is. - **`WORKFLOW_TOKEN`** (a PAT or GitHub App token with `contents:write` + `workflows:write`). The integrated `GITHUB_TOKEN` cannot push changes to files under `.github/workflows/`; GitHub rejects them without the `workflows` scope. - Add this secret if `claude` will edit workflow files, or to push to a - protected branch. Unlike `GITHUB_TOKEN`, a PAT or App-token push **does** - trigger other `push`-based workflows, so enabling it can set off extra CI - runs. + Add this secret if `claude` will edit workflow files, to push to a protected + branch, or -- for `bump-dev-version` with its default `auto-merge` in a repo + with required status checks -- to let the bump PR's checks run so it can merge + (a `GITHUB_TOKEN`-authored PR's `pull_request` checks never report, so the + merge stays blocked; see its + [reference page](reference/bump-dev-version.qmd)). Unlike `GITHUB_TOKEN`, a + PAT or App-token push **does** trigger other `push`-based workflows, so + enabling it can set off extra CI runs. When the secret is absent and `claude` does edit a workflow file, the rejected push is reported as an error naming this secret, and the commits are posted to the thread as a `git format-patch` so they survive the run. diff --git a/website/reference/bump-dev-version.qmd b/website/reference/bump-dev-version.qmd index bc37807..d1514f9 100644 --- a/website/reference/bump-dev-version.qmd +++ b/website/reference/bump-dev-version.qmd @@ -28,14 +28,37 @@ message. | `description-path` | string | `DESCRIPTION` | Path to the DESCRIPTION file to bump. | | `base-branch` | string | `main` | Base branch to open the bump PR against. | | `pr-branch` | string | `automated/bump-dev-version` | Head branch for the automation PR. | -| `auto-merge` | boolean | `true` | Enable GitHub's native auto-merge (squash) on the bump PR. | +| `auto-merge` | boolean | `true` | Enable GitHub's native auto-merge (squash) on the bump PR. In a repo with required status checks, needs `WORKFLOW_TOKEN` (see Secrets). | | `dry-run` | boolean | `false` | Bump but skip opening/merging a PR. Not yet exercised by this repo's own CI (its `dev-version` selftest job calls the `bump-dev-version` composite directly instead of this reusable workflow -- see the bootstrapping-gap note in `CLAUDE.md`); meant for a consumer to smoke-test the bump logic. | ## Secrets -| Secret | Required | Description | -| ---------------- | -------- | -------------------------------------------------------------- | -| `WORKFLOW_TOKEN` | no | PAT or App token; needed only to push to a protected branch. | +| Secret | Required | Description | +| ---------------- | ------------- | -------------------------------------------------------------- | +| `WORKFLOW_TOKEN` | conditional | PAT or App token. Needed to push the bump commit when `pr-branch` is protected, and to let `auto-merge` complete when the repo has required status checks (it authors the PR as a real user, so its checks run). Optional when neither applies. | + +`WORKFLOW_TOKEN` covers two independent needs. +First, the checkout and `open-sync-pr` push steps use it to push the bump +commit; without it they fall back to the integrated `GITHUB_TOKEN`, which +cannot push to a `pr-branch` a ruleset protects. +This is the reason the sibling `open-sync-pr` stubs +([`bump-submodule`](bump-submodule.qmd), +[`sync-shared-fragments`](sync-shared-fragments.qmd), +[`sync-upstream`](sync-upstream.qmd)) document, and it still applies here. +Second, it lets `auto-merge` complete in a repo with required status checks. +GitHub does not trigger `pull_request` workflow runs for a +`GITHUB_TOKEN`-authored PR (it suppresses them to prevent recursive runs), so +those required checks never report and the merge is blocked forever -- the PR +sits open on every merge. +Required checks block manual merges too, so turning off `auto-merge` does not +avoid this; the genuine fixes are to set `WORKFLOW_TOKEN` (so the PR is authored +by a real user whose checks run), force-merge with branch-protection bypass +rights, or re-trigger the checks with a real-user event (a manual push to the +bump branch, or closing and reopening the PR). +The reusable workflow emits a warning at the start of its run when `auto-merge` +is on and `WORKFLOW_TOKEN` is missing. +Omit the token only when `pr-branch` is unprotected and the repo has no required +checks. ## Outputs