こんにちは!日々の開発、本当にお疲れ様です。
マイクロサービスの数が増えてくると、「Aサービスがビルド・デプロイ成功したら、次はBサービスの結合テストを走らせたい」「全サービスのリリースが完了したら、ドキュメントの更新通知を飛ばしたい」といった、リポジトリを跨いだワークフローの連鎖(オーケストレーション)が必要になってきますよね。
今回は、GitHub Actionsの `workflow_run` イベント を使って、複数のCI/CDパイプラインを美しく、そして堅牢に階層化・自動化するテクニックを解説します。
これをマスターすれば、リポジトリが分かれていても「まるで一つの巨大なシステム」のようにスムーズな自動リリースが実現でき、毎日の手動オペレーションから完全解放されますよ。ぜひ最後までついてきてくださいね!
—
1. そもそも「Workflow Run」イベントとは?
GitHub Actionsのトリガーといえば、`push` や `pull_request` がお馴染みですよね。
では、`workflow_run` は何をするものなのでしょうか?
一言で言うと、「ある特定のワークフローが完了した(または失敗した)という事実を検知して、次のワークフローを自動起動する」ためのトリガーです。
なぜこれがマイクロサービスで重宝するのか?
よくあるアンチパターンとして、「同じリポジトリにすべてのコードを押し込む(モノリス)」か、「別リポジトリだけど、無理やりギットフックやWebhooksで繋ぐ」という方法があります。しかし、これらは管理がすぐに破綻します。
`workflow_run` を使えば、以下のようなメリットが得られます。
- 関心事の分離: 「ビルド・単体テストを行うリポジトリ」と「インフラデプロイやE2Eテストを行うリポジトリ」を綺麗に分離できる。
- セキュリティの担保: 後続のワークフローで強力な権限(本番環境へのデプロイ権限など)が必要な場合、トリガー元とは別のセキュアなコンテキストで実行できる。
- 依存関係の可視化: どのワークフローがどのワークフローの成果を必要としているかが明確になる。
—
2. 最も重要な基礎セットアップ:前提条件の理解
`workflow_run` を使う上で、一番最初にハマりやすいポイントがあります。それは「権限(Permissions)」と「ブランチの制約」です。
1. デフォルトではデフォルトブランチ(通常は `main` や `master`)でしか動かない
`workflow_run` は、ターゲットとなるワークフローがデフォルトブランチ上で実行された場合にのみトリガーされます。開発中のフィーチャーブランチでいくらテストを通しても、デフォルトブランチで動かないと連鎖しないので注意してください。
2. クロスリポジトリ(別リポジトリ間)の場合の認証
もし「リポジトリAの完了をトリガーに、リポジトリBを動かす」場合、標準の `GITHUB_TOKEN` では別リポジトリを叩けないことがあります。その場合は、Personal Access Token (PAT) や GitHub Apps の権限設定が必要になります。
今回は、分かりやすさを重視して、「同一リポジトリ内でのワークフローの階層化(ビルド ➔ デプロイの連鎖)」を基本の「Hello World」として丁寧に見ていきましょう。
—
3. 実践!「Hello World」的 ワークフロー連鎖の構築
それでは、実際に手を動かしてみましょう。
今回は1つのリポジトリの中に、以下の2つの階層化されたワークフローを用意します。
1. 第1階層(上流): `ci-base.yml` (コードのビルドとテストを行う)
2. 第2階層(下流): `cd-deploy.yml` (`ci-base.yml` が無事に成功した時だけ走り、デプロイを行う)
ステップ1:上流ワークフローの作成 (`.github/workflows/ci-base.yml`)
まずは、すべての基本となる上流のCIワークフローです。ここは普段通りのテストを行います。
name: 1. CI Base Workflow (上流)
on:
push:
branches: [ “main” ] # mainブランチへのプッシュで発火
jobs:
build-and-test:
name: Build and Test
runs-on: ubuntu-latest
steps:
- name: コードのチェックアウト
uses: actions/checkout@v4
- name: セットアップ Node.js
uses: actions/setup-node@v4
with:
node-version: ’20’
- name: 依存関係のインストールとテスト
run: |
npm ci
npm test
echo “🎉 テストが正常に完了しました!”
ステップ2:下流ワークフローの作成 (`.github/workflows/cd-deploy.yml`)
ここが今回のメインディッシュです。`workflow_run` を使って、先ほどの `1. CI Base Workflow (上流)` が無事に完了したことをトリガーにします。
name: 2. CD Deploy Workflow (下流)
on:
workflow_run:
workflows: [“1. CI Base Workflow (上流)”] # 監視する上流ワークフローの名前を指定
types:
- completed # ワークフローが完了した瞬間をキャッチ
jobs:
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
# 【超重要】上流ワークフローが「成功(success)」した時だけこのジョブを走らせる!
# これを忘れると、テストが失敗していてもデプロイが走ってしまいます。
if: ${{ github.event.workflow_run.conclusion == ‘success’ }}
steps:
- name: 完了通知
run: |
echo “🚀 上流のCIが無事に成功したため、デプロイプロセスを開始します!”
echo “トリガー元の上流ワークフローID: ${{ github.event.workflow_run.id }}”
echo “実行ブランチ: ${{ github.event.workflow_run.head_branch }}”
- name: コードのチェックアウト(上流と同じコミットを取得)
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_branch }}
- name: デプロイシミュレーション
run: |
echo “📦 本番サーバーへファイルを転送中…”
echo “✨ デプロイが完了しました!お疲れ様です!”
—
4. この設計がもたらす圧倒的なメリット
上記のコードを見て、「おっ?」と気づいた方もいるかもしれません。
この `workflow_run` を使ったアプローチには、従来の「1つのファイルに全部書く」方法と比べて、圧倒的なアドバンテージがあります。
1. 関心の完全な分離(Fail Fast & Safe)
テストのロジックとデプロイのロジックが完全に別のファイル・別のコンテキストで動きます。もしテストが失敗した場合(`conclusion == ‘failure’`)、下流のデプロイジョブは `if` 条件によって自動的にスキップ(あるいは無視)されるため、バグったコードがデプロイされる悲劇を綺麗に防げます。
2. 実行ログとステータスの独立
GitHubの「Actions」タブを見るとわかりますが、上流のテスト結果と、下流のデプロイ結果がそれぞれの独立したパイプラインとして美しく可視化されます。「どこでコケたのか」が一目瞭然になります。
3. 別リポジトリ(マルチrepo)への拡張性
今回は同一リポジトリ内でしたが、ワークフロー名をリポジトリ名付き(例: `other-org/shared-infra/.github/workflows/deploy.yml` など、※クロスリポジトリの設定やPATが必要)に拡張することで、マイクロサービス間の厳格なリリースチェーンを構築できます。
—
先輩エンジニアからのアドバイス:さらに現場で活かすためのハック
最後に、現場でこの仕組みを運用する上で知っておくべき「ちょっとした裏技」を授けます。
- 成果物(Artifact)の受け渡し
上流でビルドした成果物(Dockerイメージやビルド済みアセットなど)を下流で使いたい場合は、上流で `actions/upload-artifact@v4` を使い、下流の `workflow_run` コンテキストから `actions/download-artifact` でダウンロードするのが王道パターンです。
- ループに注意
下流のワークフロー内でコードをプッシュするような処理を入れると、無限ループ(CIがCIを呼び続ける地獄)に陥ることがあります。下流はあくまで「デプロイや通知、E2Eテスト」といった読み取り・検証・適用に留めるのが鉄則です。
—
さあ、これでGitHub Actionsの `workflow_run` を使った階層化自動化の基礎はバッチリです。
これを導入すれば、あなたのチームの開発パイプラインは一段とプロフェッショナルで、堅牢なものに生まれ変わります。
これをマスターすれば、毎日の作業が劇的に楽になりますよ。ぜひ、あなたのプロジェクトでも試してみてくださいね!