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

GitHub Actions 複合 Action 開発:action.yml から Marketplace 公開までの完全ガイド

深夜3時、私は画面の前に表示された15回目のエラーログを見つめていました。エラーの原因は何でしょうか?あるプライベートリポジトリの npm install ステップで、NODE_AUTH_TOKEN を追加し忘れていたのです。

今週だけで既に3回目です。私たちは8つのリポジトリを持っており、それぞれにほぼ同じワークフロー設定をコピペしています。checkout、setup-node、install、build、test。ある箇所を変更するたびに、8つのリポジトリを同期する必要があります。ある日、Nodeのバージョンをアップグレードした際、5つのリポジトリを変更しましたが、残りの3つを忘れてしまいました。

その瞬間、私は悟りました。「このままではいけない」と。GitHub Actionsの複合Action(Composite Action)はまさにこのために存在します。繰り返し使うステップを再利用可能なコンポーネントとしてパッケージ化し、関数を呼び出すように複数のワークフローで使用できるのです。本記事では、最初の複合Actionを開発してMarketplaceに公開するまで、CI/CDコンポーネント化の核心スキルを習得します。

第一章:複合Actionの核心概念

1.1 複合Actionとは

複合Actionは、GitHub Actionsが提供するコンポーネント化の仕組みです。複数のステップ(steps)を1つの独立したActionとしてカプセル化し、異なるワークフローで再利用できます。

JavaScript ActionやDocker Actionとは異なり、複合Actionはコードを書く必要がありません。YAML設定を書くだけで、一連のステップを定義でき、GitHubが自動的に実行します。簡単に言えば、複合Actionはステップの「関数カプセル化」のようなものです。

公式の定義では、複合Actionは runs.using: "composite" で識別され、すべてのステップは同じRunner内で実行されます。つまり、作業ディレクトリや環境変数に直接アクセスでき、他のActionを呼び出すことさえ可能です。

1.2 3つのAction型の比較

GitHub Actionsは3つのAction型をサポートしています。

実装方法適用シーン
JavaScript ActionJS/TSコードを記述複雑なロジック、APIコールが必要
Docker ActionDockerfileを記述特定の環境、依存関係が必要
複合Action純粋なYAML設定既存のステップを組み合わせ、迅速に再利用

複合Actionのメリットは明確です。コード不要、迅速な開発、メンテナンスが容易。バンドル、コンパイル、依存関係管理を気にする必要がなく、YAMLを書くだけです。

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

ここが多くの人が混乱するポイントです。一見すると、どちらも「再利用」ですが、本質は異なります。

複合Actionはステップグループです。Job内で実行され、呼び出し元のRunnerを使用し、Secretsは明示的に渡す必要があります。

再利用可能ワークフローは完全なパイプラインです。独立したJobを作成し、独自のRunnerを持つことができ、Secretsは自動的に継承されます。

例を挙げましょう。「依存関係のインストール + テストの実行」をパッケージ化して再利用したい場合、複合Actionを使います。「ビルド→テスト→デプロイ」のパイプライン全体を標準化したい場合、再利用可能ワークフローを使います。第4章で詳しく比較します。

第二章:最初の複合Actionを開発する

2.1 action.yml構造の詳細

複合Actionの核心は action.yml ファイルです。これはメタデータファイルで、Actionの名前、入力、出力、実行ステップを定義します。

まず最小限の例を見てみましょう。

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

このActionは1つのことしか行いません。1行のテキストを出力するだけです。しかし実際のプロジェクトでは、パラメータ化と出力が必要です。

2.2 完全な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

2.3 フィールドの詳細解説

inputs:Actionが受け取るパラメータを定義します。各パラメータには以下を指定できます。

  • description:パラメータの説明(Marketplaceに表示されます)
  • required:必須かどうか
  • default:デフォルト値

outputs:Actionの出力を定義します。$GITHUB_OUTPUT 環境変数経由で渡されます。フォーマットに注意してください。

echo "name=value" >> $GITHUB_OUTPUT

runs.steps:実行ステップです。通常のワークフローと似ていますが、2つの重要な違いがあります。

  1. shellを明示的に指定する必要があります。各ステップの run コマンドには shell: bash(または shpwsh)が必要です。これは複合Actionの必須要件です。

  2. uses で他のActionを呼び出せます。上記の例の actions/setup-node@v4 のように。

2.4 よくある落とし穴

開発過程で、私はいくつかの落とし穴に遭遇しました。

落とし穴1:inputsにtypeフィールドがない

複合Actionのinputsはstring型のみをサポートしています。再利用可能ワークフローのように type: booleantype: number を定義できません。ブール値が必要な場合は、文字列 "true" または "false" を渡し、ステップ内で判断します。

落とし穴2:shellは明示的に指定が必要

通常のワークフローでは、run コマンドで shell を省略でき、GitHubがRunnerに基づいて自動的に選択します。しかし複合Actionでは明示的に指定しないとエラーになります。

