Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions .github/workflows/automerge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ on:
- ready_for_review

permissions:
contents: write
pull-requests: write
contents: read
pull-requests: read

jobs:
automerge:
name: Enable auto-merge for eligible Dependabot PRs
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
# Both the PR author and the run actor must be Dependabot. A human pushing a
# fixup to a Dependabot branch (or reopening / re-running) is a human-actor
# run: it reads the Actions secret store, where AUTOMERGE_APP_PRIVATE_KEY
# (a Dependabot secret) is absent, so the token step would fail. Skip instead.
if: ${{ github.actor == 'dependabot[bot]' && github.event.pull_request.user.login == 'dependabot[bot]' }}

steps:
- name: Fetch Dependabot metadata
Expand All @@ -27,10 +31,40 @@ jobs:
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Enable auto-merge
# Enable auto-merge as the froefam-automerge GitHub App, not GITHUB_TOKEN:
# a merge pushed by GITHUB_TOKEN does not trigger main.yml (GitHub's
# workflow-recursion guard), so auto-merged PRs never get a release. See #122.
- name: Generate app token
id: app-token
if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }}
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
Comment thread
drache42 marked this conversation as resolved.
with:
client-id: ${{ vars.AUTOMERGE_APP_CLIENT_ID }}
private-key: ${{ secrets.AUTOMERGE_APP_PRIVATE_KEY }}
# Least privilege: mint only what `gh pr merge --auto` needs, rather
# than inheriting every permission the installation holds.
permission-contents: write
Comment thread
drache42 marked this conversation as resolved.
Comment thread
drache42 marked this conversation as resolved.
permission-pull-requests: write

- name: Enable auto-merge
# Runs only for eligible updates - the token step above is skipped otherwise.
if: ${{ steps.app-token.outcome == 'success' }}
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: gh pr merge --auto --merge "$env:PR_URL"
run: gh pr merge --auto --merge "$env:PR_URL"

- name: Explain failure
if: ${{ failure() }}
Comment thread
drache42 marked this conversation as resolved.
shell: pwsh
run: |
@(
'### Dependabot auto-merge did not complete'
''
'A step in this job failed, so auto-merge was not enabled; the PR can still be'
'merged manually. If the failure is in **Generate app token**, check that the'
'`AUTOMERGE_APP_PRIVATE_KEY` Dependabot secret is valid and the `froefam-automerge`'
'GitHub App is still installed on this repository with Contents and Pull requests'
'write access.'
) | Add-Content -Path $env:GITHUB_STEP_SUMMARY
6 changes: 6 additions & 0 deletions docs/CI-CD.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Dependabot auto-merge is defined in `.github/workflows/automerge.yml`.
- Trigger: Dependabot pull requests targeting `main`
- Eligible updates: semver patch and semver minor updates
- Merge mode: GitHub auto-merge using the normal PR merge flow
- Merge identity: auto-merge is enabled with a token from the `froefam-automerge` GitHub App, not `GITHUB_TOKEN`. A merge that `GITHUB_TOKEN` pushes does not start another workflow run, so `main.yml` (and therefore `compute-version` / `auto-release`) would never fire for an auto-merged PR. The App identity makes the merge behave like a human merge and the release pipeline runs. See issue #122.
- Safety gate: branch protection and required checks still apply, so the pull request does not merge until all required status checks pass
- Major updates: never auto-merge

Expand Down Expand Up @@ -109,19 +110,22 @@ Enable these repository settings:

1. Configure a branch ruleset targeting `main` with `label-gate` as a required status check
2. Enable auto-merge in the repository settings so Dependabot PRs can enter GitHub's built-in auto-merge flow
3. Create a GitHub App (`froefam-automerge`) with **Contents: read and write** and **Pull requests: read and write**, install it on this repository, and record its Client ID in `AUTOMERGE_APP_CLIENT_ID` and its private key in the `AUTOMERGE_APP_PRIVATE_KEY` Dependabot secret (see the tables below)

### Secrets

| Secret | Required | Purpose |
| --- | --- | --- |
| `ANTHROPIC_API_KEY` | Yes | Enables `classify-pr.yml` to call the Anthropic API for automatic PR classification. Without this, classification fails and `semver: unknown` is applied. |
| `DISCORD_WEBHOOK_URL` | No | Discord webhook URL for pipeline failure, release, and Dependabot breaking-change notifications. |
| `AUTOMERGE_APP_PRIVATE_KEY` | Yes, for auto-merge | Private key for the `froefam-automerge` GitHub App, used by `automerge.yml` to mint the token that enables auto-merge. Must be stored as a **Dependabot** secret (Settings → Secrets and variables → Dependabot) — `automerge.yml` is triggered by Dependabot, and Dependabot-triggered runs only read secrets from that store. |

### Repository variables

| Variable | Required | Purpose |
| --- | --- | --- |
| `ANTHROPIC_MODEL` | Yes | The Anthropic model ID used by `classify-pr.yml` (e.g. `claude-haiku-4-5`). Update this variable to switch models without modifying workflow files. |
| `AUTOMERGE_APP_CLIENT_ID` | Yes, for auto-merge | Client ID of the `froefam-automerge` GitHub App, passed to `actions/create-github-app-token` in `automerge.yml`. Not secret; a plain Actions variable is fine (also readable from Dependabot-triggered runs). |

No separate registry secret is required for `ghcr.io` publishing. The workflows use `GITHUB_TOKEN` with `packages: write` permission.

Expand Down Expand Up @@ -168,6 +172,8 @@ Use `act` for iteration and a draft PR for final verification.

Dependabot auto-merge is implemented by enabling GitHub's built-in auto-merge on eligible PRs. It does not bypass branch protection.

Auto-merge is enabled using a short-lived token minted from the `froefam-automerge` GitHub App (`actions/create-github-app-token`), so the eventual merge is attributed to the App rather than `github-actions[bot]`. This is required for the post-merge `main.yml` run — GitHub does not start a workflow from a `push` made with the default `GITHUB_TOKEN`.

To override it:

1. Open the Dependabot PR in GitHub
Expand Down
Loading