7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1つのリポジトリで複数のComposite Actionsを管理する実践的な方法

7
Last updated at Posted at 2025-12-03

こんにちは。
LIFULLでエンジニアマネージャとシニアエンジニアをしているりくしるです。

この記事はLIFULL Advent Calendar 2025の4日目の記事になります。

昨日の記事でもComposite Actionsについての紹介記事を上げておりますので、まずはこちらの記事をお読みいただけるとありがたいです。

この記事では、上記記事の基本を踏まえた上で管理方法についてを紹介しています。

はじめに

GitHub ActionsのComposite Actionsは、ワークフローの再利用が可能になるGitHub Actionsの機能です。

しかし、多くの参考記事では1リポジトリに1つのComposite Actionという構成が紹介されており、複数のアクションを管理する際の課題については触れられていません。

本記事では、1つのリポジトリで複数のComposite Actionsを効率的に管理する方法と、さらにコンポーネント化によってコードを簡潔に保つテクニックを紹介します。

なお、下記に取り上げるテクニックは以下の取り組みの中で利用した例になります。

この取り組みの中でリリースフローに関するComposite Actionsを1リポジトリで管理し、それを他の多くのリポジトリから呼ばせたいモチベーションがあったので、検討して実施いたしました。

内容にご興味をお持ちいただけましたら合わせてお読みいただけると幸いです。

Composite Actionとは

Composite Actionは、複数のステップをまとめて再利用可能なアクションとして定義できる機能です。

基本的な作成方法

action.yamlファイルを作成し、以下のように定義します。

name: Example Action
description: サンプルのComposite Action

inputs:
  message:
    description: '表示するメッセージ'
    required: true

runs:
  using: "composite"
  steps:
    - name: Echo message
      shell: bash
      run: echo "${{ inputs.message }}"

呼び出し方

- uses: organization/repository@v1.0.0
  with:
    message: "Hello, World!"

課題感

Composite Actionを作成する際、多くの参考記事では以下のような構成が紹介されています。

organization/action-name/
└── action.yaml

この場合、呼び出し方は以下のようになります。

- uses: organization/action-name@v1.0.0

しかし、この方法には以下の課題があります。

  • リポジトリの乱立: アクションごとにリポジトリを作成すると、管理が煩雑になる
  • ドキュメントの分散: 各リポジトリにREADMEを書く必要があり、全体像が把握しにくい

複数の関連するComposite Actionsを1つのリポジトリで管理できれば、これらの課題を解決できます。

解決策: ディレクトリ分け

実は、Composite Actionsはディレクトリを分けることで、1つのリポジトリに複数のアクションを配置できます。

ディレクトリ構成例

organization/actions-collection/
├── README.md
├── label-manager/
│   └── action.yaml
├── comment-handler/
│   └── action.yaml
└── notification-sender/
    └── action.yaml

各アクションの定義例

label-manager/action.yaml

name: Label Manager
description: ラベルを管理するアクション

inputs:
  github_token:
    description: 'GitHub Token'
    required: true
  labels:
    description: 'カンマ区切りのラベルリスト'
    required: true

runs:
  using: "composite"
  steps:
    - name: Add labels
      uses: actions/github-script@v7
      with:
        github-token: ${{ inputs.github_token }}
        script: |
          const labels = '${{ inputs.labels }}'.split(',').map(l => l.trim());
          await github.rest.issues.addLabels({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: context.issue.number,
            labels: labels
          });

comment-handler/action.yaml

name: Comment Handler
description: コメントを追加するアクション

inputs:
  github_token:
    description: 'GitHub Token'
    required: true
  comment_body:
    description: 'コメント本文'
    required: true

runs:
  using: "composite"
  steps:
    - name: Add comment
      uses: actions/github-script@v7
      with:
        github-token: ${{ inputs.github_token }}
        script: |
          await github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: `${{ inputs.comment_body }}`
          });

呼び出し方

ディレクトリパスを指定することで、各アクションを呼び出せます。

steps:
  - name: ラベルを追加
    uses: organization/actions-collection/label-manager@v1.0.0
    with:
      github_token: ${{ secrets.GITHUB_TOKEN }}
      labels: 'bug, enhancement'

  - name: コメントを追加
    uses: organization/actions-collection/comment-handler@v1.0.0
    with:
      github_token: ${{ secrets.GITHUB_TOKEN }}
      comment_body: 'レビューをお願いします'

メリット

  • 一元管理: 関連するアクションを1つのリポジトリで管理
  • 統一されたバージョン管理: タグ付けが1回で済む
  • ドキュメントの集約: READMEで全アクションの概要を説明可能

さらなる改善: コンポーネント化

ディレクトリ分けで複数のComposite Actionsを管理できるようになりましたが、アクション間で同じような処理が重複することがあります。

このような場合、共通処理をコンポーネントとして切り出し、各アクションから呼び出すことで、コードの重複を削減できます。

コンポーネント用ディレクトリの追加

