GitHub Actionsでの処理の再利用(Reusable Workflows, Custom Actions)について整理

処理を再利用したいときには、以下の方法があり、それぞれで呼び出しのレベルが異なっています。

  • Reusable Workflows
  • Custom Actions (Composite Action)
    • Stepの一つとして呼び出す
    • jobs.<job_id>.steps[*].uses シンタックスで呼び出す

なので、どういうレベルで呼び出したいかや処理の粒度で、workflowにするかactionにするかを選ぶと良いと思います。

ログの出力も少し違っていて、Reusable Workflowsの方が見やすいですが、どちらも見ることはできるのでそれほど困らないはずです。

checkoutの振る舞いの違い

GitHub Actionsのご紹介と弊社での利用について - Stanby Tech Blog に書いてくれていますが、以下のように違います。

  • Composite Action
    • Composite Actionを定義している側のリポジトリのリソースをcheckout
  • Reusable Workflow
    • Reusable Workflowを利用している側のリポジトリのリソースをcheckout

Composite Actionはステップの一つなのでそうなるのも理解しやすいですし、大元のワークフローの方でcheckoutするはずなので、この点はとくに問題にはならないと思います。Composite Actionでチェックアウトしたくなったら、Reusable Workflowへの変更を考えるのが良いでしょう。

Workflowなどをプライベートリポジトリーに配置したら再利用できない

現状ではできません。認証が通らないので、パブリックリポジトリーに置かないといけないです。それが憚られる場合は、暫定措置として、ファイルをコピーして別プロジェクトに展開するのが今のところの妥協案かなと思っています。

-   Both workflows are in the same repository.
-   The called workflow is stored in a public repository, and your organization allows you to use public reusable workflows.

Reusing workflows - GitHub Docs

Private Access Tokenを使ってチェックアウトすれば当然リポジトリーを参照できますが、権限が大きすぎるし個人に依存するし、詐称してなんでもできてしまうのでこれは使うべきではないでしょう。

- name: Checkout private tools
  uses: actions/checkout@v3
  with:
    repository: my-org/my-private-tools
    token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
    path: my-tools

GitHub - actions/checkout: Action for checking out a repo

一応、イシューにはなっており、 Actions: Reusable workflows work with private repositories · Issue #51 · github/roadmap · GitHub ロードマップ上では 2022Q4が目標になっているので、注視したいところです。どうやって権限を移譲するのかがイメージついていません。 GitHub public roadmap

Reusable Workflows

Reusing workflows - GitHub Docs

基本的にドキュメントの通りですが、いくつかポイントがあるので記します。

呼び出しの記述

以下のようにファイルパスまで指定します。

jobs:
  call-workflow-1-in-local-repo:
    uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89 # local repo
  call-workflow-2-in-local-repo:
    uses: ./.github/workflows/workflow-2.yml # local file path
  call-workflow-in-another-repo:
    uses: octo-org/another-repo/.github/workflows/workflow.yml@v1 # another public repo

ファイルパスまで指定するので .github/workflows ディレクトリーじゃなくてもいいかと思ったんですが、以下のエラーになって実行できません。

invalid value workflow reference: references to workflows must be rooted in '.github/workflows'

Custom Actions (Composite Action)

カスタムアクション自体は以下の3つの選択肢があります。

  • Docker container Action
    • コンテナー内で実行できるのでミドルウェアを利用するような処理を書ける
  • JavaScript Action
    • Node.jsで実行できるので複雑なロジックを書くことができる
  • Composite Action

それぞれ使い道があるので使い分ければいいですが、Composite Actionが実行が速くて手軽なので基本的にこれを使うのが良いはずです。

Creating a composite action - GitHub Docs

ディレクトリ構成

規定されていませんが、以下が推奨されています。

.github/actions/action_name

Composite Actionのシンタックス

通常のworkflowと少しだけ違うので以下を参照してください。

Metadata syntax for GitHub Actions - GitHub Docs

呼び出しの記述

以下のようにフォルダー名までを指定します。action.ymlは暗黙で補完されます。

    steps:
      - uses: actions/checkout@v3
      - uses: ./.github/actions/first_action # local folder path
      - uses: octo-org/this-repo/.github/actions/first_action@main # local repo        

ローカルフォルダーパスで実行する場合は事前にチェックアウトが必須ですが、ローカルリポジトリー形式だとチェックアウトは不要です。 チェックアウトをしない関係なのか、ローカルリポジトリー形式の方が実行完了が速いです。

ワークフローとアクションは相互運用できない

Reusable Workflowをstes.usesシンタックスで呼ぼうとすると以下のエラーになります。

reusable workflows should be referenced at the top-level `jobs.*.uses' key, not within steps

Custom Actionをjobs.usesシンタックスで呼ぼうとすると以下のエラーになります。そもそもCustom Actionはworkflow_callトリガーを実装しないので無理がありますね。もし、実装したとしても多分実行できないはず。

invalid value workflow reference: references to workflows must be rooted in '.github/workflows'