先に結論だけ
Dependabotと自動マージを併用することで、依存パッケージの更新作業を簡略化でき、手作業によるミスを防げます。パッケージ更新作業を負担に感じる方はぜひ導入を検討してください。
マージの権限をワークフローに与えるのは、抵抗感があるかもしれません。例えば、開発環境にしか影響を与えないパッケージのパッチバージョンの更新のみ許可する設定から始めてみましょう。
はじめに
この記事は、Dependabotを使って依存パッケージの更新を自動化する方法を共有するためのものです。
対象とする読者
- GitHubのリポジトリを運用しているエンジニア
- すでにテスト自動化は導入している
- GitHub Actionsを使ったことがある
- 依存関係の更新や管理が作業負担に感じる人
テスト自動化に関する内容はこの記事では取り扱いません。
対象とする環境
- 2024/08/09時点のGitHubおよびDependabot
- node.js v20.16.0
- npm v10.8.2
この記事ではパッケージマネージャーにnpmを利用しています。他のパッケージマネージャーを利用している場合は、適宜読み替えてください。
Dependabotとは
Dependabotは、GitHubが提供する依存関係スキャニングツールです。この記事で対象となるのはDependabotのバージョンアップデートですが、Dependabotには他にも以下の機能があります。
Dependabotアラート
Dependabotアラートは、脆弱性のある依存関係を検出し、リポジトリの所有者に通知するツールです。
Dependabotアラートはすべてのリポジトリで有効になっています。
Dependabotセキュリティアップデート
Dependabotセキュリティアップデートは、脆弱性を修正するプルリクエストを作成するツールです。
この機能は、ユーザーが設定しない限り有効になりません。
リポジトリのSetting
タブ→Code security and analysis
→Dependabot
セクション→Dependabot security updates
→Enable
ボタンで設定できます。
Dependabotバージョンアップデート
Dependabotバージョンアップデートは、依存パッケージの最新バージョンを確認し、プルリクエストを作成するツールです。セキュリティアップデートとは異なり、脆弱性の有無には関係なく更新のたびにプルリクエストが作成されます。
Dependabotバージョンアップデートは、ユーザーがdependabot.yml
という設定ファイルを設置すると有効化されます。設定した期間ごとにパッケージの更新を確認し、プルリクエストを発行します。
GitHubのAuto Merge機能
Auto mergeは、ブランチプロテクションルールのチェックをパスしたプルリクエストを自動でマージする機能です。
Auto merge機能を有効化する手順は自動マージを有効化するのセクションで解説します。
Dependabotで自動マージ
Dependabotバージョンアップデートと、GitHubの自動マージ機能を組み合わせることで、依存パッケージの更新を自動化できます。
自動テスト環境を整える
まずは、依存パッケージの更新による影響を確認するための自動テスト環境を整えます。node.jsには、以下のようなテストランナーがあります。
この記事ではテストそのものの実装は割愛します。依存パッケージの更新によって機能が破壊されないか、自動テストで検出できるようになるのが理想です。
自動テストをGitHub Actionsで実行する
GitHub Actionsを使って、プルリクエストが作成されたときに自動テストを実行するワークフローを設定します。
name: Run tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x, 22.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- run: npm ci
- run: npx test
このワークフローは、デフォルトブランチにプルリクエストが作成されたときにnpm test
コマンドで自動テストを実行します。
より詳細な設定方法は以下のリンクを参照してください。
ブランチプロテクションルールを有効化する
テストが失敗した場合、デフォルトブランチへのマージを阻止する設定を追加します。
GitHubのSettings
タブ→Rules
→Rulesets
→New ruleset
→New branch ruleset
でブランチプロテクションルールを作成します。
以下のスクリーンショットの手順にそって、プロテクションルールを設定します。
ポイントになるのはRequire status checks to pass
とRequire branches to be up to date before merging
の設定です。この設定で、テストが失敗した場合、デフォルトブランチへのマージが阻止されるようになります。
この設定は、Auto mergeを機能させるための最低限のものです。皆さんのプロジェクトに合わせて、Require linear history
(線形履歴の強制)やRequire a pull request before merging
(プルリクエストを経由しないマージを禁止)などより厳密な設定を検討してください。
Dependabotバージョンアップデートを有効化する
Dependabotのバージョンアップデート機能を有効化します。リポジトリに/.github/dependabot.yml
というファイルを作成します。
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
Dependabotはこの設定ファイルを読み込んで、依存パッケージの監視を開始します。
自動マージを有効化する
GitHubリポジトリのAuto merge機能を有効化します。リポジトリのSettings
タブ→General
→Pull Requests
セクション→Allow auto-merge
をチェックします。
この時点でGitHubのWeb画面から自動マージが可能です。プルリクエストを作成して、テストが完了する前にEnable auto-merge
ボタンをクリックすると自動マージが予約されます。テストにパスした時点で、そのプルリクエストがデフォルトブランチにマージされます。
Pull Requestを自動マージする
マージをGitHub Actionsで自動化します。以下のワークフローを設定します。
▼ .github/workflows/dependabot-auto-merge.yml
name: Dependabot auto-merge
on:
pull_request:
branches:
- main
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Enable auto-merge for Dependabot PRs
if: steps.metadata.outputs.dependency-type == 'direct:development' && 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}}
このワークフローでは、package.jsonのdevDependencies
に登録されているモジュールが、パッチ更新された場合に自動マージを行います。マイナー以上のバージョンアップデートや、dependencies
に登録されているモジュールのアップデートはユーザーの判断を待ちます。
Dependabotが作成したプルリクエストの内容は、dependabot/fetch-metadata
というアクションで取得できます。
-
dependency-type
:dependencies
かdevDependencies
のどちらの更新か -
update-type
: セマンティックバージョンの種類
などの情報がメタデータに格納されます。
メタデータのより詳細な情報は公式サイトを参照してください。
自動マージ後のトリガーに関する問題と対処方法
問題 : 自動マージ後にワークフローがトリガーされない
Dependabotが作成したプルリクエストを、rebase and merge
でデフォルトブランチにマージすると、GitHub Actionsのpush
やpull_request:closed
イベントがトリガーされません。
問題の原因
Dependabotはプルリクエストが解決された場合、即座に自分自身が作ったブランチを削除します。私の現在の理解では、自動マージとブランチ削除が同時に行われた場合pull_request:closed
イベントはトリガーされないようです。また、Dependabotがrebase and merge
でマージした場合、デフォルトブランチのpush
イベントもトリガーされませんでした。
影響
このトリガーの取りこぼしは、たとえばデフォルトブランチが更新されるたびにデモページを更新し、GitHub Pagesにデプロイするというユースケースで問題を引き起こします。
- ドキュメントが最新状態に維持されていない
- 依存パッケージの更新によってドキュメントのビルドに失敗しても気づけない
対処方法
この問題に対して私は
- Dependabotが
rebase and merge
した場合、処理を取りこぼすことがある - プルリクエストの作成イベントは正常にトリガーされるため、デフォルトブランチの
push
およびpull_request
イベントでドキュメントのビルドワークフローを実行する -
if: ${{ github.ref == 'refs/heads/main' }}
を利用して、デフォルトブランチのheadを参照しているときだけデプロイする
という方法で対処しました。
具体的なワークフローは以下の通りです。
▼ .github/workflows/publish-github-pages.yml
name: Publish github pages
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: write #デプロイのための書き込み許可を与える
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run buildPages #ドキュメントビルドコマンド
- name: Deploy Github pages
uses: peaceiris/actions-gh-pages@v4
if: ${{ github.ref == 'refs/heads/main' }} #デフォルトブランチのheadを参照しているときだけデプロイする
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
この対処方法が最適か、他に良い方法があればぜひコメントをお寄せください。