🤖

Dependabot PR のセキュリティリスクを Claude Code Action に判定させて自動でマージする

に公開

TL;DR

前回の記事で紹介した Dependabot PR のマルチエージェントレビューを発展させ、レビュー結果に基づいて PR を自動マージする仕組みを構築しました。Claude がレビュー基準に応じて auto-merge-approved ラベルを付与し、別ワークフローがそれを検知してマージする仕組みです。
本記事の最後にソースコードも貼っています。

はじめに

前回の記事では、Dependabot が作成する PR を Claude Code Action の 3 つの専門エージェントで並列レビューする仕組みを紹介しました。レビューの自動化には成功しましたが、最終的なマージ操作は人間が行う必要がありました。

レビュー結果を見ると、パッチ/マイナーバージョンのアップデートでは「即座にマージ可能」という判定がほとんどです。それなら、この判定結果に基づいて自動マージまで完結させれば、人間の作業をさらに削減できます。

この記事では、Claude のレビュー結果に基づく自動マージの仕組みと、その実装過程で遭遇した問題について紹介します。

アーキテクチャの全体像

前回からの変更点を含めた全体フローです。

前回の記事で紹介した「Dependabot PR → GitHub App 経由のコメント投稿 → Claude Code Action によるマルチエージェントレビュー」の流れはそのままに、レビュー後の自動マージ判定とラベルベースのマージワークフローを追加しています。

実装ステップ

1. レビューコマンドに自動マージ判定を追加

前回作成した /review-dependabot-pr コマンドに、ステップ 5 として自動マージの判定ロジックを追加しました。

Claude が 3 つのサブエージェントのレビュー結果を統合した後、以下の条件を全て満たす場合に自動マージ対象と判定します。

# 条件 判定元
1 マイナーまたはパッチバージョンアップデートである dependabot-version-analyzer
2 セキュリティ的に問題がない dependabot-security-analyzer
3 即座にマージ可能と判定されている dependabot-impact-analyzer

条件を満たす場合、Claude は gh pr editauto-merge-approved ラベルを付与します。

gh pr edit {PR_NUMBER} --repo {REPO} --add-label "auto-merge-approved"

レビューコメントの末尾にも、自動マージ判定セクションが追加されます。

自動マージ対象の場合

自動マージ対象

パッチ/マイナーバージョンアップデートであり、セキュリティ上の問題がなく、Breaking Changes の影響もないため、auto-merge-approved ラベルを付与しました。CI が全て通過した後、自動的にマージされます。

自動マージ対象外の場合

自動マージ対象外

以下の理由により自動マージの対象外です。人間のレビューをお願いします。

  • メジャーバージョンアップデート (8.x → 9.x)
  • Breaking Changes がプロジェクトに直接影響

ここで重要なのは、Claude に直接 gh pr merge を実行させていない点です。Claude のワークフローに contents: write 権限を追加する必要がなく、ラベルの付与 (pull-requests: write) だけで完結します。

2. ラベルベースの自動マージワークフロー

ラベルの付与をトリガーに、別のワークフローが PR を承認・マージします。

auto_merge_dependabot_pr.yml
name: Auto Merge Dependabot PR

on:
  pull_request_target:
    types:
      - labeled
      - synchronize
    branches:
      - main

permissions:
  contents: write
  pull-requests: write

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    if: |
      contains(github.event.pull_request.labels.*.name, 'auto-merge-approved') &&
      github.event.pull_request.user.login == 'dependabot[bot]' &&
      github.event.pull_request.head.repo.fork == false
    steps:
      - name: Enable auto-merge for Dependabot PR
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          REPO: ${{ github.repository }}
        run: |
          gh pr review "${PR_NUMBER}" --approve --repo "${REPO}"
          gh pr merge "${PR_NUMBER}" --auto --merge --repo "${REPO}"

このワークフローのポイントを解説します。

pull_request_target を使う理由

pull_request ではなく pull_request_target を使用しています。pull_request_target は base ブランチ (main) のコンテキストで実行されるため、GITHUB_TOKENcontents: write 権限を付与できます。

多層防御の if 条件

