🙌
GitHub Actions の依存関係は後続のジョブに波及する
以下のようなワークフローを作っていて、いざ実行させてみたら自分の認識とは違っていたのでメモを残しておく。
- main ブランチに push されたタイミングでワークフローを起動
- DB マイグレーション用のファイルが更新されたか確認する
- 2で変更があった場合、DB マイグレーション用のアプリをビルドする
- 3のビルドが実行された場合、DB マイグレーション用のアプリをデプロイする
- 4でデプロイが実行された場合、DB マイグレーションを実行する
- 5に依存させるかたちで、アプリをビルドする (DB マイグレーション関連のジョブはスキップされる可能性があるのでalways()をつける)
- 6に依存させるかたちで、アプリをデプロイする
YAML の抜粋は以下。
jobs:
# DB マイグレーション用のファイルが更新されたか確認
changes:
runs-on: ubuntu-latest
outputs:
migrations: ${{ steps.filter.outputs.migrations }}
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
base: 'refs/heads/${{ github.ref_name }}'
filters: |
migrations:
- 'db/migrations/**/*.sql'
# DB マイグレーション用のアプリをビルド
build:
needs: changes
if: ${{ needs.changes.outputs.migrations == 'true' }}
name: Build
runs-on: ubuntu-latest
# ... 省略 ...
# DB マイグレーション用のアプリをデプロイ
deploy:
needs: build
name: Deploy
runs-on: ubuntu-latest
# ... 省略 ...
# DB マイグレーションの実行
migrate:
needs: deploy
name: DB Migration
runs-on: ubuntu-latest
# ... 省略 ...
# アプリのビルド
build-app:
name: Build
runs-on: ubuntu-latest
needs: migrate
if: always()
# ... 省略 ...
# アプリのデプロイ
deploy-app:
needs: build-app
name: Deploy
runs-on: ubuntu-latest
# ... 省略 ...
# ... 省略 ...
作った時点での想定では、build-app ジョブに always()
を付けているので、以降の deploy-app ジョブは問題なく実行される想定だったがスキップされてしまった。
互いに必要とする一連のジョブが実行に含まれている場合、失敗またはスキップの時点から、依存関係チェーン内のすべてのジョブに失敗またはスキップが適用されます。 依存しているジョブが成功しなかった場合でもジョブを実行する場合は、jobs.<job_id>.if のalways() 条件式を使用します。
ここにバッチリ書かれていた。失敗またはスキップされた時点から後続の依存関係のあるジョブに波及するということらしい。
私が知らなかっただけ、かつ今までこういった場面に遭遇していなかったので勉強になった。
回避策は以下の通り依存関係のあるジョブに条件式を付けてあげるだけ。
if: ${{ always() && needs.build-app.result == 'success' }}
jobs:
# ... 省略 ...
# アプリのビルド
build-app:
name: Build
runs-on: ubuntu-latest
needs: migrate
if: always()
# ... 省略 ...
# アプリのデプロイ
deploy-app:
needs: build-app
if: ${{ always() && needs.build-app.result == 'success' }}
name: Deploy
runs-on: ubuntu-latest
# ... 省略 ...
# ... 省略 ...
Discussion