1.この記事で達成したいこと

  • repository_dispatchとworkflow_dispatch の使い分けや書き方の違い、共通点や相違点を整理したい
  • 結局どっちを使うのがいいのか?判断基準を見つけたい

そもそもrepository_dispatchとworkflow_dispatchはどういうときに使うのか?

  • アプリケーションリポジトリでイメージをレジストリにpushした後、マニフェストリポジトリでそのイメージタグをマニフェストに反映させたい
  • 使いまわしているWorkflowを呼びたい

このようなときに使えるのがGitHub Actionsでは2つ提供されている。それが冒頭に書いた、repository_dispatchとworkflow_dispatchである。

この記事の結論

長くなってしまったので、冒頭で結論を書く。

  • repository_dispatchとworkflow_dispatchの使い分けの判断基準の一つは、実行時に参照するWorkflowのブランチをデフォルトブランチ以外としたいケースがあるかどうか?
  • デフォルトブランチ以外のWorkflowのファイルを参照してWorkflowを実行したい場合は、workflow_dispatchを選ぶしかない

2.サンプルコードで使っているリポジトリ

3.環境情報

  • ローカル始めバージョンを書いておく必要があるものはない
  • 使うActionのバージョンについては後述するWorkflowを参照してほしい

4.repository_dispatchとworkflow_dispatchの共通点や相違点

  • 共通点
    • どちらも以下の権限を有する Personal Access Token が必要
    • repo:write
  • 相違点
    • workflow_dispatchのみ、GUIから実行できる
      • 実行場所はGithubの実行先のリポジトリのActionタブ
    • pushしたWorkflowからdispatchする際のパラメーターの渡し方が違う(詳細は4-1参照)
    • パラメーターの受け取り方が違う(詳細は5-1及び5-2参照)
      • repository_dispatchのみ、event-typeを使ってWorkflowを実行するか制御できる
      • repository_dispatchはevent-typeに応じて実行するかどうか決めることができる
      • workflow_dispatchの場合、Workflowをkickされたら実行されてしまうのでkickしたWorkflowから渡されるパラメータの値によってjobを実行するように制御することはできる
    • repository_dispatchのみ、Workflowはデフォルトブランチを参照して実行する

4-1.pushしたWorkflowからdispatchする際のパラメーターの渡し方

ここでは、curlコマンドでrepository_dispatchとworkflow_dispatchのWorkflowを実行しながらパラメータの渡し方の違いを確認しよう。 とりわけ、POSTする接続先URLと -d (--data)オプションで渡しているPOSTする値の書式はおさえておきたい。

$ curl -X POST \
 -H "Accespt: application/vnd.github.v3+json" \
 -H "Authorization: token <PAT_REPOSITORY_DISPATCH>" \
 https://api.github.com/repos/gkzz/actions-dispatch-playground/dispatches \
 -d '{"event_type": "sample-event", "client_payload": {"hoge": "hogevalue"}}'

https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event

  • workflow_dispatch
$ curl -X POST \
  -H "Accespt: application/vnd.github.v3+json" \
  -H "Authorization: token <PAT_WORKFLOW_DISPATCH>" \
  https://api.github.com/repos/gkzz/actions-dispatch-playground/actions/workflows/wf_dispatch_release.yml/dispatches \
  -d '{"ref":"main", "inputs":{"github_sha": "${{ github.sha }}", "appwf_url": "${{ steps.read-appwf.outputs.content }}"}}'

https://docs.github.com/en/rest/reference/actions#create-a-workflow-dispatch-event

続いてパラメータの受け取り方の違いを確認したいが、渡す様子と併せて追ったほうが分かりやすいので、repository_dispatchとworkflow_dispatchそれぞれを実行するサンプルコードを書いた。

5.サンプルコード

やっていることは以下のとおりシンプルなもの。

  • pushしたWorkflowのリポジトリのURLとコミットハッシュを後続のWorkflowでechoする

5-1.repository_dispatchのサンプルコード

  • 起点となるWorkflow(実行トリガーはpush)
name: Workflow as entrypoint (repository_dispatch)
'on':
  push:



    steps:
      - uses: actions/checkout@v2

      # Repository DispatchのActionであるpeter-evans/repository-dispatch@v1で渡すclient-payloadでは、ベタ書きと変数を組み合わせて新たな変数を定義することができなかった
      # そこで適当なファイルにclient-payloadで渡したい変数をechoし、juliangruber/read-file-action@v1でその変数を扱えるようにした
      # echoする際、-nオプションをつけて改行が入らないようにしないとpeter-evans/repository-dispatch@v1でclient-payloadをセットするところでエラーを引く
      - name: Set app rpeository workflow url
        run: echo -n "${{ env.APP_REPOSITORY_URL }}/actions/runs/${GITHUB_RUN_ID}" > /tmp/.appwf.txt

      - name: Read appwf.txt
        # https://github.com/marketplace/actions/read-file
        id: read-appwf
        uses: juliangruber/read-file-action@v1
        with:
          path: /tmp/.appwf.txt

      ### Manifest repository dispatch
      # https://github.com/marketplace/actions/repository-dispatch
      - name: Repository Dispatch
        uses: peter-evans/repository-dispatch@v1
        with:
          #token: ${{ secrets.GITHUB_TOKEN }}
          token: ${{ secrets.ACTIONS_PLAYGROUND_REPOSITORY_DISPATCH }} # リポジトリがpublic, privateどちらであってもPersonal Access Tokenが必要
          repository: ${{ env.MANIFEST_REPOSITORY_OWNER }}/${{ env.MANIFEST_REPOSITORY }}
          event-type: ${{ env.REPOSITORY_DISPATCH_EVENT_TYPE }}
          client-payload: '{
            "ref": "work",
            "github_sha": "${{ github.sha }}", 
            "appwf_url": "${{ steps.read-appwf.outputs.content }}"}'

      # Curlを使う場合
      #- name: Repository Dispatch with curl command
      #  run: |
      #    curl -X POST \
      #    -H "Accespt: application/vnd.github.v3+json" \
      #    -H "Authorization: token <PAT_REPOSITORY_DISPATCH>" \
      #    https://api.github.com/repos/gkzz/actions-dispatch-playground/dispatches \
      #    -d '{"event_type": "${{ env.REPOSITORY_DISPATCH_EVENT_TYPE }}", "client_payload": {"github_sha": "${{ github.sha }}", "appwf_url": "${{ steps.read-appwf.outputs.content }}"}}'
  • 起点となるWorkflowからkickされるWorkflow(実行トリガーはrepository_dispatch)
name: Subsequent workflow (repository_dispatch)
'on':
  repository_dispatch:
    # typesというパラメータが用意されており、これを使って呼び出しに応じるか制御できる
    types: [release-stg]

jobs:
  main:
    runs-on: 'ubuntu-20.04'

    steps:
      - uses: actions/checkout@v2
        # 呼び出し元が指定しているref(ブランチ)に応じてjobを実行するか制御できる
        if: github.event.client_payload.ref == 'work'
      - name: echo inputs from repository dispatch
        if: github.event.client_payload.ref == 'work'
        run: |
          echo "App's repository sha"
          echo "'${{ github.event.client_payload.github_sha }}'"
          echo "App's workflow url"
          echo "'${{ github.event.client_payload.appwf_url }}'"          