3 つの条件を AND で組み合わせて、意図しないマージを防いでいます。

  1. auto-merge-approved ラベル -- Claude のレビューで承認された PR のみ
  2. dependabot[bot] -- Dependabot 以外の PR は対象外
  3. fork == false -- フォークからの PR は対象外

gh pr merge --auto の役割

--auto オプションは、リポジトリのブランチ保護ルールで設定されたステータスチェック (CI) が全て成功するまでマージを待機します。Claude のレビュー時点では CI が実行中であっても、CI 成功後に自動的にマージされます。

synchronize トリガーの必要性

labeled だけでは不十分なケースがあります。ラベルが付与された時点で CI がまだ実行中だと、gh pr merge --auto の設定が正しく行われない場合があります。synchronize (PR のコミットが更新されたとき) でもトリガーすることで、CI 完了後の再試行が可能になります。

3. Claude のワークフローにラベル操作権限を追加

前回の記事で紹介した claude.ymlallowedTools に、gh pr edit を追加しました。

claude_args: |
  --allowedTools '...,Bash(gh pr edit:*),...'

これにより、Claude は gh pr edit --add-label "auto-merge-approved" を実行できるようになります。

採用しなかった方式

Claude に直接マージさせる

最もシンプルな方法は、Claude のワークフローに contents: write を追加して gh pr merge を直接実行させることです。しかし以下の理由で不採用としました。

  • Claude に不必要に強い権限を与えたくない
  • 誰がマージを承認したのか監査ログ上で不明確になる
  • ラベルが PR 上で可視化されるため、自動マージされた理由が一目でわかる方が運用しやすい

dependabot/fetch-metadata で自動マージする

GitHub 公式ドキュメントでは、dependabot/fetch-metadata アクションで更新の種類 (patch/minor/major) を取得し、条件に応じて gh pr merge --auto を実行する方法が紹介されています。

https://docs.github.com/ja/code-security/tutorials/secure-your-dependencies/automating-dependabot-with-github-actions#enabling-automerge-on-a-pull-request

しかし、この方式ではバージョンの種類だけで判定するため、Breaking Changes の有無やセキュリティリスクの評価ができません。Claude のマルチエージェントレビューを経由することで、CHANGELOG の内容やコードベースへの影響まで踏み込んだ判定が可能になります。

試行錯誤で遭遇した問題

実装はスムーズにいかず、いくつかの問題に遭遇しました。ここではその過程を紹介します。

gh CLI の「not a git repository」エラー

自動マージワークフローでは actions/checkout を省略しています。PR の承認とマージだけなのでソースコードは不要だからです。しかし、gh CLI はデフォルトでカレントディレクトリから Git リポジトリ情報を取得しようとするため、以下のエラーが発生しました。

fatal: not a git repository (or any of the parent directories): .git

解決策として、--repo フラグでリポジトリを明示的に指定しています。

gh pr review "${PR_NUMBER}" --approve --repo "${REPO}"
gh pr merge "${PR_NUMBER}" --auto --merge --repo "${REPO}"

github.event.label.namesynchronize イベントの不整合

初期実装では if 条件に github.event.label.name == 'auto-merge-approved' を使っていました。これは labeled イベントでは正しく動作しますが、synchronize イベントでは github.event.label.namenull になるため、条件が常に false になります。

-github.event.label.name == 'auto-merge-approved' &&
+contains(github.event.pull_request.labels.*.name, 'auto-merge-approved') &&

contains(github.event.pull_request.labels.*.name, ...) に変更することで、PR の現在のラベル一覧から判定するようになり、labeled/synchronize どちらのイベントでも正しく動作します。

この問題は、Claude Code Action の通常 PR レビュー機能 (/review-pr) で検出されました。自動マージの仕組みを作る PR 自体も、Claude にレビューさせています。

実際の動作例

自動マージされたケース

自動マージ対象外のケース

メジャーバージョンアップには auto-merge-approved ラベルを付与せず、現在抱えている互換性の問題を報告してくれました。

導入効果

毎月実行している Dependabot PR が自動マージされ、パッチ/マイナーバージョンのアップデートにおいて人間の介入がゼロになりました。

一方で、メジャーバージョンアップデートは自動マージ対象外と判定され、マージに必要な作業をレビュアーにインプットしてくれます。「安全なものは自動で、判断が必要なものは人間に」という分業が機能するようになりました。

