GitHub ActionsでファイルAが更新されているがファイルBが更新されていない時だけ実行する、を実現する
GitHub Actionsの on: push
や on: pull_rerequest
のトリガーには paths
/paths_ignore
という機能があり、特定のファイルパスが変更された時だけワークフローを実行できます。
# 例えばiOSとAndroidのmonorepoで、ios以下が変更された時だけiOSのテストを実行したい on: push: paths: - 'ios/**'
paths
/paths_ignore
には配列で複数のパス指定・globパターン指定ができ、そのうちのどれか1つにでもマッチするとワークフローが実行されます。しかしこの機能には1つ弱点があり、paths
と paths_ignore
を同時に使うことができません。つまり、ファイルAが変更され・かつ・ファイルBが変更されていない、という条件が記述できません(と認識しています)。
You can exclude paths using two types of filters. You cannot use both of these filters for the same event in a workflow.
今回はこれを乗り越える方法の紹介です。trilom/file-changes-actionというアクションを使用して、ジョブ内で自分でファイル差分をチェックしてみましょう。ここではiOSアプリのリポジトリで、Podfile
が更新されているがPodfile.lock
が更新されていない時、ということにしてみます。
name: Update Podfile.lock on: pull_request: paths: - Podfile jobs: precheck: runs-on: ubuntu-latest outputs: files_changed: ${{ steps.file_changes.outputs.files }} steps: - uses: actions/checkout@v2 - id: file_changes uses: trilom/file-changes-action@v1.2.3 update: runs-on: macos-latest needs: precheck if: contains(fromJson(needs.precheck.outputs.files_changed), 'Podfile.lock') == false steps: - uses: actions/checkout@v2 - run: pod install - uses: stefanzweifel/git-auto-commit-action@v4.2.0 with: commit_message: Update Podfile.lock file_pattern: Podfile.lock
まずは前提条件としてpaths
にPodfile
を指定して、「Podfile
が更新されている」ことをワークフローレベルでフィルタリングします。
ここからが本題です。precheck
ジョブで、trilom/file-changes-action
を使ってファイル差分を取得します。そしてそのステップのoutputをジョブのoutputに保存して、後続のジョブからアクセスできるようにします。ここでジョブを分割しているのは
- 後続の処理が複数ステップに渡る場合、それぞれのステップに
if
を書くのが面倒・メンテナンスしにくい - 今回の例では後続の処理にmacOSが必要だが、macOSは課金が高額(Ubuntuの10倍!)なので、ファイル差分のチェックはUbuntuで行う
ためです。
update
ジョブはneeds
を使ってprecheck
ジョブの終了後に直列で実行されるようにします(デフォルトでは複数のジョブは並列で実行されます)。次にジョブレベルのif
で、Podfile.lock
が変更されていない、という条件を書きます。needs
contextを使うと、前段のジョブの実行結果やoutputsにアクセスできます。ここではprecheck
ジョブでoutputsに保存したtrilom/file-changes-action
の出力結果を使用し、contains
関数で変更されたファイル名の配列にPodfile.lock
が含まれるかを確認します。
後は実処理として pod install
してPodfile.lock
を更新してから、stefanzweifel/git-auto-commit-actionを使ってプルリクエストを作成しています。
こうして「Podfile
が更新されているがPodfile.lock
が更新されていない時」という条件を実現できました。めでたしめでたし。色んなアクションを組み合わせて柔軟なジョブ制御を実現していきましょう。