Mono Repo では package や service をディレクトリとして表現するので、特定のディレクトリが変更された時だけ実行したい Workflow があると思います。 典型的にはテストやビルドでしょう。
foo
ディレクトリ内のファイルに変更があったときのみトリガーするには以下のうに指定します。
on:
push:
paths:
- 'foo/**'
# 対応する Workflow のファイルも対象に追加することで、Workflow のみ変更した時もテストできて良いでしょう
- '.github/workflows/foo.yaml'
Pull Request からトリガーしたいときは典型的には以下のようになるでしょう。
on:
push:
branches:
- main
paths:
- 'foo/**'
pull_request:
paths:
- 'foo/**'
これはデフォルトブランチが main
である前提です。
push
の branches
を指定しなければ Pull Request のブランチに push した時には二重に Workflow が実行されてしまいます。:
workflow_run
とは何か、という説明は以下の通り。
https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_run
This event occurs when a workflow run is requested or completed, and allows you to execute a workflow based on the finished result of another workflow.
つまりこれがどういうことかというと、Workflow ための Workflow、Meta-Workflow が定義できる 、ということです。
例えば以下のようなことに使えるでしょう。
- Workflow Run のエラー通知
- Workflow Run ごとの実行時間の収集
- 同一 branch における重複した Workflow Run の自動キャンセル
基本的に Mono Repo というのは同室の多数の Repository (例えばパッケージやサービス等) を統一されたフローで管理するための手法だと思うので、このような Meta-Workflow は重要な役割を果たします。
例えば Workflow Run の完了時に必ず起動する Workflow は以下のように定義します。
on:
workflow_run:
types:
- completed
このとき実行対象の Workflow を限定するときは以下のように。
on:
workflow_run:
workflows:
- 'foo / test'
- 'bar / test'
# ワイルドカードの使用も可能
- '* / test'
types:
- completed
これは人間にとってのわかりやすさもそうですが、前の項目にある通り workflow_run
イベントから Workflow をトリガーするときのフィルタリングのためにも便利です。
これは Mono Repo に限りませんが、Mono Repo の場合にはより重要度が増すと考えます。
Action の作り方は以下を参照してください。 https://docs.github.com/en/actions/creating-actions
簡単なシェルスクリプトで実装できるものなら Composite Action、より複雑なものは Docker または JavaScript で作るのが良いでしょう。 JavaScript Action の場合は、実際は typescript-action を元に作ると継続的なメンテナンスをする上で良いでしょう。
Mono Repo を運用する上では開発フローを継続的に進化させていくことが重要であり、Action 自体も継続的に開発していくことになるでしょう。 その時に重要になるのが Action をどこの Repository で開発するか、ということです。 いくつかパターンがあるので紹介します。
これがもっとも基本的なパターンですが、実をいうと Mono Repo 用の Action としては必ずしもこれを選択する必要はありません。
汎用性の高い Action であれば独立した Repository で開発するのが OSS 化する上でも便利ではありますが、特定の Mono Repo に特化した Action を開発する場合には改善の速度の面で足枷になることもあります。
Action はディレクトリ上のファイルを直接実行することもできます。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: ./.github/actions/build
このパターンを選択するメリットは、特に独立した Repository で開発するパターンと比べて、改善のサイクルを回しやすいことにありっます。 通常、外部の Repository の Action を実行する場合は、ブランチやタグを指定する必要があります。
Action に変更を加えて実際に Mono Repo で実行するには、例えば以下のようなステップを踏む必要があります。
- Action の Repository で必要な変更を行う
- Action の Repository で新たな tag を push する
- Mono Repo 側で Action の tag を新しいものに変更する
これが、Mono Repo 内のディレクトリの場合はこうなります。
- Action に必要な変更を行なって push する
ディレクトリを指定した場合は基本的に同一の branch のファイルが使用されるので、Pull Request を出せばその場で Mono Repo と結合してのテストができることになります。 つまり Action の実装に問題があっても Pull Request を出した時点で気づくこともできる、ということです。 素早くフィードバックが得られるので、Action の改善スピードとう点で有利です。
ただしこれは push
や pull_request
イベントの場合のみで、workflow_run
や issue_comment
等からトリガーする Action はデフォルトブランチにマージされて初めて実行されるという点に注意が必要です。
これは前の 2 つのパターンの融合です。
Mono Repo 内で Action を開発することのデメリットは、十分なテストができないまま変更をマージしてしまうかもしれないことです。
特に workflow_run
や issue_comment
のような、マージするまでテストができないイベントです。
このパターンは、Action を独立した Repository で開発しつつ、その中に Mono Repo と同じ構成で package や service を保持しておくというものです。 すると、Action の Repository の中で直接結合テストができるので、フィードバックを素早く得られます。
それでいて Mono Repo 本体側との結合は Action を tag としてリリースし、Mono Repo 側の指定も更新することで初めて行われます。 なので、Action 側の Repository で十分にテストをして、安定した時点で Mono Repo 本体側に反映させる、ということもできます。
スタブとしての service/package を利用して E2E テストを実装することもできるかもしれません。