Repository Dispatch を GitHub Apps トークンで動かす GitHub Actions を作った
はじめに
GitHub Actions を使ったピタゴラスイッチを構築する上で repository_dispatch
は非常に重要です。
これまで repository_dispatch
を GitHub Actions のジョブで利用する際 peter-evans/repository-dispatch
を活用してきました。
トークンは Personal Access Token (PAT) を使っていたのですが GitHub Apps のトークンに移行することにしました。
しかし、うまく動かず ...
今回 GitHub Apps トークンで repository_dispatch
を動かすために試行錯誤
し最終的に GitHub Actions Marketplace を作るところまで実装してみたのでその紹介記事です。
2024/09/11 追記: GitHub Apps によるトークン生成時に repository_dispath
対象の owner/repository を下記のように設定すれば peter-evans/repository-dispatch を動かせることが判明しました。
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.GITHUB_APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: $target_repository_name
peter-evans/repository-dispatch
前述していたとおり repository_dispatch
を GitHub Actions で呼び出す際は peter-evans/repository-dispatch
を利用していました。
Personal Access Token (PAT) は管理がめんどくさいので GitHub Apps トークンへと移行するモチベーションがありました。
よし、GitHub Apps トークンの準備はできた! peter-evans/repository-dispatch
に渡して実行しよう! ... ん??? ... 動かない ... ???
Run peter-evans/repository-dispatch@v2
with:
token: ***
repository: owner/name
event-type: event-type
client-payload: {"payload": "xxxxxxxxxx"}
Error: Resource not accessible by integration
なんだろう。権限かな ... ???
GitHub Apps に対しては必要とされる権限渡しているんだけどな ... ???
そういえば前に外部から repository_dispatch
起動させるために Go の実装[1]したことあったけどそれだと動いたよな ... う〜ん peter-evans/repository-dispatch
のドキュメントを確認しよう。
GITHUB_TOKEN (permissions contents: write) or a repo scoped Personal Access Token (PAT). See token for further details.
え ... GitHub Apps トークンに対応していない ... !!!
なるほど、そりゃ動かないわけです。
2024/09/11 追記: actions/create-github-app-token 利用時に owner と repositories を指定すれば権限が適切に払い出されます。また、最新のドキュメントについては下記をご参照ください。
Go で CLI を実装
ちょっと前に repository_dispatch
起動のコードを Go で実装をしていたのでそれを起点に作り直します。
Go で CLI を実装するといえば 標準ライブラリを使うか spf13/cobra
を使うかになるかと思います。標準ライブラリだと機能が不足しているのでちょっとしんどいな ... spf13/cobra
でも機能が豊富すぎて手軽に実装するにはちょっとしんどいな ...
ということで urfave/cli
を利用することにしました。公式ドキュメントにサンプルコードもあったので結構手軽に実装できました。
ある程度形ができたあと GitHub Actions から呼び出して調整し最終的に以下のような CLI となりました。
NAME:
repository-dispatch - Repository Dispatch a GitHub Actions workflow
USAGE:
repository-dispatch [global options] command [command options]
DESCRIPTION:
Dispatch a GitHub Actions workflow for a repository. Please specify github apps token or github apps app id and github apps app private key.
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--client-payload value, -p value GitHub Client Payload
--event-type value, -e value GitHub Event Type
--id value, -i value GitHub Apps ID
--private-key value, -k value GitHub Apps Private Key
--repository-name value, -n value GitHub Repository Name
--repository-owner value, -o value GitHub Repository Owner
--token value, -t value GitHub Apps Token
--help, -h show help
GitHub Apps トークンだけを渡して実行するパターンと GitHub Apps ID と GitHub Apps Private Key を渡して実行するパターンに対応してみました。
go install github.com/otakakot/repository-dispatch@latest
上記コマンドでインストールし実行可能なので気になった方はお試しください。
せっかくだから、 repository_dispatch
をパッケージとしてインポートしてコードから手軽に呼び出せるような構成にもしてみました。が、動作は未確認です ...
GitHub Actions で CLI を呼び出す
めでたく go install
で動かせるようになりました。 CI 上で go install
して呼び出すことで目的は達成できそうです。でもせっかくなので GitHub Actions で手軽に呼び出せるようにしてみるかと思いもう少し手を動かしてみました。
独自のアクションは以下の公式ドキュメントを参考にすることで作成できます。
おや、 Docker
もしくは JavaSrcipt
でしか実装できない ... ???
いや、そんなことはなかったです。よくよくみると複合アクションというのを使えばもうちょっと自由度高く実装できそうです。
最終的には以下のようにして jobs
設定で呼び出せるように調整しました。
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.GITHUB_APPS_ID }}
private-key: ${{ secrets.GITHUB_APPS_PRIVATE_KEY }}
owner: owner
repositories: repository
- name: Dispatch
uses: otakakot/repository-dispatch@v1.0.0
with:
token: ${{ steps.generate-token.outputs.token }}
repository: owner/repository
event-type: event-type
client-payload: '{"payload": "xxxxxxxxxx"}'
渡すパラメータについては peter-evans/repository-dispatch
を参考にしています。 with
で渡す値が同じになるようにしています。
Go で作成した CLI ツールとの整合性を取るために bash で受け取った値を整形していたりします。
独自アクションの実装として必要となる action.yaml
は以下のようになりました。
name: 'GitHub Repository Dispatch'
description: 'Create a repository dispatch event'
inputs:
token:
description: 'GitHub Apps Token'
required: true
repository:
description: 'The repository to send the dispatch event to'
default: ${{ github.repository }}
event-type:
description: 'A custom webhook event name.'
required: true
client-payload:
description: 'JSON payload with extra information about the webhook event that your action or worklow may use.'
default: '{}'
runs:
using: 'composite'
steps:
- name: Set GitHub Path
run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH
shell: bash
env:
GITHUB_ACTION_PATH: ${{ github.action_path }}
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22.1
cache: false
- name: Repository Dispatch
run: entrypoint.sh
shell: bash
env:
TOKEN: ${{ inputs.token }}
REPOSITORY: ${{ inputs.repository }}
EVENT_TYPE: ${{ inputs.event-type }}
CLIENT_PAYLOAD: ${{ inputs.client-payload }}
#!/bin/bash -ue
go install github.com/otakakot/repository-dispatch@latest
repos=(`echo ${REPOSITORY} | tr '/' ' '`)
repository-dispatch --token ${TOKEN} --event-type ${EVENT_TYPE} --repository-owner ${repos[0]} --repository-name ${repos[1]} --client-payload "${CLIENT_PAYLOAD}"
shell 内で go install
を使い CLI をインストールしています。
ツールへのパスを通すために setup-go
で Go の環境をセットアップしています。
これでめでたく Go による GitHub Actions を作ることができました!88888888
おわりに
今回の成果物は以下においておきます。
本格的に使ってもらうために README.md とかバージョン管理とかちゃんとしないとです ...
というかそもそも別の方がライブラリが存在するのであれば教えていただきたいです。
Discussion