- Git
GitHub Actions再利用可能ワークフロー|compositeとの違い
再利用可能ワークフローは、on: workflow_call を書いたワークフローを、別のワークフローの「ジョブ」として呼び出す仕組みです。 複数のジョブ・ランナーごとまとめて使い回したいときは再利用可能ワークフロー、ジョブの中の「ステップ」をまとめたいときは composite action を使います。
# 呼び出される側:.github/workflows/reusable-test.yml
on:
workflow_call:
inputs:
node-version:
type: string
default: "22"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: ${{ inputs.node-version }}
- run: npm ci && npm test
# 呼び出す側:.github/workflows/ci.yml
on: [pull_request]
jobs:
test:
uses: ./.github/workflows/reusable-test.yml # steps ではなく jobs の直下に書く
with:
node-version: "24"
| 項目 | 再利用可能ワークフロー | composite action |
|---|---|---|
| 呼び出す場所 | ジョブ(jobs.<id>.uses) |
ステップ(steps[*].uses) |
| 置き場所 | .github/workflows/ 直下の1ファイル |
action.yml を置いたフォルダかリポジトリ |
| 中身 | 複数のジョブ(ランナーをジョブごとに選べる) | ステップの並び(呼び出し元のランナーで動く) |
| secrets | 使える(渡すか secrets: inherit) |
secrets コンテキストは使えない。inputs で渡す |
| 入れ子 | 呼び出し元を含めて10段まで | 1つのワークフローで10個まで |
確認環境:この記事の YAML は actionlint 1.7.12(GitHub リリースのバイナリ)と check-jsonschema 0.38.2(SchemaStore のスキーマ)で検査し、検出されたエラー文をそのまま載せています。入れ子の上限・権限・secrets の決まりは GitHub Docs と GitHub Changelog(2025年11月6日)で確かめています。アクションの版(actions/checkout v7.0.1・actions/setup-node v7.1.0)は git ls-remote でタグを確かめました(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GitHub Actions再利用可能ワークフロー|compositeとの違い」
再利用可能ワークフローの書き方
呼び出される側(workflow_call)
on.workflow_call の下に、受け取る値(inputs)・秘密情報(secrets)・返す値(outputs)を書きます。
# .github/workflows/reusable-test.yml
name: reusable-test
on:
workflow_call:
inputs:
node-version:
description: 使う Node.js の版
type: string
default: "22"
run-e2e:
type: boolean
default: false
shard-count:
type: number
default: 1
secrets:
NPM_TOKEN:
required: false
outputs:
coverage:
description: 行カバレッジ(%)
value: ${{ jobs.test.outputs.coverage }}
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
outputs:
coverage: ${{ steps.cov.outputs.pct }}
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-node-deps
with:
node-version: ${{ inputs.node-version }}
npm-token: ${{ secrets.NPM_TOKEN }}
- run: npm test -- --coverage
- id: cov
run: echo "pct=87.5" >> "$GITHUB_OUTPUT"
- if: ${{ inputs.run-e2e }}
run: npm run e2e -- --shard-count=${{ inputs.shard-count }}
| キー | 書けるもの | 注意 |
|---|---|---|
inputs.<名前>.type |
string・number・boolean |
必須。呼び出し側の値の型が合わないとエラー |
inputs.<名前>.required |
true / false |
default と組み合わせる |
secrets.<名前>.required |
true / false |
required: true は「渡されたか」だけを見る(空の値でも通る) |
outputs.<名前>.value |
${{ jobs.<ジョブ>.outputs.<名前> }} |
ジョブの outputs を経由する。ステップの outputs は直接書けない |
ファイルは .github/workflows/ の直下に置きます。 GitHub Docs には「Subdirectories of the workflows directory are not supported.」とあります。
呼び出す側
# .github/workflows/ci.yml
name: ci
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
test:
strategy:
fail-fast: false
matrix:
node: ["22", "24"]
uses: ./.github/workflows/reusable-test.yml
with:
node-version: ${{ matrix.node }}
run-e2e: ${{ github.event_name == 'push' }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
report:
needs: test
runs-on: ubuntu-latest
steps:
- run: echo "coverage=${{ needs.test.outputs.coverage }}"
呼び出すジョブには runs-on も steps も書きません。 GitHub Docs で呼び出すジョブに書けるとされているキーは次の通りです。
| キー | 使いどころ |
|---|---|
name |
表示名 |
uses |
呼び出すワークフロー |
with |
inputs に渡す値 |
secrets |
secrets に渡す値、または inherit |
strategy |
matrix で複数回呼ぶ |
needs / if |
順番と条件 |
concurrency |
同時実行の制御 |
permissions |
呼び出し先に渡す GITHUB_TOKEN の権限 |
cache-mode |
キャッシュの読み書きの範囲(read・write・write-only・none) |
matrix で呼んだときの outputs は、値を設定した最後の成功した実行の値になります(GitHub Docs)。matrix の行ごとの値を集めたいときは、行ごとに名前を変えた artifact に書き出す方法があります。
uses の書き方
| 書き方 | 意味 |
|---|---|
./.github/workflows/test.yml |
同じリポジトリ・同じコミットのファイル |
octo-org/shared/.github/workflows/test.yml@v1 |
別のリポジトリ(タグ) |
octo-org/shared/.github/workflows/test.yml@0123abcd...(40文字) |
別のリポジトリ(コミット SHA)。GitHub Docs はこの形を勧めている |
$/.github/workflows/test.yml |
同じリポジトリの新しい書き方。@ref は付けない。GitHub Enterprise Server では使えない |
uses には ${{ }} の式を書けません。 GitHub Docs には「You cannot use contexts or expressions in this keyword.」とあります。
secrets の渡し方と secrets: inherit
| 書き方 | 渡るもの | 使える範囲 |
|---|---|---|
secrets: { NPM_TOKEN: ${{ secrets.NPM_TOKEN }} } |
書いたものだけ | どこでも |
secrets: inherit |
呼び出し元が見えるすべての secrets | 同じ組織、または同じ Enterprise の中 |
secrets は、直接呼び出したワークフローにだけ渡ります。 GitHub Docs には「Secrets are only passed to directly called workflow.」とあり、A → B → C と呼ぶとき、C で使う secrets は B が改めて渡す必要があります。
環境(environment)の secrets は、呼び出し側からは渡せません。 呼び出すジョブには environment を書けず、呼び出される側のジョブに environment を書いてその secrets を読みます。同じ名前の secrets があるときは environment の secrets が使われます。
env も引き継がれません。GitHub Docs の決まりです。
| 渡したいもの | 渡り方 |
|---|---|
呼び出し元のワークフローの env |
渡らない。with に書くと actionlint は context "env" is not allowed here |
呼び出される側の env |
呼び出し元からは見えない |
組織・リポジトリ・環境の変数(vars) |
両方で ${{ vars.NAME }} として読める |
| 呼び出される側の結果 | outputs で返す |
入れ子(ネスト)と上限
再利用可能ワークフローは、呼び出し元を含めて10段までつなげられます。 2025年11月6日の GitHub Changelog で、4段から10段、呼び出せる数が20から50に引き上げられました。
| 上限 | github.com | 出典 |
|---|---|---|
| 入れ子の段数 | 10段(呼び出し元 + 再利用可能ワークフロー9段) | GitHub Docs |
| 1つのワークフローファイルから呼べる種類 | 50(入れ子の先も数える) | GitHub Docs |
| ループ | 不可(「Loops in the workflow tree are not permitted.」) | GitHub Docs |
| composite action の入れ子 | 1つのワークフローで10個まで | GitHub Docs |
GitHub Enterprise Server では版によって上限が異なるので、使っている版の Docs を見ます。
入れ子のコピペ例:ci → release → deploy
# ci.yml の jobs に足す
release:
if: github.ref == 'refs/heads/main'
needs: test
permissions:
contents: read
id-token: write
uses: ./.github/workflows/reusable-release.yml
with:
environment: production
secrets: inherit
# .github/workflows/reusable-release.yml(2段目)
name: reusable-release
on:
workflow_call:
inputs:
environment:
type: string
required: true
jobs:
deploy:
permissions:
contents: read
id-token: write
uses: ./.github/workflows/reusable-deploy.yml
with:
environment: ${{ inputs.environment }}
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # 3段目へは改めて渡す
# .github/workflows/reusable-deploy.yml(3段目)
name: reusable-deploy
on:
workflow_call:
inputs:
environment:
type: string
required: true
secrets:
SLACK_WEBHOOK_URL:
required: true
outputs:
url:
value: ${{ jobs.deploy.outputs.url }}
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
permissions:
contents: read
id-token: write
outputs:
url: ${{ steps.deploy.outputs.url }}
steps:
- uses: actions/checkout@v7
- id: deploy
run: echo "url=https://example.com" >> "$GITHUB_OUTPUT"
- name: 通知
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
curl -fsS -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"deployed ${{ inputs.environment }}\"}" "$SLACK_WEBHOOK_URL"
この記事の4つのワークフローと composite action を actionlint 1.7.12 で検査した結果です。
actionlint
echo $?
# 0(指摘なし)
権限(permissions)の受け渡し
呼び出される側は、呼び出し元から受け取った GITHUB_TOKEN の権限を「同じか、狭く」しかできません。 GitHub Docs の決まりです。
| 状況 | 結果 |
|---|---|
呼び出すジョブに permissions が無い |
既定の GITHUB_TOKEN の権限が渡る(ワークフローの最上位に書いた permissions があればそれ) |
| 呼び出される側で同じか狭い権限を書く | その権限になる |
| 呼び出される側で広い権限を書く | 実行時にエラー |
| A → B → C の入れ子 | 段を下るほど同じか狭くなる。A が packages: read なら B・C は packages: write にできない |
広い権限を求めたときのエラーは、次の形です(実際に報告された文面)。
The nested job 'message-check' is requesting 'pull-requests: read', but is only allowed 'pull-requests: none'.
直し方は、呼び出す側のジョブで先に権限を与えることです。 上の入れ子の例で ci.yml の release ジョブに id-token: write を書いているのは、3段目で OIDC のトークンを取るためです。なお、この「広げられない」誤りは actionlint 1.7.12 では検出されませんでした(3段目を contents: write にしても指摘なし)。
OIDC で AWS に入る設定は、関連記事「GitHub ActionsからOIDCでAWSへ|IAMロールの信頼ポリシー」で扱っています。再利用可能ワークフローから OIDC を使うと、トークンの job_workflow_ref に呼び出された側のワークフローのパスと ref が入ります。
composite action の書き方
composite action は、複数のステップを1つのステップとしてまとめたものです。 呼び出し元のジョブと同じランナーで動き、チェックアウトしたファイルや環境もそのまま使えます。
# .github/actions/setup-node-deps/action.yml
name: setup-node-deps
description: Node.js を入れて npm ci する
inputs:
node-version:
description: Node.js の版
required: false
default: "22"
npm-token:
description: private パッケージ用のトークン
required: false
default: ""
outputs:
cache-hit:
description: キャッシュが当たったか
value: ${{ steps.node.outputs.cache-hit }}
runs:
using: composite
steps:
- id: node
uses: actions/setup-node@v7
with:
node-version: ${{ inputs.node-version }}
cache: npm
- run: npm ci
shell: bash
env:
NODE_AUTH_TOKEN: ${{ inputs.npm-token }}
# 呼び出す側(ステップとして使う)
steps:
- uses: actions/checkout@v7 # ローカルの action を使う前にチェックアウトが要る
- id: deps
uses: ./.github/actions/setup-node-deps
with:
node-version: "24"
npm-token: ${{ secrets.NPM_TOKEN }} # secrets は inputs で渡す
- run: echo "cache-hit=${{ steps.deps.outputs.cache-hit }}"
| 決まり | 内容 |
|---|---|
runs.using |
composite |
run のステップ |
shell が必須(GitHub Docs「Required if run is set.」) |
secrets |
使えない。GitHub Docs「The secrets context is not available for composite actions due to security reasons.」 |
| inputs | ${{ inputs.<名前> }} で読む。INPUT_<名前> の環境変数は自動では作られない |
| outputs | value に ${{ steps.<id>.outputs.<名前> }} を書く |
| 書けないキー | timeout-minutes など(check-jsonschema で Additional properties are not allowed ('timeout-minutes' was unexpected)) |
actionlint は action.yml の中身を検査しません。 action.yml を渡すと "jobs" section is missing in workflow となりました。呼び出し側の inputs の誤りは actionlint が見つけ、action.yml の書き方は check-jsonschema の --builtin-schema vendor.github-actions で検査できました。
check-jsonschema --builtin-schema vendor.github-actions .github/actions/*/action.yml
check-jsonschema --builtin-schema vendor.github-workflows .github/workflows/*.yml
再利用可能ワークフローと composite action の比較表
GitHub Docs の比較をもとに、書き方の違いを足した表です。
| 比べる点 | 再利用可能ワークフロー | composite action |
|---|---|---|
| 呼び出し | jobs.<id>.uses |
steps[*].uses |
| ファイル | .github/workflows/*.yml(サブフォルダ不可) |
<フォルダ>/action.yml |
| ジョブ・ランナー | 複数のジョブ。ジョブごとに runs-on |
ジョブを持たない。呼び出し元のランナー |
| ログ | ジョブ・ステップごとに表示 | 1つのステップとして表示 |
| secrets | 渡せる・inherit できる |
inputs で渡す |
| environment(承認・環境 secrets) | 呼び出される側のジョブに書ける | 書けない(呼び出し元のジョブで指定) |
| permissions | ジョブごとに書ける(広げられない) | 書けない(呼び出し元のジョブの権限) |
| 結果の返し方 | outputs(ジョブの outputs 経由) |
outputs(ステップの outputs 経由) |
| 入れ子 | 10段まで | 1つのワークフローで10個まで |
| Marketplace | 公開できない | 公開できる |
| 向いている用途 | ビルド→テスト→デプロイの流れを組織で共通化 | セットアップ・キャッシュ・通知など数ステップの部品 |
迷ったら「ランナーやジョブを分けたいか」「secrets・environment をまとめて扱いたいか」で決めます。 どちらも当てはまらない数ステップの部品は composite action が軽く書けます。
actionlint で検出できた誤り・できなかった誤り
actionlint 1.7.12 で、わざと誤りを入れて検査した結果です。
| 誤り | actionlint の出力(原文) |
|---|---|
呼び出すジョブに runs-on |
when a reusable workflow is called with "uses", "runs-on" is not available. only following keys are allowed: "name", "uses", "with", "secrets", "needs", "if", and "permissions" in job "a" |
呼び出すジョブに steps |
... "steps" is not available. ... |
呼び出すジョブに environment |
... "environment" is not available. ... |
| 定義していない input | input "python-version" is not defined in "./.github/workflows/reusable-test.yml" reusable workflow. defined inputs are "node-version", "run-e2e", "shard-count" |
| 必須の input を渡さない | input "env-name" is required by "./.github/workflows/r2.yml" reusable workflow |
| number の input に文字列 | input "shard-count" is typed as number by reusable workflow "./.github/workflows/reusable-test.yml". string value cannot be assigned |
| 定義していない secret を渡す | secret "OTHER" is not defined in "./.github/workflows/reusable-test.yml" reusable workflow. defined secret is "NPM_TOKEN" |
| 返していない outputs を読む | property "cov" is not defined in object type {} |
outputs.value にステップの値 |
context "steps" is not allowed here. available contexts are "github", "inputs", "jobs", "vars". |
with で env を使う |
context "env" is not allowed here. available contexts are "github", "inputs", "matrix", "needs", "strategy", "vars". |
uses に式 |
context "github" is not allowed here. no context is available here. |
別リポジトリの uses に @ref が無い |
reusable workflow call "octo-org/shared/.github/workflows/build.yml" at "uses" is not following the format "owner/repo/path/to/workflow.yml@ref" nor "./path/to/workflow.yml". |
| composite action の必須 input が無い | missing input "token" which is required by action "bad-comp" defined at "./.github/actions/bad-comp". all required inputs are "token" |
検出されなかったものも記録しておきます。GitHub 上で実行すると失敗するか、意図と違う動きになるものです。
| 誤り | actionlint 1.7.12 |
|---|---|
ステップの uses に再利用可能ワークフローを書く |
指摘なし |
.github/workflows/sub/ に置いたワークフローを呼ぶ |
指摘なし |
string の input に数値 24、boolean の input に "yes" |
指摘なし |
| 呼び出される側で権限を広げる | 指摘なし |
$/.github/workflows/... の書き方 |
書式違反として誤って指摘される |
呼び出すジョブの cache-mode |
unexpected key "cache-mode" for "job" section と誤って指摘される |
呼び出すジョブの strategy・concurrency |
指摘なし(正しく通る) |
$/ と cache-mode は GitHub Docs に載っている新しい書き方ですが、actionlint 1.7.12 ではエラーになります。 使う場合は、actionlint の -ignore で該当のメッセージを除くか、従来の ./.github/workflows/... で書きます。
actionlint -ignore 'unexpected key "cache-mode"'
よくあるエラーと直し方
| 症状 | 原因 | 直し方 |
|---|---|---|
| 呼び出したワークフローが見つからない | @ref の誤り、private リポジトリのアクセス設定 |
呼び出される側のリポジトリの Settings → Actions → Access で、呼び出し元のリポジトリを許可する |
| secrets が空になる | 入れ子の2段目で渡し直していない/environment の secrets を呼び出し元で読もうとした | 各段で secrets: を書く。environment は呼び出される側のジョブに書く |
is requesting ..., but is only allowed ... |
呼び出される側が広い権限を求めた | 呼び出すジョブの permissions で先に与える |
env の値が使えない |
env は引き継がれない |
with で渡すか vars を使う |
| 名前を変えたら呼び出しが失敗 | GitHub はリダイレクトしない(GitHub Docs) | uses のパスを新しい名前に直す |
| 呼び出し元ごとキャンセルされる | 呼び出し元と呼び出される側で同じ concurrency.group に cancel-in-progress: true |
呼び出される側の ${{ github.workflow }} は呼び出し元の名前になるので、グループ名を分ける |
public のリポジトリからは public の再利用可能ワークフローしか呼べません。 private のリポジトリからは private と public の両方を呼べます。GitHub がホストするランナーの割り当てと課金は、呼び出し元のリポジトリで決まります。
よくある質問
Q. 呼び出した側のファイルを更新したのに、再実行で前の版が動きます。
A. GitHub Docs によると、「失敗したジョブを再実行」は最初の実行と同じコミット SHA の再利用可能ワークフローを使います。「すべてのジョブを再実行」は uses の ref が指す最新の版を使います。
Q. 別リポジトリのワークフローは、タグとコミット SHA のどちらで指定しますか? A. GitHub Docs は、安定性と安全性の理由からコミット SHA を勧めています。タグは後から付け替えられるためです。SHA で固定したときの更新の自動化は、関連記事「Dependabot・Renovate設定|目的別コピペ設定集と比較表」で扱っています。
Q. 呼び出される側で github コンテキストは何を指しますか?
A. GitHub Docs では、呼び出される側の github コンテキストは呼び出し元のワークフローのものになります(github.workflow が呼び出し元の名前になるのもこのためです)。
GitHub Actions の基本は関連記事「CI/CDとは|GitHub Actionsで最初のパイプラインを作るまで」、キャッシュと matrix は「GitHub Actionsのキャッシュとmatrix|コピペ用YAMLとキー設計」で扱っています。
まとめ
- ジョブごと使い回すなら再利用可能ワークフロー(
on: workflow_call→jobs.<id>.uses)、ステップをまとめるなら composite action - inputs は
string・number・boolean。outputs はジョブの outputs を経由して返す secrets: inheritは同じ組織・Enterprise の中だけ。secrets は直接呼んだ先にしか渡らないenvは引き継がれない。withかvars- 入れ子は10段・50種類まで(2025年11月に4段・20から引き上げ)
- 権限は呼び出し元で与え、呼び出される側は狭めるだけ
- actionlint は inputs・secrets・outputs の誤りを見つけるが、権限の広げすぎ・サブフォルダ・
action.ymlの中身は見ない。$/とcache-modeは誤って指摘される
参考・出典
確認日はいずれも 2026年10月13日です。
- GitHub Docs「Reuse workflows」:https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows
- GitHub Docs「Reusable workflows reference」:https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations
- GitHub Docs「Reusing workflow configurations」:https://docs.github.com/en/actions/concepts/workflows-and-actions/reusing-workflow-configurations
- GitHub Docs「Metadata syntax reference」:https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax
- GitHub Docs「Contexts reference」:https://docs.github.com/en/actions/reference/workflows-and-actions/contexts
- GitHub Changelog「New releases for GitHub Actions – November 2025」:https://github.blog/changelog/2025-11-06-new-releases-for-github-actions-november-2025
- rhysd/actionlint v1.7.12:https://github.com/rhysd/actionlint
- check-jsonschema:https://github.com/python-jsonschema/check-jsonschema
- Eclipse platform-dev メーリングリスト(権限エラーの文面):https://www.eclipse.org/lists/platform-dev/msg03876.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「GitHub Actions再利用可能ワークフロー|compositeとの違い」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。