Skip to content

bug(release): the changelog PR the release step opens is held for workflow approval as an external contributor — automation opens what automation cannot merge #17728

Open

Description

@mrveiss

The changelog PR the release step opens cannot pass its required checks without a human approving its workflows

release.yml's "Open changelog PR to release" step now works (#15167 closed today on run 36438754248, v0.10.0). The PR it opened — #17723, changelog-v0.10.0 → release, authored by github-actions[bot] — spawned 18 workflow runs, every one action_required, including both checks release requires:

No Commit Trailers      action_required
PR Blocking Findings    action_required

The repository's fork-PR approval policy is all_external_contributors, and the repository's own Actions bot is not a member, so its PR is held for approval exactly as an unknown fork would be. The automation produces an artifact the automation cannot finish. Until a maintainer clicks "Approve and run" (or calls POST /actions/runs/{id}/approve), the changelog never reaches release, which is the outcome #15167 existed to fix — moved one step downstream.

Today it was cleared by approving the two required runs by hand. That is a per-release manual step, not a fix.

Why this was invisible until now

The step had never succeeded before today, so no bot-authored PR toward release had ever existed to be held. #15167's own acceptance criterion — the step opens the PR and exits 0 — is met and correctly closed; the PR's mergeability was never in its scope.

What this is not

Not a GITHUB_TOKEN limitation — workflows did trigger (18 runs), they were held, not suppressed. Not a permissions gap on the token — the PR was created. It is the approval policy applied to an actor it was not written for.

Acceptance criteria

  • A changelog PR opened by release.yml reaches a mergeable state without a manual workflow approval — by whichever of these the owner chooses: the approval policy narrowed so the repository's own bot is not "external"; or the step opening the PR under an identity the policy already trusts; or release's required checks satisfied for that PR by a path that does not need approval. Record which, and why, in RELEASE_WORKFLOW.md.
  • RELEASE_WORKFLOW.md's "verify after a promotion" list gains the check that the changelog PR's required runs actually ran — action_required is a fourth state beside pass/fail/pending, and a reader who does not know to look for it sees a PR that is simply "blocked".
  • release.yml self-triggers on its own changelog commit → spurious release (latent infinite loop once #11853 lands) #11855's loop guard is confirmed on this first live changelog merge: exactly one release.yml run for v0.10.0 after chore(release): changelog for v0.10.0 #17723 lands, none triggered by it.

Refs #15167, #17723, #11855, #17717.

Activity

  1. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    AC3 met on the first live merge: #17723 landed on release at abfeacde49 (paths: CHANGELOG.md, changelog/** only) and release.yml runs remain exactly one for v0.10.0 — 36438754248. No run was triggered by the changelog merge. AC1 and AC2 remain open.

  2. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    Shares a cause with #12823: both are GITHUB_TOKEN attribution. auto-update-pr-branches.yml:133/:355 already carry the ${{ secrets.AUTOBOT_PUSH_TOKEN || secrets.GITHUB_TOKEN }} shape, and release.yml:29-33 runs gh pr create under GITHUB_TOKEN — but no repository-level AUTOBOT_PUSH_TOKEN exists (measured 2026-09-28, names only), so neither path is fixed in practice. One owner decision — provision a dedicated push token as a repository secret (and drop the silent || fallback) — closes both. Raised together in the v0.9-decisions digest. (Read-only finding by 87.)

  3. mrveiss commented on Oct 3, 2026

    @mrveiss
    OwnerAuthor

    Screening: live — and this is not the same defect as the land job's "Actions is not permitted to create or approve pull requests"

    The hypothesis put to me was that this issue, the weekly-durations land failure and #17700 share one repo-setting cause, so one pending flip fixes all three. They do not. There are two adjacent-but-different repository settings here, and a third mechanism that has nothing to do with pull requests.

    The two settings are distinguished by whether a PR exists

    this issue (#17728) the land job failure
    symptom PR #17723 exists, authored by github-actions[bot], with 18 workflow runs, every one action_required "GitHub Actions is not permitted to create or approve pull requests", and no PR has ever existed
    what is blocked the workflows on a created PR the creation of the PR
    the setting fork-PR approval policy, all_external_contributors — the repo's own Actions bot is not a member, so its PR is held like an unknown fork's Allow GitHub Actions to create and approve pull requests

    This issue's own body rules out the other cause, which is why I am confident rather than guessing:

    What this is not — Not a GITHUB_TOKEN limitation — workflows did trigger (18 runs), they were held, not suppressed. Not a permissions gap on the token — the PR was created. It is the approval policy applied to an actor it was not written for.

    So the actionable nuance for the owner: check which flip is being made. Enabling "Allow GitHub Actions to create and approve pull requests" unblocks the land job and does nothing for this one — #17723's workflows stay action_required. Relaxing the fork-PR approval policy (or approving the bot's runs via POST /actions/runs/{id}/approve) unblocks this one and does nothing for land. Two flips, or one flip and a remaining defect.

    They are the same class — automation blocked by a policy written for human external contributors — and that is worth saying on both. They are not one fix.

    #17700 is a third, unrelated mechanism

    It involves no pull request and no approval policy. .github/workflows/canonical-audit.yml runs four Python commands bare under the run: block's default bash -e, and tools/lint/canonical_check.py:108 is return 1 if blocking else 0 with sys.exit(main()) at :112 — so the tool exits 1 when it finds violations, which kills the step. Detail on that issue; it shares only the appearance of "automation that produces nothing".

    Verdict

    Live. Premise verified against the issue's own evidence; the policy value and the 18 held runs are stated there and the logic is self-consistent. One correction to the framing it was screened under: a shared symptom with two distinct settings plus one unrelated mechanism is the more expensive answer, and worth knowing before anyone treats the owner's pending flip as closing three issues.

    What I did not verify: the repository's current fork-PR approval setting value, which needs admin-visible settings I cannot read. I am taking all_external_contributors from this issue's body. If that value has since changed, this verdict changes with it.

    Nothing filed; research-only session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions