言語を切り替える
テーマを切り替える

GitHub Actions 複合 Action 開発:action.yml から Marketplace 公開まで

画面に映るのは、15 回目の失敗ログ。原因はシンプル——あるプライベートリポジトリの npm installNODE_AUTH_TOKEN を渡し忘れていた。

今週だけで 3 回目です。8 リポジトリすべてに、checkout、setup-node、install、build、test がほぼコピペ。1 箇所直すたびに 8 箇所を同期。Node のバージョンアップ時は 5 つ更新して、残り 3 つを忘れる——そんな日々でした。

もう限界だと思ったとき、目に付いたのが GitHub Actions の複合 Action(Composite Action)です。繰り返しステップを 1 つのコンポーネントにまとめ、関数のようにワークフロー間で呼び出せます。本記事では、最初の 1 個を作るところから Marketplace 公開まで、CI/CD コンポーネント化の実践を順に追います。

複合 Action の基本

複合 Action とは

複合 Action は、GitHub Actions が提供するコンポーネント化の仕組みです。複数の steps を 1 つの Action にまとめ、ワークフロー間で再利用できます。

JavaScript Action や Docker Action と違い、コードは不要。YAML でステップ列を定義するだけで GitHub が実行します。イメージとしては、steps を関数のようにまとめたものに近いです。

公式定義では runs.using: "composite" で識別され、すべてのステップは同じ Runner 上で動きます。作業ディレクトリや環境変数に触れ、他の Action を uses で呼び出すこともできます。

3 種類の Action 比較

種類実装向いている用途
JavaScript ActionJS/TS を記述複雑なロジック、API 呼び出し
Docker ActionDockerfile を記述特定ランタイム、依存の固定
複合 Action純 YAML既存ステップの組み合わせ、素早い再利用

複合 Action の強みは、コード・ビルド・依存管理が不要なこと。YAML だけで済み、開発と保守が速い点です。

複合 Action と再利用可能ワークフロー

どちらも「再利用」ですが、レイヤが違います。

複合 Action は Job 内のステップ群。呼び出し元の Runner を使い、Secrets は明示的に渡します。

再利用可能ワークフロー はパイプライン全体。独立した Job を作り、Runner も別指定でき、Secrets は自動継承します。

「依存インストール + テスト」だけ共通化したいなら複合 Action。「ビルド → テスト → デプロイ」全体を揃えたいなら再利用可能ワークフロー。後述の比較章で詳しく見ます。

最初の複合 Action を作る

action.yml の構造

複合 Action の中心は action.yml。名前、inputs、outputs、実行 steps をここで定義します。

最小例:

name: 'Hello World'
description: 'A simple composite action'
runs:
  using: "composite"
  steps:
    - run: echo "Hello from composite action!"
      shell: bash

実運用ではパラメータと outputs が必要になります。

実用的な action.yml の例

Node.js プロジェクト向けのビルド+テスト Action です。

name: 'Build and Test'
description: 'Install dependencies, build project, and run tests'
author: 'Your Name'

inputs:
  node-version:
    description: 'Node.js version to use'
    required: true
    default: '20'
  install-command:
    description: 'Command to install dependencies'
    required: false
    default: 'npm ci'
  build-command:
    description: 'Command to build the project'
    required: false
    default: 'npm run build'
  test-command:
    description: 'Command to run tests'
    required: false
    default: 'npm test'

outputs:
  build-path:
    description: 'Path to the build output'
    value: ${{ steps.build.outputs.path }}
  test-coverage:
    description: 'Test coverage percentage'
    value: ${{ steps.coverage.outputs.value }}

runs:
  using: "composite"
  steps:
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: ${{ inputs.install-command }}
      shell: bash

    - name: Build project
      id: build
      run: |
        ${{ inputs.build-command }}
        echo "path=dist" >> $GITHUB_OUTPUT
      shell: bash

    - name: Run tests
      id: coverage
      run: |
        ${{ inputs.test-command }}
        echo "value=85" >> $GITHUB_OUTPUT
      shell: bash

