[GitHub Actions]ファイルの差分や更新状態を元にStepの実施を切り分けてみる

特定ファイルが更新されたタイミングでActionを実施したいものの、ファイル毎にWorkflowが大量に出来上がる状態も防ぎたく、ファイルの状態検知結果が一致したらStepを動かすという手段でやってみました。
2021.10.13

GitHub Actionsで特定ファイルの更新に紐付けたStep実施を試してみました。 on:push: にて対象ファイル指定でも問題はないのですが、複数のファイルに対して実施するStepを切り分けたい場合にはファイル毎にWorkflowが増えることも意味しており、判定に用いる条件のみ差分が生じる程度なら一つのファイルに収めたかったためです。

更新履歴からStep実行判定

更新のあったファイル一覧を取得し、その中に求めるファイルが存在するかをチェックします。更新ファイル一覧取得には tj-actions/changed-files を利用しました。

      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v10.1

      - name: confluence-markdown-sync
        if: contains(steps.changed-files.outputs.all_modified_files, 'docs/demo.md')
        uses: cupcakearmy/confluence-markdown-sync@v1
        with:
          from: 'docs/demo.md'
          to: '0000000000'
          user: 'xxxxxxx@example.com'
          cloud: 'xxxxxxx'
          token: ${{ secrets.CONFLUENCE_TOKEN }}

更新差分の情報が必要なため、actions/checkoutfetch-depth の指定を入れます。 サンプルでは fetch-depth: 0 としているため全履歴取得となりますが、実際には HEAD^HEAD の2つのみを判定に利用しているため fetch-depth: 2 で良いかもしれません。何も指定しなかった場合は以下のエラーが出ます。

You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage

差分からのファイル検知

更新履歴ではなく差分が検知されたファイル一覧を元にStepを実行するという手段もあります。git-diff-action を使うパターンですが、このActionは利用者側で適切に出力を加工する必要があります。

      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Get Diff
        uses: technote-space/get-diff-action@v5
        with:
          FILES: |
            README.md 

      - name: notify diff
        if: contains(env.GIT_DIFF, 'README.md')
        run: echo ${{ env.GIT_DIFF }}

当初は env.GIT_DIFF という環境変数名から、差分の詳細が詰まってるのだと勘違いしていました。ActionsのログにはDiffのDumpが実行コマンド込で残されているため、応用して差分の吐き出しにも使えるかもしれません。

あとがき

元は confluence-markdown-sync が常に更新を行うため、ファイルが更新された時限定でConfluenceも更新しておきたいと思ったのがきっかけでした。個別の更新ステータス取得をスクラッチで行うのは案外骨が折れるため、手軽に行いたい人にはオススメです。