From 97b4c0ec7eab7c1a845bba3e66366b3e9ab3ba1c Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sat, 3 Oct 2026 16:07:46 +0100 Subject: [PATCH] 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. --- .github/workflows/renovate-autoupdate.yaml | 31 ++++++++++++++++------ README.md | 11 +++++--- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/renovate-autoupdate.yaml b/.github/workflows/renovate-autoupdate.yaml index ec30ae8..3b802ac 100644 --- a/.github/workflows/renovate-autoupdate.yaml +++ b/.github/workflows/renovate-autoupdate.yaml @@ -58,10 +58,15 @@ on: type: string default: "chore(deps): update dependencies" 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 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: description: "Enable Git LFS checkout (for repos with large files)" required: false @@ -141,7 +146,7 @@ jobs: uses: renovatebot/github-action@v46.3.6 with: 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 }} env: LOG_LEVEL: info @@ -149,7 +154,7 @@ jobs: - name: Find the batch PR id: find-pr env: - GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} + GH_TOKEN: ${{ github.token }} run: | number=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$BATCH_BRANCH" --state open --json number --jq '.[0].number // empty') echo "pr-number=$number" >> "$GITHUB_OUTPUT" @@ -175,7 +180,7 @@ jobs: uses: actions/checkout@v6 with: ref: ${{ env.BATCH_BRANCH }} - token: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} + token: ${{ github.token }} lfs: ${{ inputs.lfs }} - name: Record the tested commit @@ -288,7 +293,7 @@ jobs: - name: Report the failure on the PR if: failure() env: - GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} + GH_TOKEN: ${{ github.token }} PR: ${{ needs.renovate.outputs.pr-number }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} 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')) }} timeout-minutes: 10 permissions: + actions: write contents: write pull-requests: write steps: - name: Squash-merge the PR env: - # A PAT or App token makes the merge push trigger the release workflow. github.token does not. - GH_TOKEN: ${{ secrets.RENOVATE_TOKEN || secrets.HOMEBREW_TAP_TOKEN || github.token }} + # A push made with github.token does not trigger workflows, so the release is dispatched below. + GH_TOKEN: ${{ github.token }} PR: ${{ needs.renovate.outputs.pr-number }} HEAD_SHA: ${{ needs.test.outputs.head-sha }} SUBJECT: ${{ inputs.commit-subject }} @@ -320,3 +326,12 @@ jobs: --subject "$SUBJECT" \ --body "Automated dependency update. All tests passed." \ ${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" diff --git a/README.md b/README.md index 6c58e7a..250ed88 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ on: - cron: "0 3 * * *" permissions: + actions: write # only to dispatch release-workflow contents: write pull-requests: write @@ -125,7 +126,7 @@ jobs: uses: lukaszraczylo/shared-actions/.github/workflows/renovate-autoupdate.yaml@main with: 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. @@ -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 | | `renovate-version` | `44` | Renovate version | | `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 | | `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`. -**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.