各フィールドの要点

inputs — Action が受け取る引数。

  • description:Marketplace にも表示される説明
  • required:必須かどうか
  • default:省略時の既定値

outputs — 呼び出し元へ返す値。$GITHUB_OUTPUT 経由で渡します。

echo "name=value" >> $GITHUB_OUTPUT

runs.steps — 通常のワークフローに近いですが、次の 2 点が必須です。

  1. shell の明示指定 — 各 runshell: bash(または shpwsh)が必要
  2. uses で他 Action を呼べる — 上記の actions/setup-node@v4 のように

よくあるつまずき

inputs に type がない

inputs は string のみ。再利用可能ワークフローの type: boolean / type: number は使えません。真偽値は "true" / "false" を渡してステップ内で判定します。

shell 省略不可

通常ワークフローでは run の shell を省略できますが、複合 Action では省略するとエラーになります。

outputs は step id 経由

outputs:
  my-output:
    value: ${{ steps.my-step.outputs.result }}

対応するステップに id が必要です。

- id: my-step
  run: echo "result=hello" >> $GITHUB_OUTPUT
  shell: bash

複合 Action の使い方

同一リポジトリ内(ローカル参照)

Action が .github/actions/build-test/action.yml にある場合:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: ./.github/actions/build-test
        with:
          node-version: '20'
          test-command: 'npm run test:ci'

./ 始まりのパスはリポジトリルート基準。チーム内共有向きで、Marketplace 公開は不要です。

リポジトリをまたぐ参照

専用リポジトリに Action を置き、他リポジトリから呼び出します。

steps:
  - uses: your-org/shared-actions/build@v1
    with:
      node-version: '18'

形式は owner/repo/path@versionpath は Action ディレクトリへの相対パスです。

組織向けリポジトリ構成の例

shared-actions/
├── build/
│   └── action.yml
├── deploy/
│   └── action.yml
├── lint/
│   └── action.yml
└── README.md

参照例:

  • your-org/shared-actions/build@v1
  • your-org/shared-actions/deploy@v1

Marketplace から使う

公開後は検索・参照が可能です。

steps:
  - uses: your-org/[email protected]
    with:
      node-version: '20'

バージョン選択、利用統計、README 表示などが揃い、オープンソース向けに適しています。

バージョン指定の考え方

# 方式 1:commit SHA(最安全・不変)
- uses: your-org/action@a1b2c3d4e5f6...

# 方式 2:セマンティックバージョン tag
- uses: your-org/[email protected]

# 方式 3:major tag(最新 v1.x を追従)
- uses: your-org/action@v1

# 非推奨:latest(意図しない更新のリスク)
# - uses: your-org/action@latest

本番は commit SHA が最も安全。tag が差し替わっても SHA は変わりません。

社内プロジェクトなら major tag@v1)で v1.x の修正を自動取り込みする運用も現実的です。

@latest は避けましょう。不意のアップグレードでビルドが壊れることがあります。

複合 Action vs 再利用可能ワークフロー

機能比較

項目複合 Action再利用可能ワークフロー
実行単位Job 内の steps独立した Job
Runner呼び出し元と共有新規(または指定)
Secrets明示的に渡す自動継承
入力型string のみboolean / number / string
出力$GITHUB_OUTPUToutputs + workflow_call
並行制御呼び出し元に従う個別設定可
環境変数継承+追加独立スコープ
向いている用途単機能のカプセル化パイプライン全体の標準化

選び方

複合 Action が向くケース

  • ビルド/テスト/デプロイなど、繰り返し steps の共通化
  • 同一 Job 内で他 steps と状態を共有したい
  • ワークフロー全体は柔軟に保ち、一部だけ再利用したい
  • Secrets の受け渡しを厳密に制御したい

再利用可能ワークフローが向くケース

  • CI/CD パイプライン全体の標準化
  • 複数プロジェクトで同一フローを強制したい
  • Secrets の自動継承で設定を減らしたい
  • iftimeout-minutes など Job/ワークフロー級の設定が必要

組み合わせる

再利用可能ワークフローの中で複合 Action を呼ぶ、が実務ではよく効きます。

# .github/workflows/ci.yml(再利用可能ワークフロー)
on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: ./.github/actions/build-test
        with:
          node-version: ${{ inputs.node-version }}

ワークフロー級の標準設定と、Action 級の step 再利用を両立できます。

バージョン管理と公開

Git タグの運用

公開の鍵はタグ管理。セマンティックバージョン + major tag の二段構えがおすすめです。

# セマンティックバージョン tag
git tag -a v1.0.0 -m "Initial release"
git push origin v1.0.0

# major tag(最新 v1.x を指す)
git tag -fa v1 -m "Update v1 tag to latest"
git push origin v1 --force

v1.1.0 リリース時:

git tag -a v1.1.0 -m "Add new feature"
git push origin v1.1.0

git tag -fa v1 -m "Update v1 tag to v1.1.0"
git push origin v1 --force

利用者は @v1.1.0 で固定、@v1 で v1 系の更新を取り込めます。

Marketplace 公開手順

1. README.md

  • Action 名と概要
  • Inputs / Outputs の説明
  • 利用例
  • ライセンス

2. action.yml

namedescriptionauthorbranding(任意)を揃えます。

3. Release 作成

GitHub リポジトリで:

  1. Releases → Draft a new release
  2. タグ(例 v1.0.0)を選択
  3. Release Notes を記入
  4. Publish this Action to the GitHub Marketplace にチェック
  5. 公開

GitHub が action.yml を検証し、Marketplace に載ります。

公開の自動化

tag プッシュで major tag 更新と Release 作成を自動化する例:

name: Release Action

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Update major tag
        run: |
          # major バージョン番号を抽出
          MAJOR=$(echo $GITHUB_REF | sed 's/refs\/tags\/v\([0-9]*\).*/\1/')

          # major tag を更新
          git config user.name github-actions
          git config user.email [email protected]
          git tag -fa v$MAJOR -m "Update v$MAJOR tag"
          git push origin v$MAJOR --force

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true

応用テクニックとベストプラクティス

Secrets の安全な受け渡し

複合 Action は secrets コンテキストに直接触れません。

# ワークフロー側
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: ./.github/actions/deploy
        with:
          token: ${{ secrets.DEPLOY_TOKEN }}
        env:
          AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
# action.yml 側
inputs:
  token:
    description: 'Deploy token'
    required: true

runs:
  using: "composite"
  steps:
    - run: deploy --token ${{ inputs.token }}
      shell: bash
      env:
        AWS_ACCESS_KEY: ${{ env.AWS_ACCESS_KEY }}

セキュリティのポイント

  • 機密値は inputs より env 優先(ログに残りにくい)
  • inputs 経由はマスクされるが、設計上 env の方が安全
  • README に必要な Secrets を明記する

ローカルスクリプトの利用

複雑な処理は YAML よりスクリプトへ。

.github/actions/build-test/
├── action.yml
└── scripts/
    └── build.sh
runs:
  using: "composite"
  steps:
    - run: $GITHUB_ACTION_PATH/scripts/build.sh
      shell: bash

$GITHUB_ACTION_PATH は Action ルートへのパスです。

組織向け Action リポジトリ

your-org/shared-actions/
├── .github/
│   └── workflows/
│       └── test.yml
├── build/
│   ├── action.yml
│   └── README.md
├── deploy/
│   ├── action.yml
│   └── README.md
├── lint/
│   ├── action.yml
│   └── README.md
└── README.md

各サブディレクトリが 1 Action。README とテストをセットにします。

落とし穴とデバッグ

ネスト深度

複合 Action の入れ子は最大 10 層。3 層以内を推奨します。

環境変数のスコープ

step 内の env はその step だけ有効。跨ぎたい場合は GITHUB_ENV を使います。

steps:
  - run: echo "MY_VAR=value" >> $GITHUB_ENV
    shell: bash
  - run: echo $MY_VAR
    shell: bash

デバッグ

  1. ACTIONS_STEP_DEBUG=true で詳細ログ
  2. step 内の echo で変数確認
  3. tmate Action で SSH デバッグ(本番では非推奨)

まとめ

複合 Action は、繰り返し CI 設定から解放してくれるコンポーネント化の要です。関数のように steps をカプセル化できます。

覚えておきたい 3 点:

構造をはっきり — action.yml で inputs/outputs/steps を定義。パラメータ化で柔軟に、outputs で結果を返す。

用途で選ぶ — 単機能は複合 Action、パイプライン全体は再利用可能ワークフロー。組み合わせが最強。

バージョンは慎重に — 本番は commit SHA、社内は major tag。latest は避ける。

次の一歩:プロジェクトで build-test を 1 つの Action にまとめ、問題なければ Marketplace でチームやコミュニティに共有してみてください。

GitHub Actions 複合 Action を開発する

ゼロから再利用可能な複合 Action を作り、ビルド/テストステップをパッケージ化する

⏱️ 目安時間: 30 分

  1. 1

    ステップ1: Action ディレクトリを用意

    リポジトリ内に複合 Action 用ディレクトリを作成:

    • mkdir -p .github/actions/build-test
    • action.yml を作成
  2. 2

    ステップ2: action.yml を記述

    inputs、outputs、実行ステップを定義:

    • inputs で node-version や test-command などを定義
    • outputs で build-path や coverage を定義
    • runs.steps には必ず shell: bash を指定
  3. 3

    ステップ3: ローカル参照でテスト

    ワークフローから参照して動作確認:

    • uses: ./.github/actions/build-test
    • with: node-version: '20'
    • ローカルで通ったら公開へ
  4. 4

    ステップ4: Git タグを作成

    セマンティックバージョンと major tag を併用:

    • git tag -a v1.0.0 -m 'Initial release'
    • git tag -fa v1 -m 'Update v1 tag'
    • git push origin v1.0.0 v1
  5. 5

    ステップ5: Marketplace に公開

    GitHub UI から公開:

    • Releases → Draft a new release
    • タグ(例 v1.0.0)を選択
    • Publish to Marketplace にチェック
    • GitHub が action.yml を検証して公開

FAQ

複合 Action と再利用可能ワークフローの違いは?
複合 Action は Job 内のステップ群で、呼び出し元の Runner を使い、Secrets は明示的に渡す必要があります。再利用可能ワークフローは独立した Job を作り、Secrets を自動継承します。単機能のカプセル化には複合 Action、パイプライン全体の標準化には再利用可能ワークフローが向いています。
複合 Action の inputs に type フィールドがないのはなぜ?
複合 Action の inputs は string 型のみです。再利用可能ワークフローのように boolean や number は定義できません。真偽値が必要なら 'true' / 'false' を渡し、ステップ内で判定してください。
複合 Action で Secrets を渡すには?
secrets コンテキストには直接アクセスできません。inputs 経由(ログではマスク)または env 経由(より安全、値はログに出ない)で明示的に渡します。
Action 参照は commit SHA と tag、どちらを使うべき?
本番は commit SHA(不変で最安全)。社内プロジェクトは major tag(@v1 など、最新 v1.x を追従)。@latest は意図しないアップグレードでビルドが壊れる恐れがあるため避けてください。
複合 Action の最大ネスト深度は?
複合 Action 同士の呼び出しは最大 10 層。デバッグが難しくなるため、3 層以内を推奨します。
複合 Action では shell を明示指定する必要がある?
はい。各 run ステップに shell: bash(または sh、pwsh)が必須です。通常のワークフローでは省略できますが、複合 Action では省略不可です。

7分で読めます · 公開日: 2026年5月6日 · 更新日: 2026年6月24日

関連記事

コメント

GitHubアカウントでログインしてコメントできます