Release-token gate
When GitHub Actions opens a pull request using the workflow's default github.token or secrets.GITHUB_TOKEN, GitHub does not emit new workflow trigger events for that pull request. A release pull request opened by release-please under the default workflow token therefore sits without required status checks, unable to trigger CI verification.
The release-token gate fails any workflow step invoking release-please that does not source its token from a dedicated GitHub App token step. The gate is adopt.AuditReleaseToken in internal/adopt/release_token_audit.go over the measurement in internal/forge/release_token.go. Both praetorctl audit and the MCP tool standards_audit run it.
Quick start
Passing shape
Mint a GitHub App installation token in an earlier step of the same job, and pass its output token to release-please:
jobs:
release:
runs-on: ubuntu-26.04
steps:
- name: Mint the release token
id: app-token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- uses: googleapis/release-please-action@v4
with:
token: ${{ steps.app-token.outputs.token }}
Exceptions
If a repository cannot immediately adopt a GitHub App token, declare an entry in .standards.yaml under exceptions:. The gate enforces category C (a fixed 10-day rectification interval):
exceptions:
- rule: "release-token"
path: ".github/workflows/release.yml"
category: "C"
entered: "2026-10-18"
expires: "2026-10-28"
reason: "GitHub App creation underway; awaiting organization administrator approval"
The entry excuses every release-please step in the named workflow. A live entry passes and prints the workflow findings with its reason and expiry. An expired entry fails like a missing one. An entry naming a workflow with no findings is stale and fails until removed.
What the gate reads
Every workflow document under .github/workflows is parsed and checked:
- Release-please step identification. Any step whose
uses:starts withgoogleapis/release-please-action@orgoogle-github-actions/release-please-action@is evaluated. - Token expression.
with.tokenmust be exactly one${{ steps.<id>.outputs.token }}expression (whitespace inside braces allowed). It must not contain||fallbacks or surrounding text. Default tokens (${{ github.token }}or${{ secrets.GITHUB_TOKEN }}) are refused. - App token step placement. An earlier step in the same job must declare
id: <id>anduses:starting withactions/create-github-app-token@. Referencing a step in another job or a later step in the same job is refused. - Unconditional execution. The app-token step must have no
if:condition and nocontinue-on-error:. A skipped or forgiven token step yields an empty token, causingrelease-pleaseto silently fall back togithub.token. - Secret and App identifiers. The app-token step's
with.private-keymust be a single${{ secrets.<NAME> }}expression. The step must also setclient-idorapp-idto a non-empty value. - Skip condition. A repository with no
release-pleasestep skips the gate with a[SKIP]report.
Reading the output
A failure names each workflow, job, step, and line where known:
[FAIL] Release token: .github/workflows/release.yml:14: job release, step "release-please": takes the workflow token (github.token or secrets.GITHUB_TOKEN), which starts no checks on its release pull request.
[FAIL] Release token: no live exceptions entry declares the steps above; give each a token from an actions/create-github-app-token step (docs/guides/release-token.md), or, for a step that cannot yet, declare its workflow in the exceptions list of .standards.yaml (rule release-token, path .github/workflows/<workflow>, category C, a reason, and an expiry at most 10 days ahead).
A pass reports the evaluated steps:
[PASS] Release token: 1 release-please step takes token from a GitHub App token step.
Read from the workflow files under .github/workflows; no release pull request was checked on the forge.
When no workflow invokes release-please, the gate skips: