【Github】Github Actions ~ workflow_run / workflow_call ~

■ はじめに

実作業において、Github Actionsで
ファイル分割して実行したいケースが出てきそうになっている。
そこで、今回は、onイベント の workflow_run / workflow_call について
掘り下げる。

目次

【0】workflow_run / workflow_call との違い
【1】workflow_run
 1)構文
 2)サンプル
【2】workflow_call - Reusable Workflows
 1)構文
 2)サンプル
【3】Tips1:workflow_call の input に可変の値を入れたい場合
 1)ダメな例
 2)OKな例
【4】使用上の注意
 1)input の データ型が文字列以外は、fromJSONでキャストが必要
 2)workflow_call は、.github/workflows直下に置くこと

【0】workflow_run / workflow_call との違い

* サンプルを見比べると分かるが、以下の通り。

[a] workflow_run

* workflow_run を使ったYAMLファイルは、
 指定したワークフローの結果をイベントトリガーとして
 開始する

[b] workflow_call

* 呼び出し元から明示的にworkflow_call を使ったYAMLを
 呼び出して実行される
 => workflow_call を使ったYAMLファイルだけでは開始されない

【1】workflow_run

* 他のワークフローの完了をトリガーに実行

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#workflow_run

1)構文

on:
  workflow_run:
    workflows: ["Build"] # Build という名前のワークフローが実行
    types: [completed]  # completed (完了したら)  completed/requested/in_progress
    branches: [canary] # 名前が canary のブランチ
    # branches-ignore:
    #   - 'releases/**'

1)サンプル

* 「.github/workflows/workflow1.yml」が実行された後に
 「.github/workflows/workflow2.yml」が実行される

.github/workflows/workflow1.yml

name: Demo Workflow1

on:
  workflow_dispatch:
    inputs:
      env:
        description: 'Enviroment'
        required: true
        default: 'dev'
        type: choice
        options:
        - dev
        - stage
        - prod
      demoInputValue:
        description: 'Sample input'
        required: true
        type: string
jobs:
  job1:
    runs-on: ubuntu-latest
    env:
      ENV: ${{ inputs.env }}
      DEMO_INPUT_VALUE: ${{ inputs.demoInputValue }}
    steps:
      - run: |
          echo "ENV: $ENV"
          echo "DEMO_INPUT_VALUE: $DEMO_INPUT_VALUE"

.github/workflows/workflow2.yml

name: Demo Workflow2

on:
  workflow_run:
    workflows: [Demo Workflow1]
    types:
      - completed

jobs:
  on-success:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - run: echo 'The triggering workflow passed'
  on-failure:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    steps:
      - run: echo 'The triggering workflow failed'

【2】workflow_call - Reusable Workflows

* 別のワークフローからワークフローを呼び出すことができる
 => 再利用可能なワークフロー(Reusable Workflows)

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#workflow_call

1)構文

https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_call
https://docs.github.com/ja/actions/using-workflows/reusing-workflows#using-inputs-and-secrets-in-a-reusable-workflow

on:
  workflow_call:
    inputs: # [1]
      username:
        description: 'A username passed from the caller workflow'
        default: 'john-doe'
        required: false
        type: string # string/number/boolean
    outputs: # [2]
      workflow_output1:
        description: "The first job output"
        value: ${{ jobs.my_job.outputs.job_output1 }}
      workflow_output2:
        description: "The second job output"
        value: ${{ jobs.my_job.outputs.job_output2 }}
    secrets: # [3]
      access-token:
        description: 'A token passed from the caller workflow'
        required: false

2)サンプル

* 結構ハマった。
 ちゃんと動くまでは、
 動いているサンプルをそのままコピペした方がいい、、、

.github/workflows/workflow-a.yml

name: Start workflow

on:
  workflow_dispatch:

jobs:
  # Step1:別ワークフローを呼び出す
  call_demo_workflow:
    uses: ./.github/workflows/workflow-b.yml
    with:
      input_name: Mike

  # Step2:別ワークフローのOutputを受け取る
  show_outputs:
    needs:
      - call_demo_workflow
    runs-on: ubuntu-latest
    steps:
      - run: |
          echo ${{ needs.call_demo_workflow.outputs.result_message }}

.github/workflows/workflow-b.yml

name: Sample workflow for workflow_call

on:
  workflow_call:
    inputs:
      input_name:
        description: Fill name
        required: true
        type: string
    outputs:
      result_message:
        description: Result output message
        value: ${{ jobs.greeting.outputs.output_result }}

