このシリーズではアナロジーを使った説明中心となっていますが、あくまでもイメージをつかむための例えとなっております。
記事の内容が完全に正しいというわけではありませんのでご了承ください。
公式リンクを随時添付しておりますので、公式の説明も読むことをお勧めします。
今回の【アナロジー解説】シリーズ第二弾は GitHub Actions です。
アナロジーとは、ある事柄を別の似ている事柄に当てはめて理解・説明する「類推(るいすい)」のことです。
GitHub Actions とは
GitHub Actions は、「何かをきっかけに、GitHub が用意したサーバー上でコマンドを自動実行する仕組み」です。
よく使われる場面はこんなところです。
- コードを push したら、自動でテストを実行する
- プルリクエストを作ったら、自動でビルドが走る
- 毎朝決まった時間に、定期処理を実行する
手作業でやっていた繰り返し作業を、コードで定義して自動化できます。
厨房アナロジー
GitHub Actions の仕組みをレストランの厨房で例えてみましょう。
お客さんが注文を入れると(=コードが push されると)、厨房のシステムが自動で動き出します。どの担当が、どの順番で、何をするかはあらかじめ決めておいた手順書のとおりに進みます。シェフが毎回手動で指示を出す必要はありません。
Workflow / Job / Step の3層構造
GitHub Actions の設定は .github/workflows/*.yml という YAML ファイルに書きます。構造は3つの階層に分かれています。
Workflow(設定ファイル全体)
└── Job(どのサーバーで動かすか)
└── Step(1手順ずつの処理)
厨房アナロジーで対応させるとこうなります。
| 概念 | 役割 | 厨房アナロジー |
|---|---|---|
| Workflow | 「いつ・何をするか」の全体像 | 注文への対応手順全体 |
| Job | ランナー(サーバー)1台に割り当てる作業。複数あれば並列実行される | 前菜担当・メイン担当などの各ブース |
| Step | Job 内の1手順。上から順番に実行される | 切る→炒める→盛り付けるなどの各工程 |
Job が複数あれば、前菜担当とメイン担当が同時に動くように並列で動きます。一方 Step は必ず上から順番に実行されます。前の工程が終わらないと次には進めません。
実際の YAML はこのような形になります。
name: "サンプル Workflow"
on:
push: # push をトリガーにする
branches:
- main
jobs:
build: # Job の名前(自由につけてよい)
runs-on: ubuntu-latest # どの OS のサーバーで動かすか
steps:
- name: コードをチェックアウト
uses: actions/checkout@v4
- name: テストを実行
run: npm test
on: がトリガーの定義です。push を指定すれば push のたびに動き、schedule を使えば定期実行もできます。
トリガー(on:)の考え方
注文の取り方には種類があります。
- テーブルでの口頭注文(push や pull_request など、GitHub 上のイベント)
- 電話注文(外部からの API 呼び出し)
- ランチタイムの定番メニュー(
scheduleによる定期実行) - 店員が手動で厨房に指示(
workflow_dispatchによる手動実行)
よく使うトリガーをまとめると次のとおりです。
| トリガー | タイミング |
|---|---|
push |
ブランチへの push 時 |
pull_request |
PR の作成・更新時 |
schedule |
cron 形式で指定した時刻 |
workflow_dispatch |
GitHub の画面からボタンで手動実行 |
workflow_call |
別の Workflow から呼び出されたとき |
Actions タブで対象の Workflow を開くと、「Run workflow」ボタンが表示されます。
Composite Action
Composite Action とは
Composite Action は、複数の Step をまとめた「再利用できる部品」です。プログラムでいう関数に相当します。
厨房アナロジーでいうと、レシピカードです。「このソースを作るときはこの手順で」と1枚のカードにまとめておけば、どのシェフが担当しても同じ手順で作れます。何度も同じ工程を書く代わりに、カードを参照するだけで済みます。
ファイルは .github/actions/<名前>/action.yml に置きます。
# .github/actions/greeting/action.yml
name: "Greeting Action"
description: "名前を受け取ってメッセージを出力する"
inputs:
target_name:
description: "挨拶する相手の名前"
required: true
outputs:
message:
description: "生成した挨拶メッセージ"
value: ${{ steps.build_message.outputs.msg }}
runs:
using: "composite" # Composite Action の宣言
steps:
- name: Build message
id: build_message
shell: bash
run: |
msg="Hello, ${{ inputs.target_name }}!"
echo "msg=$msg" >> "$GITHUB_OUTPUT"
runs.using: "composite" が Composite Action の宣言です。inputs で値を受け取り、outputs で結果を返します。
Workflow から呼び出す
Workflow から呼び出すときは、steps: の下に uses: を書きます。
jobs:
greet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # ← 先に checkout が必要
- name: Greeting Action を実行
id: greeting
uses: ./.github/actions/greeting # ローカルの Action を参照
with:
target_name: "Taro"
- name: 出力を確認
run: echo "${{ steps.greeting.outputs.message }}"
actions/checkout@v4 が最初に必要な理由は、ランナー(サーバー)は最初リポジトリのファイルを持っていないからです。checkout してはじめてローカルの Action ファイルを読み込めます。
実行すると、Actions のログ上で Composite Action の Step が独立して表示されます。
Reusable Workflow
Reusable Workflow とは
Reusable Workflow は、別の Workflow から呼び出せる Workflow です。トリガーに workflow_call を指定することで実現します。
厨房アナロジーでいうと、系列店でも使える調理マニュアルです。同じチェーンの別店舗(別の Workflow)でも、このマニュアルを参照すれば同じ手順で料理を出せます。店舗ごとに独自のマニュアルを一から書く必要はありません。
Composite Action との違い
よく混乱するのが Composite Action との使い分けです。
| Composite Action | Reusable Workflow | |
|---|---|---|
| ファイルの場所 | .github/actions/ |
.github/workflows/ |
runs-on の指定 |
呼び出し元が決める | 自分で指定できる |
| Job を複数持てるか | 不可 | 可能 |
uses: を書く場所 |
steps: の下(step レベル) |
jobs: の下(job レベル) |
一番間違えやすいのは uses: を書く場所です。Composite Action は steps: の下、Reusable Workflow は jobs: の下に書きます。
# Reusable Workflow の定義
# .github/workflows/_reusable-hello.yml
on:
workflow_call: # Reusable Workflow のトリガー
inputs:
name:
required: true
type: string
jobs:
greet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/greeting
with:
target_name: ${{ inputs.name }}
呼び出す側はこうなります。
jobs:
call-reusable:
uses: ./.github/workflows/_reusable-hello.yml # job レベルで uses
with:
name: "Taro"
secrets: inherit # 呼び出し元の secrets を引き継ぐ
secrets: inherit を書かないと、呼び出し先の Workflow で API キーなどの secrets が使えなくなります。忘れがちなので注意が必要です。
実行すると、Actions のログ上で Reusable Workflow が入れ子の Workflow として表示されます。
3層構造をまとめる
ここまで説明してきた3つの概念は、実際の現場ではこのような階層で組み合わせて使います。
[エントリポイント Workflow] 例:deploy.yml
→ トリガー・パラメータの受け付け
↓ job レベルで uses:
[Reusable Workflow] 例:_terraform-plan.yml
→ ランナー指定・処理の順序制御
↓ step レベルで uses:
[Composite Action] 例:.github/actions/setup/action.yml
→ 具体的な処理の部品
3層の呼び出し関係を図で整理するとこうなります。
なぜ3層に分けるのか、というと理由は3つです。
- 再利用できる。Reusable Workflow を複数のエントリポイントから呼べる
- 責務を分けられる。「何を実行するか」と「どう実行するか」を別々に管理できる
- 変更が局所化できる。処理を変えるときに Composite Action だけ直せばよい
厨房でいうと、フロアスタッフ(エントリポイント)が注文を受け、調理マニュアル(Reusable Workflow)に沿って厨房が動き、各レシピカード(Composite Action)が個別の料理を担当する、という分業です。
まとめ
| 概念 | 説明 |
|---|---|
| Workflow |
on: で指定したトリガーをきっかけに動く処理全体 |
| Job | ランナー1台に割り当てる作業。複数あれば並列実行 |
| Step | Job 内の1手順。上から順番に実行される |
| Composite Action | Step をまとめた再利用できる部品。steps: の下で呼び出す |
| Reusable Workflow | 別の Workflow から呼び出せる Workflow。jobs: の下で呼び出す |
secrets: inherit |
Reusable Workflow に呼び出し元の secrets を引き継ぐ宣言 |
最初は「Composite Action と Reusable Workflow の違い」や「uses: を書く場所」で混乱することが多いと思います。厨房アナロジーと合わせて、3層構造の図を頭に置いておくと整理しやすいです。
また、近日中に少し実践寄りですが、Github Actions で AI に自動コードレビューをしてもらう機能の実装について書く予定です。


