はじめに
この記事は、GitHub Actionsでjobやworkflow同士を連鎖させる方法を記録、共有するためのものです。
想定する環境
この記事は、2021/11/12時点でのGitHubを前提に書かれています。GitHubが更新されると、記事の内容をそのまま適用できないことがあります。ご注意ください。
想定する読者
- gitを使ったことがある
- GitHubのアカウントを持っている
- GitHub Actionsを使ったことがある
この記事ではgitの使い方やGitHubの導入方法などは取り扱いません。ご承知ください。
GitHub Actionsとは
GitHub Actionsとは、GitHubが提供するCI/CD環境です。リポジトリへのPushやPull requestの作成、Issueへのコメントなどさまざまなイベントを引き金としてコンテナーが立ち上がり、指定された命令を処理します。
利用ケースとして
- Pull requestが作成されたら、テストを実行し合否を判定する
- デフォルトブランチが更新されたら、APIドキュメントを生成しGitHub Pagesで公開する
- Issueが作成されたら、内容にしたがって特定のラベルをつける
- 一定期間Issueに活動がなかったら、IssueをCloseする
などがあります。
ワークフロー
GitHub Actionsのアクションは、以下のような粒度で管理されています。(公式ドキュメント)
ステップ
アクションの最小単位です。シェルコマンド1行に相当します。
ジョブ
複数のステップで構成された処理です。ジョブ同士は並列処理されます。
ワークフロー
複数のジョブで構成され、イベントを引き金として実行される処理の塊です。1つのワークフローは1つのYAMLファイルに記述されます。
ワークフローファイルは.github/workflows
というディレクトリに保存され、このファイル自体もgitでバージョン管理されます。
ワークフローファイルの肥大化
複雑なワークフローを構成すると、ワークフローファイルが肥大化して管理が難しくなっていきます。そのためジョブを分割したり、相互に関連しないジョブを別々のワークフローに切り分けなければいけません。
処理の連鎖
GitHub Actionsには、ワークフローやジョブの分割のための連鎖機能があります。この連鎖機能を使えば「テストが成功し、デフォルトブランチにマージされたら、APIドキュメントを更新してGitHub Pagesで公開し、npmでパッケージを公開する」といった複雑な処理を管理しやすくなります。
GitHub Actionsでは、依存ジョブとworkflow_runトリガーの2種類の連鎖機能が提供されています。
ジョブの連鎖 : 依存ジョブ
GitHub Actionsのジョブはデフォルトでは並列で実行されます。依存ジョブにneedsフィールドを設定すると、指定した他ジョブの完了を待ちます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ./build_server.sh
test:
needs: build
^^^^^^^^^^^^ ここが依存ジョブの設定
runs-on: ubuntu-latest
steps:
- run: ./test_server.sh
上記の例ではbuildジョブが成功したら、testジョブが実行されます。buildジョブが失敗したらtestジョブは実行されずに中断されます。
依存ジョブは並列実行されないため、ワークフロー全体の処理時間は長くなります。後続の処理が中断される利点と、処理時間が長くなる欠点を比べて設定してください。
ワークフローの連鎖 : workflow_runトリガー
workflow_runトリガーを使うと、前ワークフローの完了を引き金に次のワークフローが開始されます。
on:
workflow_run:
workflows: ["Run Tests"]
branches: [main]
types:
- completed
上記の例ではRun Tests
という名前のワークフローが、mainブランチで完了したときに処理が始まります。
なお、workflow_runトリガー単体では、前ワークフローの処理が成功したか失敗したかをチェックできません。前ワークフローが成功したか否かを確認するにはコンテキストgithub.event.workflow_run
を確認します。このコンテキストには前ワークフローの情報が格納されています。
on:
workflow_run:
workflows: ["Build"]
types: [completed]
jobs:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
...
たとえばgithub.event.workflow_run.conclusion
には前ワークフローの成否が格納されています。
処理を分割することで、再利用しやすく可読性の高いワークフローを作れます。お手元の環境で複雑すぎるワークフローがある場合、ぜひ分割を検討してみてください。
以上、ありがとうございました。