[github actions] Reusable workflowsが実装されたのでざっとまとめ
追記
年末にこの記事の内容も含めてgithub actionsをどう再利用するか総まとめしたのでそちらも併せてどうぞ!↓↓↓
この記事について
2021/11/24についにgithub actionsにReusable workflows
が実装されました。
まずは簡単にドキュメントをさらいながらポイントをまとめていこうと思います。
そもそも何が嬉しいのか
これまでのgithub actionsではworkflowからactionを呼ぶことは可能だったものの、workflowから別のworkflowを呼ぶことはできませんでした。
workflowがひとつだけの場合そう問題にはならないのですが、同じworkflowの記述を使い回したい場合にはこれが問題になっていました。
例えば下記のようなworkflowを複数のリポジトリで使う場合、actions/checkout@v2
とactions/setup-node@v2
の順序や利用するバージョン、引数などが同じであっても、各リポジトリでそれぞれ記述するしかありませんでした。
もし利用するバージョンに変更がありそれを全てのリポジトリに反映したい場合は、全てのリポジトリに対して横展開のPRを出す必要がありとても煩雑になっていたと思います。
jobs:
example:
name: example job
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
registry-url: "xxxxxxxxx"
scope: "@xxxxxxxxxx"
...
今回の実装でworkflowレベルで共通化できるようになり、一括管理しやすくなったというのが嬉しいポイントでした。
ドキュメントをざっとまとめていく
気になった点をまとめていきます。下記のドキュメントに見出しを揃えているので、気になった方は深掘りしてみてください。
Overview
- 呼び出す側のworkflowを
caller workflow
、呼ばれる側をcalled workflow
と呼びます。 -
called workflow
はcaller workflow
のcontextで処理されるため、例えcalled workflow
でactions/checkout
actionを使っていたとしても、checkoutされるのはcaller workflow
のあるリポジトリです。 - 同様に
called workflow
の中であってもcaller workflow
のgithub
のcontextが引き継がれるので、secrets.GITHUB_TOKEN
を引き回して使うことができます。 - 一方で
caller workflow
のenv
を引き継いで使うことはできないので注意が必要そうです。 -
called workflow
は必ずworkflow_call
をon
に記述する必要があります。
env
の扱いは意識しないとハマりそうかなと思いました。
Access to reusable workflows
- 下記のいずれかを満たす場合のみworkflowを再利用できる
- public repoのworkflow
- 同じrepoのworkflow
同じリポジトリであればprivate repositoryのworkflowを呼び出せるのは嬉しいですね。
Limitations
-
called workflow
から別のworkflowを呼び出すことはできません。 - private repositoryのworkflowは同じrepositoryの中からしか呼び出すことはできません
個人的には後者が特にネックかなと感じました。private repositoryをcheckoutすれば異なるrepositoryからでもreusable workflowを使えるかどうかが気になるので、後ほど検証してみようと思います。 追記しました
Example reusable workflow
再利用されるworkflowの場合on.workflow_call
を記述する必要があります。
inputs
やoutputs
, secrets
などworkflow全体に関わる定義はon.workflow_call
以下に書くようです。
jobの書き方は特段変わったところはなさそうです。(後述のoutput
周りを除く)
name: Reusable workflow example
on:
workflow_call:
inputs:
username:
required: true
type: string
secrets:
token:
required: true
jobs:
example_job:
name: Pass input and secrets to my-action
runs-on: ubuntu-latest
steps:
- uses: ./.github/actions/my-action@v1
with:
username: ${{ inputs.username }}
token: ${{ secrets.token }}
Calling a reusable workflow
actionを使うのと同じような記述ですが、steps.foo.uses
に記述するのではなく、jobs.foo.uses
に記述する点が異なっています。
@
以下に使用するバージョンやbranch, commit hashを記述する点や、with
に引数を渡すのはaction同様です。
name: Call a reusable workflow
on:
pull_request:
branches:
- main
jobs:
call-workflow:
uses: octo-org/example-repo/.github/workflows/workflow-A.yml@v1
call-workflow-passing-data:
uses: octo-org/example-repo/.github/workflows/workflow-B.yml@main
with:
username: mona
secrets:
token: ${{ secrets.TOKEN }}
Using outputs from a reusable workflow
reusable workflowから戻り値を得たい場合、
stepのoutput -> jobのoutput -> workflowのoutput
と伝達していく仕組みのようです。
name: Reusable workflow
on:
workflow_call:
# Map the workflow outputs to job outputs
outputs:
firstword:
description: "The first output string"
value: ${{ jobs.example_job.outputs.output1 }}
secondword:
description: "The second output string"
value: ${{ jobs.example_job.outputs.output2 }}
jobs:
example_job:
name: Generate output
runs-on: ubuntu-latest
# Map the job outputs to step outputs
outputs:
output1: ${{ steps.step1.outputs.firstword }}
output2: ${{ steps.step2.outputs.secondword }}
steps:
- id: step1
run: echo "::set-output name=firstword::hello"
- id: step2
run: echo "::set-output name=secondword::world"
まとめ
- reusable workflowでより簡単にworkflowを記述できるようになりそうです
-
private repositoryのreusable workflowを(なんとかして)他のrepositoryで使えないかとても気になりました追記しました
追記 private repositoryのReusable workflowの使用について
action
と同じようにcheckout
して再利用できるか試してみましたがダメでした。
下記のエラーメッセージ的にかなり意図した動きのように見えたので、現時点では利用できないように思えました。(リポジトリ名は適当に置き換えてます)
error parsing called workflow "xxxx": Workflows in 'xxxx' cannot access remote workflows in 'xxxx'. See https://docs.github.com/en/actions/learn-github-actions/reusing-workflows#access-to-reusable-workflows for more information.
Discussion