落とし穴3:outputsはstep id経由で参照が必要

出力値の value フィールドはステップの出力を参照する必要があります。

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

ステップには id を設定する必要があります。

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

第三章:複合Actionを使用する

3.1 ローカル参照

最もシンプルな使用方法は、同じリポジトリ内で参照することです。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への公開は不要です。

3.2 クロスリポジトリ参照

複数のリポジトリ間で共有したい場合、Actionを独立したリポジトリに配置し、クロスリポジトリ参照ができます。

steps:
  # 組織内の共有Actionを参照
  - uses: your-org/shared-actions/build@v1
    with:
      node-version: '18'

パスフォーマットは owner/repo/path@version です。path はActionのリポジトリ内の相対パスです。

推奨する組織レベルの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

3.3 Marketplaceから使用する

Marketplaceに公開した後、ユーザーは直接検索して参照できます。

steps:
  # Actionが "build-test-action" として公開されていると仮定
  - uses: your-org/[email protected]
    with:
      node-version: '20'

Marketplaceはバージョン選択、使用統計、README表示などの機能を提供し、オープンソースプロジェクトや公開共有するActionに適しています。

3.4 バージョン選択戦略

Actionを参照する際、3つのバージョン選択方法があります。

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

# 方法2:セマンティックバージョンタグ(推奨)
- uses: your-org/[email protected]

# 方法3:major tag(最新のv1.xを自動追跡)
- uses: your-org/action@v1

# 非推奨:latestタグ(予期しないアップグレードの可能性)
# - uses: your-org/action@latest

セキュリティの推奨事項

本番環境では、commit SHAを使用するのが最も安全です。SHAは不変であり、メンテナーがタグを更新しても予期しないアップグレードが発生しません。

内部プロジェクトでは、major tag(例:@v1)を使用するのが柔軟な選択です。最新のv1.xバージョンを自動的に追跡し、バグ修正や新機能を取得できます。

@latest の使用は避けてください。予期しないアップグレードが発生し、ビルドが壊れる可能性があります。

第四章:複合Action vs 再利用可能ワークフロー

4.1 機能比較表

選択時の核心的なリファレンスです。

次元複合Action再利用可能ワークフロー
実行レベルJob内のステップグループ独立したJob
Runner呼び出し元のRunnerを使用新しいRunnerを作成(または指定)
Secrets明示的な渡しが必要自動継承
入力型stringのみboolean / number / string
出力渡し$GITHUB_OUTPUToutputs + workflow_call
並行制御呼び出し元の並行制限を継承独立して設定可能
環境変数継承 + 追加可能独立したスコープ
適用シーン単一機能のカプセル化パイプライン全体の標準化

4.2 選択の決定マトリックス

シーンに応じて適切な再利用方法を選択します。

複合Actionを使用する場合

  • 繰り返し使用するビルド/テスト/デプロイステップをパッケージ化
  • Job内で他のステップとやり取りする必要がある
  • ワークフローの柔軟性を維持しつつ、一部のステップのみ再利用したい
  • Secretsの受け渡しを制御でき、セキュリティ要件が高い

再利用可能ワークフローを使用する場合

  • CI/CDパイプライン全体を標準化
  • 複数のプロジェクトで同じ完全なフローが必要
  • Secretsの自動継承が必要(設定を削減)
  • iftimeout-minutes などのワークフローレベルの設定が必要

組み合わせて使用する

実際には、組み合わせて使用するのがベストプラクティスです。再利用可能ワークフローが複合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
      
      # 複合Actionを呼び出し
      - uses: ./.github/actions/build-test
        with:
          node-version: ${{ inputs.node-version }}

こうすることで、ワークフローレベルの標準設定と、Actionレベルのステップ再利用の両方が得られます。

第五章:バージョン管理と公開

5.1 Gitタグのベストプラクティス

Actionを公開する核心はGitタグ管理です。セマンティックバージョニング + major 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をリリースする際、major tagを更新します。

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

# v1タグを最新バージョンに更新
git tag -fa v1 -m "Update v1 tag to v1.1.0"
git push origin v1 --force

こうすることで、ユーザーは選択できます。

  • @v1.1.0 で特定バージョンに固定
  • @v1 でv1.xのアップデートを自動的に取得

5.2 Marketplace公開プロセス

GitHub Marketplaceに公開するには以下が必要です。

1. README.mdを準備

READMEには以下を含める必要があります。

  • Action名と説明
  • InputsとOutputsの説明
  • 使用例
  • ライセンス

2. action.ymlを準備

namedescriptionauthorbranding(オプション)フィールドが完全であることを確認します。

3. リリースを作成

