あけまして、おめでとうございます。神社のおみくじで、人生はじめて大吉を引きました、silverbirder です。
普段の業務で、FigmaのデザイントークンやAPIのスキーマファイル、i18nのメッセージファイルなどを、フロントエンドへ同期するコミュニケーションが不毛に感じています。そこで、GitHub ActionsとPull Requestを活用して、同期コミュニケーションを削減する仕組みを紹介します。
目新しい情報はないかもしれませんが、同じお困りごとを持つ人へ助けになれば、幸いです。
GitHub Actionsで使用するもの
今回紹介する仕組みの核となるのが GitHub Actionsのrepository-dispatch トリガーです。
https://docs.github.com/ja/rest/repos/repos?apiVersion=2022-11-28#create-a-repository-dispatch-event
このトリガーは、GitHub APIを経由して、GitHub Actionsのワークフローを起動することができます。そのため、次のように 異なるリポジトリでのGitHub Actionsワークフローを連携できます。
repository-dispatchとcreate-pull-requestは、次のGitHub Actionsです。
https://github.com/peter-evans/repository-dispatch https://github.com/peter-evans/create-pull-request
- respository-dispatch
- repository-dispatch-eventをdispatchするAction
- create-pull-request
- Pull Requestを作成するAction
これらのGitHub Actionsを使わずに gh
などを使って代替できますが、便利なモノを使って楽をします。
GitHubリポジトリ以外からのトリガー
GitHubのリポジトリ(username/other)からトリガーだけでなく、他のサービスからでもトリガーできます。例えば、Google Sheets からだと、Google Apps ScriptからGitHub APIを呼べばよいです。
他にも、Kibelaのoutgoing webhookを、Serverが受けて、ServerがGitHub APIを呼び出す方法があります。
Serverは、IFTTTやZapierのようなサービスでも良いですし、自前のサーバーでも良いでしょう。
自動commit
schemaファイルから、型を生成したい(yarn codegen)こともあると思います。そういうときは、次のフローを追加します。
git-auto-commit-actionは、変更したファイルをgit commitするだけのActionです。
https://github.com/stefanzweifel/git-auto-commit-action
create-pull-requestだけでも、自動commitすることができます。私は、次のケースで使用しました。
- FigmaのDesign Tokensで、Figma上からPull Requestを作成する。
- GitHub Actionsで、style dictionaryのbuildしたものをcommitしたい
on: pull_request: types: [opened] jobs: update: if: startsWith(github.head_ref, 'figma/') runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - run: npm ci - run: npx style-dictionary build - uses: stefanzweifel/git-auto-commit-action@v4
Preview
Figmaのデザイントークンや、i18nのメッセージファイルを更新したとき、Previewできる仕組みがあると、画面の確認ができて、良いです。
例えば、vercelやchromaticのpreviewです。
https://vercel.com/docs/concepts/deployments/preview-deployments https://www.chromatic.com/docs/review
サンプルコード
i18nのメッセージファイルをフロントエンドへ同期するGitHub Actionsを、紹介します。
repository | やること |
---|---|
username/frontend | i18nのメッセージファイルを利用 |
username/message | i18nのメッセージファイルを管理 |
# <username/message>/.github/workflows/main.yml on: push: branches: - main paths: - 'i18n/**' jobs: dispath: name: Setup runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: peter-evans/repository-dispatch@v1 with: repository: username/frontend token: ${{ secrets.PAT }} event-type: create-pull-request-message client-payload: '{"ref": "${{ github.ref }}"}'
# <username/frontend>/.github/workflows/main.yml on: repository_dispatch: types: [create-pull-request-message] jobs: createPullRequest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/checkout@v3 with: repository: username/message ref: ${{ github.event.client_payload.ref }} path: "tmp/" - run: | mv tmp/message.json src/message.json rm -rf tmp - uses: actions/setup-node@v3 - run: npm ci - run: yarn generate:message - uses: peter-evans/create-pull-request@v4
受け入れテストをマークダウンで管理
安心してマージできるように、受け入れテストを整備しておきましょう。
具体的には、cucumberで仕様書をMarkdown(MARKDOWN_WITH_GHERKIN)で管理します。
例えば、次のような仕様書です。
# Feature: Staying alive This is about actually staying alive, not the [Bee Gees song](https://www.youtube.com/watch?v=I_izvAbhExY). ## Rule: If you don't eat you die  `@important` `@essential` ### Scenario Outline: eating * Given there are <start> cucumbers * When I eat <eat> cucumbers * Then I should have <left> cucumbers #### Examples: | start | eat | left | | ----- | --- | ---- | | 12 | 5 | 7 | | 20 | 5 | 15 |
このMarkdownも、GitHub ActionsでPull Requestするフローに載せましょう。新しいシナリオが追加された場合、(cucumberのライブラリ上) テストコードが存在しないとエラーとなります。
機能で担保したいシナリオをMarkdownで管理していくことで、次のメリットがあります。
- 仕様が明確になる
- CIで受け入れテスト(cucumber)を動かし成功すると、仕様を満たす状態 となる
ハマったこと
GitHub Actions Botのcommitで、他のワークフローをトリガーできない
https://github.com/orgs/community/discussions/27028
tokenに、PATを渡すように変更すれば解決します。
他の解決策としては、workflow_run のトリガーを使えます。
https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#workflow_run
ただし、デフォルトブランチでのみ動作します。
repository-dispatchのPOSTは、JSONで制限がある
https://github.com/peter-evans/repository-dispatch#client-payload
同期したいファイルをjsonに変換して、dispatchするeventペイロードに含めようと、当初考えていました。ただ、次の懸念があったため、却下しました。
- jsonにしてしまうとコメントが消える
- JSONのバイトサイズに上限がある
そこで、同期したいリポジトリのgithub.refをeventペイロードに含めて、eventを受けた側がソースコードをチェックアウトして使う方針に切り替えました。
終わりに
GitHub ActionsとPull Requestを活用することで、自動的にアプリケーションのソースコードを更新する仕組みを簡単に組み立てられます。 このようなOpsがあれば、Slackでのメッセージラリーをする回数が減らせられます。ぜひ、ご活用ください。