ソースコード

.github/workflows/dependabot-review-comment.yml

別途、前回の記事で解説している GitHub App の作成が必要です。

# Dependabot が作成した PR に対してレビュー依頼コメントを投稿するワークフロー
name: Dependabot Review Comment

on:
  pull_request:
    types: [opened, ready_for_review, reopened]

jobs:
  post-review-comment:
    # Dependabot の PR のみ実行
    if: github.actor == 'dependabot[bot]'
    runs-on: ubuntu-latest
    timeout-minutes: 5
    permissions:
      contents: read
      pull-requests: write

    steps:
      # actions/create-github-app-token の repositories パラメータは
      # "owner/repo" 形式ではなく "owner" / "repo" を別々に要求するため、リポジトリ名を抽出
      - name: Get repository name
        id: repository
        run: echo "name=${GITHUB_REPOSITORY#"${GITHUB_REPOSITORY_OWNER}"/}" >> "${GITHUB_OUTPUT}"
      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
        with:
          app-id: ${{ vars.GH_APP_ID }}
          private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}
          repositories: ${{ steps.repository.outputs.name }}
          permission-pull-requests: write
      - name: Post review request comment
        env:
          GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
        run: |
          gh pr comment ${{ github.event.pull_request.number }} \
            --repo ${{ github.repository }} \
            --body "@claude /review-dependabot-pr"
.claude/commands/review-dependabot-pr.md
---
description: Dependabot が作成した依存関係更新PRを、バージョン差分・影響範囲・セキュリティの3つの観点から包括的にレビューする
---

# Dependabot PR レビュー

このコマンドは、Dependabot が作成した依存関係更新PRを専門的にレビューします。

## レビューの流れ

### ステップ1: プロジェクトルールの読み込み

最初に、プロジェクトルートの CLAUDE.md ファイルを Read ツールで読み込み、プロジェクト固有のルール、開発環境、設計方針を確認します。この情報は、後続のすべてのサブエージェントに共有されます。

### ステップ2: PR情報の取得

```bash
# 現在のPR番号とリポジトリ情報を取得
gh pr view --json number,title,body,author,labels
```

Dependabot PRであることを確認します (`author.login == "dependabot[bot]"`)。

### ステップ3: 3つの専門サブエージェントによる包括的レビュー

以下の順序で各サブエージェントを**並列実行**します:

1. **dependabot-version-analyzer** (バージョン差分アナライザー)
   - ライブラリ名とバージョン範囲の特定
   - CHANGELOG/リリースノートの調査
   - Breaking Changes の特定
   - セキュリティ修正の初期確認

2. **dependabot-security-analyzer** (セキュリティアナライザー)
   - CVE/セキュリティアドバイザリの詳細調査
   - 脆弱性の深刻度評価
   - このプロジェクトへの影響判定
   - 緊急度の評価

3. **dependabot-impact-analyzer** (影響範囲アナライザー)
   - Breaking Changes のコードベースへの影響分析
   - 修正が必要な箇所の特定
   - マイグレーション作業の見積もり
   - マージ可否の判断

**重要**: 各サブエージェントには、ステップ1で読み込んだ CLAUDE.md の内容を前提知識として提供します。各エージェント内で CLAUDE.md を再読み込みする必要はありません。

### ステップ4: レビュー結果の統合と投稿

3つのサブエージェントの結果を統合し、以下の形式でレビューコメントを投稿します。

### ステップ5: 自動マージ条件の判定とラベル付与

レビュー結果の統合が完了した後、以下の自動マージ条件を判定します。

#### 自動マージ条件 (全てを満たす必要あり)

1. **マイナー or パッチバージョンアップデートである**
   - dependabot-version-analyzer の「変更タイプ」が「Minor」か「Patch」である

2. **セキュリティ的に問題がない**
   - dependabot-security-analyzer の結果が以下のいずれか:
     - 「セキュリティ修正は含まれていません」
     - セキュリティ修正ありだが深刻度が Low または Info

3. **マージが許可されている**
   - dependabot-impact-analyzer の結果が「即座にマージ可能」であること

#### 条件を満たす場合

レビューコメント内に自動マージ対象である旨を追記し、ラベルを付与:

