Skip to content

Instantly share code, notes, and snippets.

@yuya-takeyama
Last active Sep 14, 2021
Embed
What would you like to do?
Mono Repo のための GitHub Actions の Tips 集

paths フィルターを活用する

https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpaths

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 である前提です。 pushbranches を指定しなければ Pull Request のブランチに push した時には二重に Workflow が実行されてしまいます。:

workflow_run イベントからトリガーする 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 が定義できる 、ということです。

例えば以下のようなことに使えるでしょう。

基本的に 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 のファイル名や name の命名規則を持つ

これは人間にとってのわかりやすさもそうですが、前の項目にある通り workflow_run イベントから Workflow をトリガーするときのフィルタリングのためにも便利です。

Action を自作し、進化させる

これは 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 で開発するか、ということです。 いくつかパターンがあるので紹介します。

1. 独立した Repository で開発する

これがもっとも基本的なパターンですが、実をいうと Mono Repo 用の Action としては必ずしもこれを選択する必要はありません。

汎用性の高い Action であれば独立した Repository で開発するのが OSS 化する上でも便利ではありますが、特定の Mono Repo に特化した Action を開発する場合には改善の速度の面で足枷になることもあります。

2. Mono Repo 内のディレクトリで開発する

Action はディレクトリ上のファイルを直接実行することもできます。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      -  uses: ./.github/actions/build

このパターンを選択するメリットは、特に独立した Repository で開発するパターンと比べて、改善のサイクルを回しやすいことにありっます。 通常、外部の Repository の Action を実行する場合は、ブランチやタグを指定する必要があります。

Action に変更を加えて実際に Mono Repo で実行するには、例えば以下のようなステップを踏む必要があります。

  1. Action の Repository で必要な変更を行う
  2. Action の Repository で新たな tag を push する
  3. Mono Repo 側で Action の tag を新しいものに変更する

これが、Mono Repo 内のディレクトリの場合はこうなります。

  1. Action に必要な変更を行なって push する

ディレクトリを指定した場合は基本的に同一の branch のファイルが使用されるので、Pull Request を出せばその場で Mono Repo と結合してのテストができることになります。 つまり Action の実装に問題があっても Pull Request を出した時点で気づくこともできる、ということです。 素早くフィードバックが得られるので、Action の改善スピードとう点で有利です。

ただしこれは pushpull_request イベントの場合のみで、workflow_runissue_comment 等からトリガーする Action はデフォルトブランチにマージされて初めて実行されるという点に注意が必要です。

3. 独立した Repository で Mono Repo をシミュレーションしながら開発する

これは前の 2 つのパターンの融合です。

Mono Repo 内で Action を開発することのデメリットは、十分なテストができないまま変更をマージしてしまうかもしれないことです。 特に workflow_runissue_comment のような、マージするまでテストができないイベントです。

このパターンは、Action を独立した Repository で開発しつつ、その中に Mono Repo と同じ構成で package や service を保持しておくというものです。 すると、Action の Repository の中で直接結合テストができるので、フィードバックを素早く得られます。

それでいて Mono Repo 本体側との結合は Action を tag としてリリースし、Mono Repo 側の指定も更新することで初めて行われます。 なので、Action 側の Repository で十分にテストをして、安定した時点で Mono Repo 本体側に反映させる、ということもできます。

スタブとしての service/package を利用して E2E テストを実装することもできるかもしれません。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment