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
45 changes: 45 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: dependabot-auto-merge
# Auto-merges low-risk Dependabot PRs once the required CI checks pass.
# Native auto-merge waits for the branch-protection checks on main (test +
# docker), so a bump only lands if the workflows still go green. Scope:
# - github-actions: all updates (CI-only, low blast radius).
# - npm / docker: minor + patch only — major bumps stay manual for review.
#
# Majors are excluded on purpose, and recent history shows why: the TypeScript
# 5.9 -> 7.0 bump broke the build outright (TS7016), and the Node 24 -> 25
# base-image bump was declined for being a non-LTS release. Both needed a human.
#
# Merges with --merge rather than --squash to match this repo's history.
#
# NB: package-ecosystem is Dependabot's internal identifier, not the friendly
# name from dependabot.yml — npm reports as `npm_and_yarn` and Actions as
# `github_actions` (they match the dependabot/<ecosystem>/ branch prefix). A
# literal `== 'npm'` would silently never match, which is exactly the trap the
# sibling random-mcp-server repo fell into: it tests `== 'pip'` while the real
# output there is `uv`, so its Python bumps never auto-merge. Hence startsWith.
on: pull_request

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Fetch Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v3

- name: Enable auto-merge for in-scope updates
if: >-
startsWith(steps.metadata.outputs.package-ecosystem, 'github')
|| ( (steps.metadata.outputs.package-ecosystem == 'docker'
|| startsWith(steps.metadata.outputs.package-ecosystem, 'npm'))
&& (steps.metadata.outputs.update-type == 'version-update:semver-minor'
|| steps.metadata.outputs.update-type == 'version-update:semver-patch') )
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9 changes: 9 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ Run `gh issue list` for the current state.
github-actions. `@types/*` and other minor/patch npm bumps are **grouped**
into single PRs; majors stay individual so each gets its own review. Security
updates are independent of this file and arrive regardless.
- **Low-risk Dependabot PRs auto-merge** via
`.github/workflows/dependabot-auto-merge.yml`: all github-actions updates,
plus npm/docker **minor and patch**. Majors always stay manual — the
TypeScript 5.9 → 7.0 bump broke the build and the Node 24 → 25 base image was
declined, and both needed a human. This relies on branch protection: `main`
requires the `test` and `docker` checks, which is what native auto-merge
waits for. Without required checks, auto-merge would land PRs *without* CI
gating them. `enforce_admins` is off, so direct version-bump pushes to `main`
still work.
- **Transitive CVEs are pinned via `overrides`,** not by adding direct
dependencies — see the `overrides` block in `package.json` (`js-yaml`, `qs`,
`brace-expansion`). When a follow-up advisory lands for something already
Expand Down