```bash
gh pr edit {PR_NUMBER} --repo {REPO} --add-label "auto-merge-approved"
```

#### 条件を満たさない場合

レビューコメント内に自動マージ対象外の理由を記載。ラベルは付与しない。

## レビューコメントの形式

````markdown
# 🤖 Dependabot PR 自動レビュー

## 🎯 総合評価

**ライブラリ**: {library_name}
**バージョン変更**: {old_version} → {new_version}
**変更タイプ**: Major / Minor / Patch

**総合判断**: ✅ 承認 / ⚠️ 修正推奨 / 🚨 修正必須 / 🔒 緊急マージ推奨

---

## 📊 バージョン差分調査結果

{dependabot-version-analyzer からの結果を要約}

### 主な変更内容
- 新機能: {新機能の要約}
- 改善点: {改善点の要約}
- Bug修正: {修正の要約}

### ⚠️ Breaking Changes
{Breaking Changesがある場合のみ記載}

**参考リンク**:
- [Release Notes]({url})
- [CHANGELOG]({url})

---

## 🔒 セキュリティ分析結果

{dependabot-security-analyzer からの結果を要約}

### セキュリティ修正の有無
{セキュリティ修正の有無と詳細}

### 推奨アクション
{緊急度に応じた推奨アクション}

---

## 🔍 影響範囲分析結果

{dependabot-impact-analyzer からの結果を要約}

### 影響の有無
{Breaking Changesのプロジェクトへの影響}

### 必要な対応
{修正が必要な場合の詳細}

---

## 🎯 最終判断

{以下のいずれかを明確に記載}

### ケース1: 🔒 セキュリティ緊急対応
```
🚨 **緊急マージを強く推奨します**

**理由**:
- Critical/Highなセキュリティ脆弱性の修正が含まれています
- CVE-XXXX-XXXXX: {vulnerability_summary}
- このプロジェクトに該当します

**推奨アクション**:
1. ✅ 即座にこのPRを承認・マージ
2. 🚀 可能な限り早くデプロイ (24時間以内)
3. 📢 関係者への通知

**追加対応**:
{追加で必要な対応があれば記載}
```

### ケース2: ✅ 影響なし - 即座にマージ可能
```
**このPRは安全にマージできます**

**理由**:
- Breaking Changesはプロジェクトに影響しません
- または、Breaking Changesが含まれていません
- セキュリティ上の問題はありません
- テストが全て通過しています

**推奨アクション**:
- ✅ 承認してマージしてください
```

### ケース3: ⚠️ 修正後にマージ可能
```
⚠️ **コード修正が必要です**

**理由**:
- Breaking Changesがプロジェクトに影響します
- {影響箇所の件数}箇所で修正が必要です

⚠️ 注意: この分析はGitHub Code Search APIに基づいており、
型レベルの詳細な影響分析はローカル環境での確認を推奨します。

**必要な対応**:
1. {修正項目1}
2. {修正項目2}

**推奨アクション**:
1. 🛠️ 必要な修正を実施
2. ✅ テストを実行して動作確認
3. ✅ 修正後にマージ

**参考情報**:
- マイグレーションガイド: {url}
```

### ケース4: ⚠️ マージ可能だが要対応
```
⚠️ **マージは可能ですが、別途対応が必要です**

**理由**:
- 非推奨APIを使用していますが、現時点では動作します
- 将来のバージョンで削除される可能性があります

**推奨アクション**:
1. ✅ このPRはマージ可能
2. 📝 別PRで非推奨APIを置き換える Issue を作成
3. ⏰ 削除予定バージョン {version} までに対応

**非推奨箇所**:
{非推奨APIの使用箇所}
```

---

## 🤖 自動マージ判定

{以下のいずれかを記載}

### 自動マージ対象 ✅
パッチ/マイナーバージョンアップデートであり、セキュリティ上の問題がなく、
Breaking Changes の影響もないため、`auto-merge-approved` ラベルを付与しました。
CI が全て通過した後、自動的にマージされます。

### 自動マージ対象外 ❌
以下の理由により自動マージの対象外です。人間のレビューをお願いします。
- {理由}

---

## 📚 参考情報