jobs:
  greeting:
    runs-on: ubuntu-latest
    outputs:
      output_result: ${{ steps.message.outputs.result }}
    steps:
      - id: message
        run: |
          echo 'result=Hi, ${{ inputs.input_name }}!' >> $GITHUB_OUTPUT
      

【3】Tips1:workflow_call の input に可変の値を入れたい場合

*実装するまで分からなかったのだが、
以下の「ダメな例」のようにinput に環境変数 env.XXX が使えない。
 => 以下のサイトのように、
  needs.xxxx.outputs.xxxxx のようにしないと使えない

https://stackoverflow.com/questions/73305126/passing-env-variable-inputs-to-a-reusable-workflow
https://github.com/orgs/community/discussions/26671

1)ダメな例

* input に環境変数 env.XXX が使えない

コード抜粋

env:
  ENV_INPUT_NAME: Tom
jobs:
  # Step1:別ワークフローを呼び出す
  call_demo_workflow:
    uses: ./.github/workflows/workflow-b.yml
    with:
      # !! NG !! input に環境変数 env.XXX が使えない
      input_name: {{ env.ENV_INPUT_NAME }}

2)OKな例

* needs.xxxx.outputs.xxxxx のようにしてワンクッション置く

サンプル

name: Start workflow

on:
  workflow_dispatch:

env:
  INPUT_NAME: Smith

jobs:
  init:
    outputs:
      input_value: ${{ steps.init_values.outputs.input_value }}
    runs-on: ubuntu-latest
    steps:
      - id: init_values
        run: |
          echo 'input_value=${{ env.INPUT_NAME }}!' >> $GITHUB_OUTPUT
  call_demo_workflow:
    needs:
      - init
    uses: ./.github/workflows/workflow-b.yml
    with:
      # ★注目★
      input_name: ${{ needs.init.outputs.input_value }}

  show_outputs:
    needs:
      - call_demo_workflow
    runs-on: ubuntu-latest
    steps:
      - run: |
          echo ${{ needs.call_demo_workflow.outputs.result_message }}

【4】使用上の注意

1)input の データ型が文字列以外は、fromJSONでキャストが必要

* input の データ型が文字列以外(e.g. type: number)の場合は
 呼び出し元の直前に「fromJSON」をしてキャストする必要がある
 => そうしないと、例えば、
  エラー「The template is not valid. xxxxx: Unexpected value '<数字>'」
  が表示される

「type: number」だった場合の対応例

  call_demo_workflow:
    needs:
      - init
    uses: ./.github/workflows/workflow-b.yml
    with:
      # ★注目★
      input_name: ${{ fromJSON(needs.init.outputs.input_value) }}

2)workflow_call は、.github/workflows直下に置くこと

* workflow_call(Reusable / 再利用可能なWorkflow)のファイルは、
 .github/workflows直下に置く

 => 例えば、ディレクトリを掘って、
  .github/workflows/reusables配下に置くことはできない

.github/workflows/reusables配下に置いた時のエラー内容

invalid value workflow reference:
 workflows must be defined at the top level of the .github/workflows/ directory

参考文献

https://docs.github.com/ja/actions/using-workflows/reusing-workflows
https://zenn.dev/jerome/articles/618af7cc934f2f
https://zenn.dev/dzeyelid/articles/fc4bd999fbccd8
https://qiita.com/M_Kagawa/items/98f154477b8b5bd3d315

関連記事

Github ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/07/18/234652
Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ ワークフロー制御 ~
https://dk521123.hatenablog.com/entry/2024/01/28/004128
Github Actions ~ あれこれ編 ~
https://dk521123.hatenablog.com/entry/2023/12/21/155224
Github Actions ~ エラー処理 ~
https://dk521123.hatenablog.com/entry/2024/01/01/232057
Github Actions ~ GITHUB_ENV ~
https://dk521123.hatenablog.com/entry/2023/12/29/000840
Github Actions ~ GITHUB_OUTPUT ~
https://dk521123.hatenablog.com/entry/2024/01/30/002943
Github Actions ~ Artifact ~
https://dk521123.hatenablog.com/entry/2024/02/13/021717
Github Actions ~ 設定値を切り替えることを考える ~
https://dk521123.hatenablog.com/entry/2024/02/18/232926
Github Actions ~ Self-hosted runners / 入門編 ~
https://dk521123.hatenablog.com/entry/2023/12/18/204119
Github Actions ~ Self-hosted runners / あれこれ編 ~
https://dk521123.hatenablog.com/entry/2024/02/07/002736