Skip to content

ci(maintenance): auto-merge Dependabot dev dependency updates - #5568

Open
svozza wants to merge 1 commit into
mainfrom
chore/dependabot-auto-merge
Open

ci(maintenance): auto-merge Dependabot dev dependency updates#5568
svozza wants to merge 1 commit into
mainfrom
chore/dependabot-auto-merge

Conversation

@svozza

@svozza svozza commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Dependabot opens daily pull requests that maintainers approve by hand, and because main uses strict status checks with dismiss_stale_reviews, every merge invalidates the others and restarts the cycle. This automates approval and merge for the narrow slice where review adds little — non-major bumps of direct npm development dependencies — and leaves everything else for a human.

Rehearsed end to end on a private staging fork against live Dependabot pull requests, including the negative cases.

Changes

  • Add .github/workflows/dependabot-auto-merge.yml, triggered on pull_request (never pull_request_target), with permissions: {} at workflow level. It never checks out or executes pull request code
  • Require three independent gates before an approval is issued: the pull request was opened by dependabot[bot] and is not from a fork, the update is an npm direct:development non-major bump, and every commit on the branch is authored by dependabot[bot] with a valid GitHub signature
  • Read commits from the API rather than the event payload, so a commit pushed after the run starts is still caught
  • Withdraw this workflow's own approval and its own auto-merge whenever a run does not itself approve. This is not defensive tidying — see below
  • Pin dependabot/fetch-metadata to 25dd0e34f4fe68f24cc83900b1fe3fe149efef98 (v3.1.0)

Why the withdrawal step exists

An approval and an armed auto-merge outlive the run that granted them, and GitHub does not dismiss reviews when a branch is updated from its base — the diff is unchanged, so the approval survives. In rehearsal this let a pull request merge after it stopped qualifying: the workflow approved a clean head, "Update branch" then added a merge commit authored by a human, the commit gate correctly went red, and the pull request merged anyway because nothing revoked the earlier approval. The squashed result on main looked like an ordinary signed Dependabot commit.

dependabot/fetch-metadata also verifies only commits[0] and reads that commit's message for all metadata, so on a branch carrying extra history it can report the wrong dependency entirely. The all-commits gate is what makes its output trustworthy.

Rollout order

This job's auto-merge context must be a required status check, otherwise a red gate blocks nothing. Safe for human pull requests: the job is skipped for them and reports skipped, which GitHub counts as satisfied.

  1. Merge ci(maintenance): add aggregate unit-test check for branch protection #5567
  2. Add run-unit-tests / unit-tests-complete and dependency-review to the required status checks for main
  3. Mark this ready and merge it
  4. Once auto-merge has reported on any pull request, add it to the required status checks. Not before this pull request merges — until the workflow is on main the context never reports, and every unrelated pull request would sit blocked waiting for it
  5. Only then set allow_auto_merge: true on the repository

Keeping allow_auto_merge disabled until step 5 is the interlock: nothing can auto-merge while the gate is unenforced. Between steps 3 and 5, an in-scope Dependabot pull request will be approved and then have that approval withdrawn when arming fails, leaving a red auto-merge check. Harmless, and it stops as soon as step 5 is done.

Scope caveat worth knowing

Dependabot derives dependency-type from npm's production tree in package-lock.json, not from which section of package.json declares a dependency. typescript, @types/node and esbuild therefore report direct:production and will not auto-merge — typescript because valibot, a production dependency, declares an optional peer dependency on it. Grouped updates do auto-merge when the group is dev-only and non-major, which is worth knowing given the typescript and vitest groups in dependabot.yml.

Issue number: closes #5491


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

Closes the approve-and-merge toil for the narrow slice where review adds
little: non-major bumps of direct npm development dependencies. Everything
else is left untouched for a human.

Three gates must agree before an approval is issued: the PR was opened by
dependabot[bot] and is not from a fork, the update is an npm
direct:development non-major bump, and every commit on the branch is
authored by dependabot[bot] with a valid GitHub signature. The commit gate
reads commits from the API rather than the event payload, so a commit
pushed after the run starts is still caught.

Two details are load-bearing and easy to get wrong:

- fetch-metadata only verifies commits[0] and reads that commit's message
  for all metadata, so on a branch carrying extra history it can describe
  the wrong dependency entirely. The all-commits gate is what makes its
  output trustworthy.
- An approval and an armed auto-merge outlive the run that granted them,
  and GitHub does not dismiss reviews when a branch is updated from its
  base. Without the withdrawal step, a PR that passed the gates once can
  merge after a later push fails them. This was reproduced in rehearsal:
  clicking "Update branch" landed a human-authored merge commit on main
  with the gate red, and the squashed result looked like a clean signed
  Dependabot commit.

The withdrawal step only ever touches this workflow's own approvals and
the auto-merge it enabled itself, never a maintainer's.

This job's `auto-merge` context must be added to the required status checks
for the withdrawal step to be backed by enforcement.
@svozza
svozza force-pushed the chore/dependabot-auto-merge branch from 56bc64c to 9706bce Compare August 19, 2026 12:27
@svozza
svozza marked this pull request as ready for review August 19, 2026 12:33
@svozza svozza removed the do-not-merge This item should not be merged label Aug 19, 2026
@svozza
svozza requested a review from dreamorosi August 19, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L PRs between 100-499 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Maintenance: enable auto-merge for Dependabot dev-dependency PRs

1 participant