Skip to main content
友田 陽大
Dependabot & dependency automation
Dependabot
GitHub Actions
CI/CD
DevSecOps
自動化
セキュリティ

Dependabot auto-merge × GitHub Actions automation guide: safely auto-merging only patch/minor with fetch-metadata

An implementation guide to safely auto-merging Dependabot PRs with GitHub Actions. Faithful to the official documentation (as of June 2026), it explains, with copy-paste real code: all outputs of dependabot/fetch-metadata@v3, conditional branching by update-type, gh pr merge --auto, the token model of a read-only GITHUB_TOKEN and Dependabot secrets, using pull_request vs. pull_request_target, and how to build safety valves with required checks and branch protection.

Published
Reading time
9 min read
Author
友田 陽大
Share

Once you bring in Dependabot, the next thing you'll surely want is auto-merge. Manually merging an @types/node patch every time is a waste of time — but auto-merging anything is an accident that pushes breaking changes into production unattended. The right answer is the division of labor: "auto-merge only the things with a low probability of breaking (patch/minor), conditioned on passing CI, and have a human review major."

This article, as a topic of the Dependabot production-operations guide, explains safe auto-merge with GitHub Actions at the implementation level. Since there are many security pitfalls here, it handles the token model and event triggers especially carefully.

Rules for this article: action names, outputs, and token behavior are based on the GitHub official documentation and the dependabot/fetch-metadata README (as of June 2026). Since auto-merge directly connects to security, always confirm the latest in the official automation guide before production. Don't hardcode secrets other than GITHUB_TOKEN in the workflow.


1. The big picture: auto-merge is a "reservation"

GitHub's auto-merge isn't "merge now" but a reservation to "merge when all required checks turn green." So even with auto-merge enabled, if tests fail it isn't merged. This property is the core of safety.

Dependabot がPRを開く
   └─▶ ワークフロー起動(actor が dependabot[bot] か検査)
          └─▶ fetch-metadata で update-type 等を取得
                 └─▶ patch/minor なら gh pr merge --auto を実行(=予約)
                        └─▶ 必須チェック(テスト/型/lint/ビルド)が green
                               └─▶ 自動マージ ✅   (赤なら止まる ⛔)

As a premise, enable "Allow auto-merge" in the repository settings (Settings → General → Pull Requests).


2. The minimal implementation: auto-merge patch/minor

First, a working minimal form. The points are to trigger on the pull_request event and explicitly declare write permissions on the workflow side.

# .github/workflows/dependabot-auto-merge.yml
name: Dependabot auto-merge
on: pull_request

permissions:
  contents: write          # マージに必要
  pull-requests: write     # PR操作に必要

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    # Dependabot 以外のPRでは何もしない(必須のガード)
    if: github.actor == 'dependabot[bot]'
    steps:
      - name: Fetch Dependabot metadata
        id: meta
        uses: dependabot/fetch-metadata@v3
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"

      - name: Enable auto-merge for patch & minor
        if: |
          steps.meta.outputs.update-type == 'version-update:semver-patch' ||
          steps.meta.outputs.update-type == 'version-update:semver-minor'
        run: gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Three key points:

  1. if: github.actor == 'dependabot[bot]' — a guard that doesn't run on non-Dependabot PRs. Omitting this is dangerous as it reacts to third-party PRs too.
  2. Explicit permissions: — the GITHUB_TOKEN of a pull_request workflow triggered by Dependabot is read-only by default. Explicitly grant contents: write and pull-requests: write for auto-merge (below).
  3. Conditional branching on update-type — only version-update:semver-patch / semver-minor. Major (semver-major) is intentionally excluded and routed to a human.

3. The token model: this is the heart of security