5-2.workflow_dispatchのサンプルコード

  • push

    steps:
      - uses: actions/checkout@v2

      - name: Set app rpeository workflow url
        run: echo -n "${{ env.APP_REPOSITORY_URL }}/actions/runs/${GITHUB_RUN_ID}" > /tmp/.appwf.txt

      - name: Read appwf.txt
        # https://github.com/marketplace/actions/read-file
        id: read-appwf
        uses: juliangruber/read-file-action@v1
        with:
          path: /tmp/.appwf.txt

      - name: Workflow Dispatch
        # https://github.com/benc-uk/workflow-dispatch
        uses: benc-uk/workflow-dispatch@v1
        with:
          workflow: Subsequent workflow (workflow_dispatch)
          #token: ${{ secrets.GITHUB_TOKEN }}
          token: ${{ secrets.ACTIONS_PLAYGROUND_WORKFLOW_DISPATCH }} # リポジトリがpublic, privateどちらであってもPersonal Access Tokenが必要
          repo: 'gkzz/actions-dispatch-playground'
          ref: 'work'
          # inputsはpeter-evans/repository-dispatch@v1でいうところのclient-payload、あるいはcurlコマンドの--dataオプションで渡す値
          inputs: '{
            "github_sha": "${{ github.sha }}", 
            "appwf_url": "${{ steps.read-appwf.outputs.content }}"}'

      # curlを使う場合
      # https://docs.github.com/ja/rest/reference/actions#create-a-workflow-dispatch-event
      # https://zenn.dev/masaaania/articles/c930f2f755a577
      #- name: Workflow Dispatch with curl command
      #  run: |
      #    curl -X POST \
      #    -H "Accespt: application/vnd.github.v3+json" \
      #    -H "Authorization: token <PAT_WORKFLOW_DISPATCH>" \
      #    https://api.github.com/repos/gkzz/actions-dispatch-playground/actions/workflows/wf_dispatch_release.yml/dispatches \
      #    -d '{"ref":"main", "inputs":{"github_sha": "${{ github.sha }}", "appwf_url": "${{ steps.read-appwf.outputs.content }}"}}'
  • workflow_dispatch
name: Subsequent workflow (workflow_dispatch)

on:
  workflow_dispatch:
    # requiredオプションやdefault値を使ってパラメータの値判定や制御ができる
    inputs:
      github_sha:
        description: "App's repository sha"
        required: true
        default: "github_sha_not_found"
      appwf_url:
        description: "App's workflow url"
        required: true
        default: "appwf_url_not_found"


jobs:
  main:
    runs-on: 'ubuntu-20.04'

    steps:
      - uses: actions/checkout@v2
        # repository_dispatch同様、workflow_dispatchでも呼び出し元が指定しているref(ブランチ)に応じてjobを実行するか制御できるが、workflow_dispatchでは、refが必須パラメータであり、これを参照して該当ブランチのWorkflowを実行できる
        if: github.event.client_payload.ref == 'work'
      - name: echo inputs from workflow dispatch
        if: github.event.client_payload.ref == 'work'
        run: |
          echo "App's repository sha"
          echo "'${{ github.event.inputs.github_sha }}'"
          echo "App's workflow url"
          echo "'${{ github.event.inputs.appwf_url }}'"          

6.repository_dispatchとworkflow_dispatchの使い分けの判断基準

ここまでrepository_dispatchとworkflow_dispatchの違いを追ってきたが、使い分けの判断基準の一つとして、実行時に参照するWorkflowのブランチをデフォルトブランチ以外としたいケースがあるかどうか?という点は挙げられるだろう。

デフォルトブランチ以外のWorkflowのファイルを参照してWorkflowを実行したい場合は、workflow_dispatchを選ぶしかない。もちろんrepository_dispatchでもパラメーターにブランチ/refを渡すことはできる。ただし、できることは デフォルトブランチのWorkflowを使ってデフォルトブランチから任意のブランチへcheckout するというようなことである。


   steps:
      - uses: actions/checkout@v2
        if: github.event.client_payload
        with:
          token: ${{ secrets.YOUR_PERSONAL_ACCESS_TOKEN }}
          ref: ${{ github.event.client_payload.ref }}

cf. Whats is the difference between repository_dispatch and workflow_dispatch in Github Actions? - Stack Overflow

Apparently, repository_dispatch events may only be read on the default branch