dependabotのPRに自動でビルド成果物をコミットする

ビルド成果物をリポジトリに含める必要がある場合、どのタイミングでコミットするかが問題になります。 例えばGitHub Actionsのように、JavaScriptの成果物をリポジトリに含める必要があるようなケースです。 リリースを打つ時にビルド成果物をコミットするという方法もありますが、この記事ではメインブランチへのマージ時にはビルドしないといけないという前提があることにします。

人間がPRを出す場合は手元からビルドして成果物も一緒にコミットできますが、dependabotのようなbotにはビルドをさせることができません。 しかし、GitHub Actionsを使えば、dependabotのPRに対してもビルド成果物をコミットすることができます。

name: CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha || github.sha }}
          token: ${{ secrets.DEPENDABOT_TOKEN || secrets.GITHUB_TOKEN }}
          fetch-depth: ${{ github.actor == 'dependabot[bot]' && 2 || 1 }}
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - name: Install Dependencies
        run: npm ci
      - name: Run tests
        run: npm run test
      - name: Build
        run: npm run build
      - name: Check for dist changes
        id: dist-changes
        run: git diff --exit-code
      - name: Push dist changes for dependabot
        if: github.actor == 'dependabot[bot]' && failure() &&
          steps.dist-changes.outcome == 'failure'
        run: |
          git config user.name "$(git show -s --format=%an)"
          git config user.email "$(git show -s --format=%ae)"
          git commit --all --amend --no-edit
          git push --force origin "HEAD:${GITHUB_HEAD_REF}"
  • GITHUB_TOKENの権限を強めたくないので、permissionsは読み取り権限のみにしています。Dependabot secretを使うことで、dependabotのPRでしか利用できないシークレットを設定できます。このシークレットには該当リポジトリへのwrite権限を付与したアクセストークンを設定しておきます。
  • pull_requestイベントでactions/checkoutを使うと、マージコミットをチェックアウトしてしまいます。今回はPRにコミットを積みたいので、refgithub.event.pull_request.head.shapushイベント時のフォールバックを指定します。
  • あとはテストとビルドを行います。そしてビルド成果物が変更されているかを確認し、もし変更があればdependabotのPRにコミットします。今回はパッケージの更新コミットにamendしたかったので、push --forceで更新しています。また、fetch-depthも2にしています。もしamendしない場合はpush --forceも不要でfetch-depthを指定しないでも問題ありません。

ポイントはチェックアウトするときのrefと、Dependabot secretを使うことでしょうか。 GitHub Actionsがそうなのですが、ビルド成果物をコミットしなければならないというシチュエーションはそもそも珍しいかもしれません。 しかし、Dependabot secretの存在を知っておくと、dependabotのPRにのみ利用できるシークレットを設定できるのでとても便利ですね。

それではまた!