Money Forward Developers Blog

株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。

20230215130734

Dependabot 運用を自動化したい

この記事は、Money Forward Engineering 1 Advent Calendar 2022 16日目の投稿です。

Money Forward ME サーバサイドエンジニアの島津です。 今回は、Dependabot 運用の自動化について、ご紹介したいと思います。

Dependabot について

Dependabot は、プロジェクトで使用されているライブラリの脆弱性を監視し、依存関係を最新の状態に保つための、GitHub のサービスです。 その中でもいくつか機能がありますが、今回は Dependabot version updates の機能を使用した際の自動化についてです。

この機能を使うと、リポジトリ内の各種パッケージのバージョンをチェックし、常に最新に保つために自動的に bot が プルリクエストを作成してくれます。 詳しい設定方法は割愛しますが、リポジトリ内で .github/dependabot.yml を記述するだけで有効化できます。

▼Dependabotが作成してくれるPR例

背景

私は Money Forward ME のサーバサイドエンジニアで、Rails アプリケーションの開発を行っていますが、Dependabot を使って Gem などのバージョンを常に最新化できるようにしています。 Dependabot が上げるプルリクエストをレビュー・マージするのは人間の手作業だったので、チーム内で週替りの当番制にするなどして、プルリクエストが滞留しないように工夫していました。

しかし、機能開発が忙しくなると、どうしても優先度が下がってしまい、徐々にプルリクエストが溜まってしまう課題がありました。 少しでもこの運用を自動化して、より価値の高い開発に集中できる環境を作りたいという気持ちがあり、Dependabot 運用自動化に取り組むことにしました。

作成したワークフロー

自動化には GitHub Acrions を使用しました。

name: Dependabot automation

on:
  pull_request:
    types:
      - opened

permissions:
  pull-requests: write # approve/merge に必要
  contents: write # merge に必要
  issues: write  # label 付与に必要 (この例では不要)
  repository-projects: write # PRタイトル変更等に必要(公式ドキュメントをご参照ください)

jobs:
  dependabot-automation:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    timeout-minutes: 13
    steps:
      - name: Dependabot metadata
        id: metadata
        uses: dependabot/fetch-metadata@v1.3.5
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Approve & enable auto-merge for Dependabot PR
        if: |
          steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
          (steps.metadata.outputs.update-type == 'version-update:semver-minor' && steps.metadata.outputs.dependency-type == 'direct:development')
        run: |
          gh pr review --approve "$PR_URL"
          gh pr edit "$PR_URL" -t "(auto merged) $PR_TITLE"
          gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{ github.event.pull_request.html_url }}
          PR_TITLE: ${{ github.event.pull_request.title }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

実は GitHub が Automating Dependabot with GitHub Actions を公開していて、それを若干アレンジした形になります。

自動マージする条件

  • パッチバージョンのアップデート、もしくは開発環境のみ利用されるライブラリのマイナーバージョンのアップデート
  • CI が pass したとき

の2つが挙げられます。

1つ目のバージョンについては、以下で指定しています。

if: |
  steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
  (steps.metadata.outputs.update-type == 'version-update:semver-minor' && steps.metadata.outputs.dependency-type == 'direct:development')

dependabot/fetch-metadataで取得したメタデータをもとに判定が可能です。 Dependabot は依存関係のバージョニングを Semantic Versioning を基準に判定しています。

それによるとパッチバージョンは、後方互換性のあるバグフィックスを行った際にインクリメントされるので、自動マージの対象として問題ないと判断しました。

PATCH version when you make backwards compatible bug fixes

またマイナーバージョンは、後方互換を保った機能追加と定義されています。 ただライブラリによっては braking changes が含まれている可能性もあるため、プロダクションに直接影響の少ない開発環境やテストの実行で利用されるライブラリを自動マージの対象としました。 例えば Rubocop や RSpec 周りの Gem が対象になります。

MINOR version when you add functionality in a backwards compatible manner

2つ目の CI が pass した場合のみマージする、というのは以下で行っています。

gh pr merge --auto --merge "$PR_URL"

GitHub の自動マージ機能とブランチ保護ルールを組み合わせて実現しています。

これまで自動マージ機能をリポジトリで使えるようにすると、ブランチ保護ルールをクリアした全プルリクエストが勝手にマージされてしまうのではないかと誤解していました。。 しかし、改めてしっかりドキュメントを読むと、自動マージ機能を使えるようにしたリポジトリでも、プルリクエスト内で個別に有効化しない限り自動マージは実行されないようでした。(詳しくはドキュメントをご参照ください。)

GitHubの自動マージ機能は、既存の開発フローに影響が少なく有効にできることがわかったので、リポジトリの設定で自動マージを有効化し、gh pr merge --auto コマンドで自動マージを行うようにしました。

これでブランチ保護ルールで設定している required の CI が通過したときに自動マージをしてくれるようになりました。

補足ですが、マージしても直ちに本番環境にデプロイされるわけではなく、ステージング環境を挟むので、自動マージされたプルリクエストがあれば、それも踏まえて動作確認するようにしています。

▼自動マージが含まれるリリースプルリクエスト ( マージ後に自動作成される本番環境に対応するブランチに対するプルリクエスト )

他に試した方法

様々な事情で auto-merge 機能を有効化できないリポジトリもあるかもしれないので、 GitHub の auto-merge 機能を有効化する前に、実装していた方法もご紹介します。

      - name: Automerge
        id: automerge
        uses: pascalgn/automerge-action@v0.15.5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          MERGE_LABELS: dependencies
          MERGE_REQUIRED_APPROVALS: 1
          MERGE_RETRY_SLEEP: 120000 # 120s
          MERGE_RETRIES: 6 # default
          MERGE_DELETE_BRANCH: true
          MERGE_FILTER_AUTHOR: dependabot[bot]

pascalgn/automerge-action という action を利用して、自動マージ部分を実行していました。 この action でも required の CI が通過するまで待ってくれるので、要件は満たすことができました。

最後に

いかがでしたでしょうか。

今回紹介した Dependabot 以外にも自動化できる部分は、どんどん手放していきたいと思います。 今後は自動化対象外のDependabot PR のレビュワー自動アサインや、コンフリクト時の対応についても考えてみたいと思います。 自動化して仕事を減らしていきましょう。


マネーフォワードでは、エンジニアを募集しています。 ご応募お待ちしています。

【会社情報】 ■Wantedly株式会社マネーフォワード福岡開発拠点関西開発拠点(大阪/京都)

【SNS】 ■マネーフォワード公式noteTwitter - 【公式】マネーフォワードTwitter - Money Forward Developersconnpass - マネーフォワードYouTube - Money Forward Developers