GitHubリポジトリページで:

  1. “Releases” → “Draft a new release” をクリック
  2. タグを選択(例:v1.0.0
  3. リリースノートを入力
  4. “Publish this Action to the GitHub Marketplace” にチェック
  5. 公開

GitHubが自動的に action.yml を検証し、Marketplaceに公開します。

5.3 自動化公開ワークフロー

ワークフローを作成して自動公開できます。

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

このワークフローは、タグをプッシュすると自動的にmajor tagを更新し、リリースを作成します。

第六章:高度なテクニックとベストプラクティス

6.1 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 で機密情報を渡す(マスクされる)
  • READMEで必要なSecretsを明確に説明する

6.2 ローカルスクリプトの使用

複雑なロジックはYAMLに書くのに適していません。Actionディレクトリにスクリプトファイルを配置できます。

.github/actions/build-test/
├── action.yml
└── scripts/
    └── build.sh

action.ymlで呼び出します。

runs:
  using: "composite"
  steps:
    - run: $GITHUB_ACTION_PATH/scripts/build.sh
      shell: bash

$GITHUB_ACTION_PATH は複合Actionのルートディレクトリへのパスです。

6.3 組織レベルのActionリポジトリ設計

チームの場合、共有Actionを一元管理することを推奨します。

your-org/shared-actions/
├── .github/
│   └── workflows/
│       └── test.yml       # すべてのActionをテスト
├── build/
│   ├── action.yml
│   └── README.md
├── deploy/
│   ├── action.yml
│   └── README.md
├── lint/
│   ├── action.yml
│   └── README.md
└── README.md

各サブディレクトリは独立したActionで、完全なREADMEとテストを持ちます。

6.4 よくある落とし穴とデバッグテクニック

落とし穴1:ネスト深度の制限

複合Actionが複合Actionを呼び出す場合、最大深度は10層です。超えるとエラーになります。3層以下のネストを推奨します。深いネストはデバッグが困難です。

落とし穴2:環境変数のスコープ

複合Action内の env はステップ内でのみ有効です。ステップ間で共有する必要がある場合、GITHUB_ENV を使用します。

steps:
  - run: echo "MY_VAR=value" >> $GITHUB_ENV
    shell: bash
  - run: echo $MY_VAR  # アクセス可能
    shell: bash

デバッグテクニック

  1. ACTIONS_STEP_DEBUG=true を使用して詳細ログを有効化
  2. ステップ内で echo を使用して変数を出力
  3. tmate Actionを使用してSSHデバッグ(本番環境では非推奨)

結論

複合ActionはGitHub Actionsコンポーネント化の核心ツールであり、繰り返しの設定から解放され、関数を書くようにCIステップをカプセル化できます。

3つのポイントを覚えておきましょう。

構造を明確に:action.ymlでinputs/outputs/stepsを定義し、関数シグネチャのように設計します。パラメータ化でActionをより柔軟に、出力で呼び出し元が結果を取得できるようにします。

正しく選択する:複合Actionは単一機能をカプセル化(ビルド、テスト、デプロイ)し、再利用可能ワークフローはパイプライン全体を標準化します。組み合わせて使用するのがベストです。

バージョンを安全に:commit SHAが最も安全で、本番環境に適しています。major tagは柔軟で、内部プロジェクトに適しています。latest は避けてください。

次のステップ:プロジェクトで最初の複合Actionを作成し、繰り返し使用するbuild-testステップをパッケージ化してから、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が自動検証して公開

FAQ

複合Actionと再利用可能ワークフローの違いは何ですか?
複合ActionはJob内のステップグループで、呼び出し元のRunnerを使用し、Secretsは明示的に渡す必要があります。再利用可能ワークフローは独立したJobを作成し、Secretsは自動継承されます。複合Actionで単一機能をカプセル化し、再利用可能ワークフローでパイプライン全体を標準化します。
複合Actionのinputsにtypeフィールドがないのはなぜですか?
複合Actionのinputsはstring型のみをサポートしています。再利用可能ワークフローのようにbooleanやnumberを定義できません。ブール値が必要な場合は、文字列 'true' または 'false' を渡し、ステップ内で判断します。
複合ActionでSecretsを渡すにはどうすればいいですか?
複合Actionはsecretsコンテキストに直接アクセスできず、明示的に渡す必要があります。inputs経由で渡す(ログでマスクされる)か、env経由で渡す(より安全、ログに値が表示されない)。
Actionを参照する際、commit SHAとタグのどちらを使うべきですか?
本番環境ではcommit SHAを使用(最も安全、不変)。内部プロジェクトではmajor tagを使用(例:@v1、最新バージョンを自動追跡)。@latestは避けてください、予期しないアップグレードでビルドが壊れる可能性があります。
複合Actionの最大ネスト深度は?
複合Actionが複合Actionを呼び出す場合、最大深度は10層です。3層以下を推奨します、深いネストはデバッグが困難です。
複合Actionでshellは明示的に指定する必要がありますか?
はい。複合Actionの各ステップのrunコマンドにはshell: bash(またはsh、pwsh)が必要です。これは必須要件で、通常のワークフローでは省略できますが、複合Actionでは指定が必須です。

7 min read · 公開日: 2026年5月6日 · 更新日: 2026年5月6日

関連記事

コメント

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