- プロジェクトドキュメント: `CLAUDE.md`
- リリースノート: {url}
- CHANGELOG: {url}
- セキュリティアドバイザリ: {url}
- マイグレーションガイド: {url}

---

<details>
<summary>📋 レビュー詳細</summary>

### バージョン差分の詳細
{dependabot-version-analyzer の完全な出力}

### セキュリティ分析の詳細
{dependabot-security-analyzer の完全な出力}

### 影響範囲分析の詳細
{dependabot-impact-analyzer の完全な出力}

</details>

---

*このレビューは Claude Code によって自動生成されました*
````

## レビューのポイント

### 1. 明確な判断を提供

- 「マージ可能」「修正必要」「緊急対応」を明確に区別
- 曖昧な表現を避ける
- 具体的なアクションアイテムを提示

### 2. セキュリティを最優先

- Critical/Highなセキュリティ修正は最優先でマージ推奨
- CVE情報を明確に記載
- 緊急度を適切に判断

### 3. 影響範囲の正確な評価

- Breaking Changesの有無を明確に
- 影響がある場合は具体的な修正箇所を提示
- 影響がない場合もその根拠を明記

### 4. 実行可能な推奨事項

- 開発者が次に何をすべきか明確に
- 参考URLやマイグレーションガイドを提供
- 推定工数を提示 (可能な場合)

## 注意事項

### インラインコメントについて

Dependabotのプルリクエストはパッケージ管理ファイル、または依存関係ファイルのみの変更であるため、通常はインラインコメントは不要です。

**インラインコメントを使用する場合**:
- 影響を受けるコードファイル (非依存関係ファイル) に対してのみ
- 具体的な修正が必要な箇所のみ
- `mcp__github_inline_comment__create_inline_comment` を使用

### トップレベルコメントの使用

以下の場合はトップレベルコメント (PR全体へのコメント) を使用:
- 総合的な評価とマージ判断
- 複数ファイルにまたがる影響の説明
- セキュリティ分析結果
- 全般的な推奨事項

### エラーハンドリング

以下の場合は人間のレビューを促す:
- changelogやリリースノートが見つからない
- セキュリティ情報が不明確
- 影響範囲の判断が困難
- 自動レビューの限界を超える複雑なケース
.github/workflows/auto_merge_dependabot_pr.yml
name: Auto Merge Dependabot PR

on:
  pull_request_target:
    types:
      - labeled
      # CIのステータスチェックが更新された際にトリガーされる
      # gh pr merge の --auto オプションは、CIのステータスチェックが成功した場合にのみマージされる
      - synchronize
    branches:
      - main

permissions:
  contents: write
  pull-requests: write

jobs:
  auto-merge:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    # 安全チェック (多層防御):
    # 1. ラベル名が auto-merge-approved であること
    # 2. PR 作成者が dependabot[bot] であること
    # 3. フォークからの PR でないこと
    if: |
      contains(github.event.pull_request.labels.*.name, 'auto-merge-approved') &&
      github.event.pull_request.user.login == 'dependabot[bot]' &&
      github.event.pull_request.head.repo.fork == false
    steps:
      - name: Enable auto-merge for Dependabot PR
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          REPO: ${{ github.repository }}
        run: |
          gh pr review "${PR_NUMBER}" --approve --repo "${REPO}"
          gh pr merge "${PR_NUMBER}" --auto --merge --repo "${REPO}"

まとめ

前回の記事で紹介した Claude Code Action のマルチエージェントレビューに、ラベルベースの自動マージを組み合わせることで、Dependabot PR の対応を「レビュー→判断→マージ」まで自動化できました。

実装のポイントをまとめると、

  • ラベルベース方式 -- Claude に直接マージ権限を与えず、ラベルの付与で間接的にマージを制御する
  • 多層防御 -- ラベル名・PR 作成者・フォーク判定の 3 条件で意図しないマージを防止する
  • --auto オプション -- CI ステータスチェック通過を前提条件として組み込む

Dependabot の PR は「定型的だが調査コストが高い」タスクの代表例です。マルチエージェントレビューで判断の質を担保し、ラベルベースの自動マージで運用コストを最小化する。この組み合わせは、Dependabot に限らず、CI が通れば安全にマージできる定型的な PR の自動化にも応用できるパターンだと考えています。

GENDA

Discussion