organization/actions-collection/
├── README.md
├── shared/                    # 共通コンポーネント
│   ├── add-labels/
│   │   └── action.yaml
│   ├── add-comment/
│   │   └── action.yaml
│   └── get-pr-info/
│       └── action.yaml
├── label-manager/             # 公開アクション
│   └── action.yaml
├── comment-handler/           # 公開アクション
│   └── action.yaml
└── pr-automation/             # 公開アクション
    └── action.yaml

共通コンポーネントの定義例

shared/add-labels/action.yaml

name: Add Labels (Internal)
description: ラベルを追加する内部コンポーネント

inputs:
  github_token:
    description: 'GitHub Token'
    required: true
  labels:
    description: 'カンマ区切りのラベルリスト'
    required: true

runs:
  using: "composite"
  steps:
    - name: Add labels
      uses: actions/github-script@v7
      with:
        github-token: ${{ inputs.github_token }}
        script: |
          const labels = '${{ inputs.labels }}'.split(',').map(l => l.trim());
          await github.rest.issues.addLabels({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: context.issue.number,
            labels: labels
          });

shared/get-pr-info/action.yaml

name: Get PR Info (Internal)
description: PRの情報を取得する内部コンポーネント

inputs:
  github_token:
    description: 'GitHub Token'
    required: true
  pr_number:
    description: 'PR番号'
    required: true

outputs:
  pr_title:
    description: 'PRのタイトル'
    value: ${{ steps.get-pr.outputs.title }}
  pr_body:
    description: 'PRの本文'
    value: ${{ steps.get-pr.outputs.body }}

runs:
  using: "composite"
  steps:
    - id: get-pr
      uses: actions/github-script@v7
      with:
        github-token: ${{ inputs.github_token }}
        script: |
          const { data: pr } = await github.rest.pulls.get({
            owner: context.repo.owner,
            repo: context.repo.repo,
            pull_number: ${{ inputs.pr_number }}
          });
          core.setOutput('title', pr.title);
          core.setOutput('body', pr.body);

コンポーネントを利用するアクション

pr-automation/action.yaml

name: PR Automation
description: PRに対して自動的にラベルとコメントを追加

inputs:
  github_token:
    description: 'GitHub Token'
    required: true
  pr_number:
    description: 'PR番号'
    required: true

runs:
  using: "composite"
  steps:
    # 共通コンポーネントを呼び出し
    - name: Get PR information
      id: pr-info
      uses: organization/actions-collection/shared/get-pr-info@v1.0.0
      with:
        github_token: ${{ inputs.github_token }}
        pr_number: ${{ inputs.pr_number }}

    # PRタイトルに基づいてラベルを決定
    - name: Determine labels
      id: labels
      shell: bash
      run: |
        title="${{ steps.pr-info.outputs.pr_title }}"
        if [[ $title == *"[feat]"* ]]; then
          echo "labels=feature" >> $GITHUB_OUTPUT
        elif [[ $title == *"[fix]"* ]]; then
          echo "labels=bugfix" >> $GITHUB_OUTPUT
        else
          echo "labels=other" >> $GITHUB_OUTPUT
        fi

    # 共通コンポーネントでラベルを追加
    - name: Add labels
      uses: organization/actions-collection/shared/add-labels@v1.0.0
      with:
        github_token: ${{ inputs.github_token }}
        labels: ${{ steps.labels.outputs.labels }}

    # 共通コンポーネントでコメントを追加
    - name: Add comment
      uses: organization/actions-collection/shared/add-comment@v1.0.0
      with:
        github_token: ${{ inputs.github_token }}
        comment_body: |
          自動的にラベル `${{ steps.labels.outputs.labels }}` を追加しました。

呼び出し方

外部からは公開アクションのみを呼び出します。

steps:
  - name: PR自動化
    uses: organization/actions-collection/pr-automation@v1.0.0
    with:
      github_token: ${{ secrets.GITHUB_TOKEN }}
      pr_number: ${{ github.event.pull_request.number }}

ポイント

  • 絶対パス指定: 同一リポジトリ内のコンポーネントも organization/actions-collection/shared/add-labels@v1.0.0 のように絶対パスで呼び出す
  • 内部コンポーネント: shared/ ディレクトリは外部から直接呼び出されることを想定していない
  • コードの再利用: 複数のアクションで同じ処理を共有できる

最終的なディレクトリ構成

organization/actions-collection/
├── README.md
├── shared/                    # 内部コンポーネント(外部から直接呼び出さない)
│   ├── add-labels/
│   │   └── action.yaml
│   ├── add-comment/
│   │   └── action.yaml
│   └── get-pr-info/
│       └── action.yaml
├── label-manager/             # 公開アクション
│   └── action.yaml
├── comment-handler/           # 公開アクション
│   └── action.yaml
└── pr-automation/             # 公開アクション(内部コンポーネントを利用)
    └── action.yaml

まとめ

Composite Actionは非常に便利な機能ですが、リポジトリごとに作成すると管理が煩雑になります。

本記事で紹介した方法を使えば、複数のComposite Actionsを1つのリポジトリで管理することが可能です。
Composite Actionsが増えれば増えるほど同じようなコードが増えるので、共通処理をsharedディレクトリに配置してコード量自体の削減もできます。

多くのComposite Actionsを作成する場合は、ぜひこの方法を検討してみてください。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?