fix(autoupdate): run the Renovate workflow with the workflow token only

The workflow runs inside the calling repository, so its own token is
enough and no PAT is needed. Drop the PAT fallbacks and make admin merge
opt-in, because the workflow token cannot bypass branch protection.
A merge made with that token does not trigger push workflows, so add a
release-workflow input that dispatches the release after the merge.
This commit is contained in:
2026-10-03 16:07:46 +01:00
parent 413f9c3064
commit 97b4c0ec7e
2 changed files with 31 additions and 11 deletions
+23 -8
View File
@@ -58,10 +58,15 @@ on:
type: string type: string
default: "chore(deps): update dependencies" default: "chore(deps): update dependencies"
admin-merge: admin-merge:
description: "Merge with --admin, which bypasses branch protection" description: "Merge with --admin, which bypasses branch protection. The workflow token cannot do this, so leave it off unless you pass a token that can."
required: false required: false
type: boolean type: boolean
default: true default: false
release-workflow:
description: "Workflow file to dispatch after the merge, for example release.yaml. It must have a workflow_dispatch trigger and the caller needs actions: write. Empty means no dispatch."
required: false
type: string
default: ""
lfs: lfs:
description: "Enable Git LFS checkout (for repos with large files)" description: "Enable Git LFS checkout (for repos with large files)"
required: false required: false
@@ -141,7 +146,7 @@ jobs:
uses: renovatebot/[email protected] uses: renovatebot/[email protected]
with: with:
configurationFile: ${{ runner.temp }}/renovate-autoupdate-config.json configurationFile: ${{ runner.temp }}/renovate-autoupdate-config.json
token: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} token: ${{ github.token }}
renovate-version: ${{ inputs.renovate-version }} renovate-version: ${{ inputs.renovate-version }}
env: env:
LOG_LEVEL: info LOG_LEVEL: info
@@ -149,7 +154,7 @@ jobs:
- name: Find the batch PR - name: Find the batch PR
id: find-pr id: find-pr
env: env:
GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
number=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$BATCH_BRANCH" --state open --json number --jq '.[0].number // empty') number=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$BATCH_BRANCH" --state open --json number --jq '.[0].number // empty')
echo "pr-number=$number" >> "$GITHUB_OUTPUT" echo "pr-number=$number" >> "$GITHUB_OUTPUT"
@@ -175,7 +180,7 @@ jobs:
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
ref: ${{ env.BATCH_BRANCH }} ref: ${{ env.BATCH_BRANCH }}
token: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} token: ${{ github.token }}
lfs: ${{ inputs.lfs }} lfs: ${{ inputs.lfs }}
- name: Record the tested commit - name: Record the tested commit
@@ -288,7 +293,7 @@ jobs:
- name: Report the failure on the PR - name: Report the failure on the PR
if: failure() if: failure()
env: env:
GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} GH_TOKEN: ${{ github.token }}
PR: ${{ needs.renovate.outputs.pr-number }} PR: ${{ needs.renovate.outputs.pr-number }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: | run: |
@@ -302,13 +307,14 @@ jobs:
runs-on: ${{ fromJSON(startsWith(inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest', '{') && (inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest') || format('"{0}"', inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest')) }} runs-on: ${{ fromJSON(startsWith(inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest', '{') && (inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest') || format('"{0}"', inputs.runner || vars.SHARED_ACTIONS_RUNNER || 'ubuntu-latest')) }}
timeout-minutes: 10 timeout-minutes: 10
permissions: permissions:
actions: write
contents: write contents: write
pull-requests: write pull-requests: write
steps: steps:
- name: Squash-merge the PR - name: Squash-merge the PR
env: env:
# A PAT or App token makes the merge push trigger the release workflow. github.token does not. # A push made with github.token does not trigger workflows, so the release is dispatched below.
GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} GH_TOKEN: ${{ github.token }}
PR: ${{ needs.renovate.outputs.pr-number }} PR: ${{ needs.renovate.outputs.pr-number }}
HEAD_SHA: ${{ needs.test.outputs.head-sha }} HEAD_SHA: ${{ needs.test.outputs.head-sha }}
SUBJECT: ${{ inputs.commit-subject }} SUBJECT: ${{ inputs.commit-subject }}
@@ -320,3 +326,12 @@ jobs:
--subject "$SUBJECT" \ --subject "$SUBJECT" \
--body "Automated dependency update. All tests passed." \ --body "Automated dependency update. All tests passed." \
${ADMIN:+--admin} ${ADMIN:+--admin}
- name: Dispatch the release workflow
if: inputs.release-workflow != ''
env:
GH_TOKEN: ${{ github.token }}
RELEASE_WORKFLOW: ${{ inputs.release-workflow }}
run: |
branch=$(gh api "repos/$GITHUB_REPOSITORY" --jq .default_branch)
gh workflow run "$RELEASE_WORKFLOW" --repo "$GITHUB_REPOSITORY" --ref "$branch"
+8 -3
View File
@@ -117,6 +117,7 @@ on:
- cron: "0 3 * * *" - cron: "0 3 * * *"
permissions: permissions:
actions: write # only to dispatch release-workflow
contents: write contents: write
pull-requests: write pull-requests: write
@@ -125,7 +126,7 @@ jobs:
uses: lukaszraczylo/shared-actions/.github/workflows/renovate-autoupdate.yaml@main uses: lukaszraczylo/shared-actions/.github/workflows/renovate-autoupdate.yaml@main
with: with:
go-version: ">=1.24" go-version: ">=1.24"
secrets: inherit release-workflow: release.yaml
``` ```
The workflow finds `go.mod` and `package.json` itself and tests what exists. A repo with both, such as a Go backend with a Vue frontend, gets both tested in one run. The workflow finds `go.mod` and `package.json` itself and tests what exists. A repo with both, such as a Go backend with a Vue frontend, gets both tested in one run.
@@ -143,7 +144,8 @@ The workflow finds `go.mod` and `package.json` itself and tests what exists. A r
| `minimum-release-age` | `2 days` | Skip releases younger than this | | `minimum-release-age` | `2 days` | Skip releases younger than this |
| `renovate-version` | `44` | Renovate version | | `renovate-version` | `44` | Renovate version |
| `commit-subject` | `chore(deps): update dependencies` | Squash commit subject | | `commit-subject` | `chore(deps): update dependencies` | Squash commit subject |
| `admin-merge` | `true` | Merge with `--admin` | | `release-workflow` | | Workflow file to dispatch after the merge, for example `release.yaml`. It needs a `workflow_dispatch` trigger. Empty means no dispatch. |
| `admin-merge` | `false` | Merge with `--admin`. The workflow token cannot bypass branch protection. |
| `lfs` | `false` | Git LFS checkout | | `lfs` | `false` | Git LFS checkout |
| `runner` | | Runner label or runner group, as in the other workflows | | `runner` | | Runner label or runner group, as in the other workflows |
@@ -160,7 +162,10 @@ The workflow finds `go.mod` and `package.json` itself and tests what exists. A r
The defaults already cap `typescript` below 7, which breaks `vue-tsc`. The defaults already cap `typescript` below 7, which breaks `vue-tsc`.
**Token.** The workflow uses `RENOVATE_TOKEN`, then `HOMEBREW_TAP_TOKEN`, then `github.token`. With `github.token` the merge push does not trigger other workflows, so a release workflow on `push` will not run. Use a PAT or App token for repositories that release on push. **Token.** No secret is needed. Everything runs inside the calling repository with the workflow's own token, which needs `contents: write` and `pull-requests: write`. Two repository settings matter:
- Settings, Actions, General: tick "Allow GitHub Actions to create and approve pull requests". Without it Renovate cannot open the PR.
- A push made with the workflow token does not trigger other workflows, so a release workflow that runs on `push` will not start after the merge. Set `release-workflow` to dispatch it explicitly, and grant `actions: write`.
**Commit message.** The squash commit uses a fixed subject and body without the words `major`, `minor` or `breaking`, because `semver-generator` matches release keywords in commit messages. **Commit message.** The squash commit uses a fixed subject and body without the words `major`, `minor` or `breaking`, because `semver-generator` matches release keywords in commit messages.