Most accidents in auto-merge are insufficient understanding of tokens. Grasp the official behavior accurately.

  • The GITHUB_TOKEN of a pull_request workflow triggered by Dependabot is read-only by default. And it can't access normal Actions secrets. This is a design to prevent a compromised dependency from stealing secrets via CI.
  • If you need writes, declare permissions: within the workflow and elevate only the necessary scope (for Dependabot's pull_request event, the permissions declared in the workflow are respected).
  • If the workflow needs secrets (e.g., a test accessing a private resource), put them in the Dependabot secret store (Settings → Secrets and variables → Dependabot). It's separate from Actions secrets.

Mnemonic: "CI that runs on a Dependabot PR starts read-only & with no secrets." So auto-merge needs an explicit permissions, and secrets go in the Dependabot-dedicated store. Miss these two and you stall on "no permission" or "the secret is empty."

3.1 pull_request or pull_request_target

The dependabot/fetch-metadata README also has an example using pull_request_target, but the safe default is pull_request. The reason:

  • pull_request_target runs with a token that can read/write in the base repository's context. Here, checking out and running the PR's code (= including the updated dependency) with actions/checkout creates a path for a compromised dependency to touch a write-permissioned token or secrets.
  • On the other hand, only metadata retrieval + gh pr merge --auto (= an operation that doesn't run code) can sufficiently achieve the goal with pull_request + explicit permissions, and is safer.

Conclusion: use pull_request for auto-merge that doesn't involve building or arbitrary code execution. If you absolutely need pull_request_target, don't check out and run the PR's head, and use it with an understanding of the trust boundary.

When using a merge queue: you can't add a PR to the queue with the built-in GITHUB_TOKEN. You need to authenticate the workflow with a PAT or a GitHub App token (official note).


4. Build a "delicate policy" with all fetch-metadata outputs

dependabot/fetch-metadata@v3 has 14 outputs. Using them, you can build a more delicate auto-merge policy than "patch/minor only."

OutputUse example
update-typeGranularity judgment with version-update:semver-patch/minor/major
dependency-typedirect:production / direct:development / indirect
dependency-namesLimit to specific packages (e.g., rails)
dependency-groupBranch on whether it's a group PR (groups setting)
package-ecosystemPer-ecosystem policy (github-actions auto, etc.)
directoryPer-directory policy for monorepos
previous-version / new-versionLog/judge by version diff
compatibility-scoreThreshold judgment by compatibility score
alert-state / ghsa-id / cvssTreat security updates separately
maintainer-changesRoute to human review if there's a maintainer change
target-branchPer-target-branch policy
updated-dependencies-jsonRaw data for machine processing

4.1 Practical example: dev dependencies up to minor, production dependencies patch only

      - name: Auto-merge policy
        # 開発依存は patch/minor を自動、本番の direct 依存は patch のみ自動
        if: |
          (steps.meta.outputs.dependency-type == 'direct:development' &&
            (steps.meta.outputs.update-type == 'version-update:semver-patch' ||
             steps.meta.outputs.update-type == 'version-update:semver-minor')) ||
          (steps.meta.outputs.dependency-type == 'direct:production' &&
            steps.meta.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 }}

Design philosophy: the closer to production, the more cautious. direct:production minor goes to human review, and direct:development (test/build tools) is loosened a bit more — "automation proportional to risk."

4.2 Always have a human look at a maintainer change

      - name: Flag maintainer changes for human review
        if: steps.meta.outputs.maintainer-changes == 'true'
        run: gh pr comment "$PR_URL" --body "⚠️ メンテナ変更あり。サプライチェーン観点で人間レビュー必須。"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

A maintainer change can be a sign of a dependency hijack. Looking at maintainer-changes, excluding it from auto-merge and putting human eyes on it is a cheap and effective defense.


5. Build safety valves: required checks × branch protection

Auto-merge is "merge if green." In other words, "what you make the green condition" is the safety itself. Auto-merge without a safety valve is just Russian roulette.

5.1 Run real CI even on Dependabot PRs

# .github/workflows/ci.yml(Dependabot PR でも走る通常CI)
name: CI
on: pull_request

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "npm"
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test
      - run: npm run build

Note: this CI installs and runs the updated dependency with npm ci. Dependabot CI running on pull_request has a read-only token and no secrets, so even if a malicious dependency sneaks in, the damage is minimized. Designing so that integration tests needing secrets don't run on Dependabot PRs is more robust.

5.2 Make it required with branch protection

In main's branch protection (or Rulesets), set the following:

  • Require lint / typecheck / test / build in Require status checks to pass before merging.
  • Require branches to be up to date before merging (optional, in consultation with rebase-strategy).
  • With this, gh pr merge --auto won't merge until all required checks turn green = the safety valve works.

"Before bringing in auto-merge, first prepare trustworthy required checks" — don't reverse the order.


6. Combining with group PRs and cooldown

The groups / cooldown you built in the complete configuration guide mesh cleanly with auto-merge.

  • Bundle patch/minor into one PR with groups → auto-merge that group PR: the review target shrinks to just "major and substantive updates." You can judge a group PR with the dependency-group output.
  • Let fresh versions age with cooldown → auto-merge what comes out after aging: lower the regression risk before automatically incorporating.
      - name: Auto-merge grouped patch/minor PRs
        if: |
          steps.meta.outputs.dependency-group != '' &&
          steps.meta.outputs.update-type != 'version-update:semver-major'
        run: gh pr merge --auto --squash "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

(Choose per your operation, such as --squash to fold a group PR's history into one commit.)


7. Antipattern collection

  • No if: github.actor guard → reacts to third-party PRs. Always include the required guard.
  • Auto-merge major too → breaking changes to production unattended. patch/minor-limited is the iron rule.
  • Auto-merge with no required checks → no safety valve. A set with branch protection.
  • Check out & run PR code with pull_request_target → a path for a write token/secrets to touch a malicious dependency. If no code execution, pull_request.
  • Depend on Actions secrets → Dependabot CI can't touch them. Use the Dependabot secret store.
  • write-all for permissions globally → a least-privilege violation. Narrow to just contents / pull-requests.

8. FAQ

Q. I enabled auto-merge but it doesn't merge. A. --auto merges "when required checks turn green." It doesn't proceed if checks are pending/failing, or if "Allow auto-merge" or branch-protection required checks aren't set.

Q. I get a Resource not accessible by integration error. A. Dependabot's pull_request workflow is read-only by default. Explicitly declare permissions: { contents: write, pull-requests: write } in the workflow.

Q. I'd like to auto everything including major. A. Not recommended. It's not worth the risk of incorporating breaking changes unattended. Exclude major with fetch-metadata's update-type and route it to human review.

Q. I use a merge queue. A. Since you can't add to the queue with the built-in GITHUB_TOKEN, authenticate the workflow with a PAT or a GitHub App token.

Q. Is it OK to auto-merge security updates too? A. If CI (especially tests) is sufficient, auto-merging patch security updates is highly effective. But also consider a policy of looking at alert-state / cvss and having a human confirm the critical ones. For the big picture of vulnerability response, go to the alerts/security-updates guide.

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Dependency auto-updates & supply-chain defense, from design to production

From enabling alerts/security/version updates, to dependabot.yml design (groups, cooldown, monorepo directories, private registries), safe auto-merge via GitHub Actions + fetch-metadata (auto for patch/minor, human review for major), severity-based-SLA vulnerability response, and observability of the open count. With experience wiring dependency updates into CI quality gates, I implement automation that doesn't flood you with PRs or pile up technical debt.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading