Slide 1

Slide 1 text

© DeNA Co., Ltd. 1 業務で使えるかもしれない…!? GitHub Actions の Tips 集 幸田優哉 品質本部品質管理部 SWET 第二グループ 株式会社ディー・エヌ・エー

Slide 2

Slide 2 text

© DeNA Co., Ltd. 2 Yuya Koda 昨年9月に DeNA の SWET チームに Join しました。 業務では全社向けに提供している GitHub Actions self-hosted runner をいい感じにしています。 最近のマイブームはボルダリングと Bluesky でどう でもいい日常をつぶやくことです。 DeNA 品質本部品質管理部 SWET 第二グループ ponkio_o © DeNA Co., Ltd. 自己紹介 koday.me

Slide 3

Slide 3 text

© DeNA Co., Ltd. 3 GitHub Actions 使っている人✋

Slide 4

Slide 4 text

© DeNA Co., Ltd. 4 今日は使う中でハマったポイントや Tips を紹介します

Slide 5

Slide 5 text

© DeNA Co., Ltd. 5 matrix job

Slide 6

Slide 6 text

© DeNA Co., Ltd. 6 1 同じような Job を並列実行したい ● 「ほとんど同じ処理なんだけど微妙にパラメータが違う」といった場面はよくある ○ 複数のディレクトリで何かをしたい ○ 複数のバージョンでテストしたい ○ 複数のアーキテクチャでビルドしたい ● for などでループさせることもできるが、これらは多くの場合に独立して実行可能 なのでできれば並列実行させたい

Slide 7

Slide 7 text

© DeNA Co., Ltd. 7 2 matrix job とは ● jobs..strategy.matrix に渡す情報から複数の Job を並列で実行でき る機能 ● 例えば「バージョンと OS の組み合わせ」を事前に定義しておくことで、同じ Job の 定義でバージョンと OS の値だけを差し替えて、並列で実行させることができる ○ 単なる配列の他に Map も設定可能 ○ 並列実行の上限を指定したり、値の上書きや除外などもできる → 工夫次第で幅が広がる Actions の便利機能の1つ

Slide 8

Slide 8 text

© DeNA Co., Ltd. 8 3 実行例

Slide 9

Slide 9 text

© DeNA Co., Ltd. 9 4 Input に JSON が使える ● 公式ドキュメントの Using a matrix for your jobs のページには記載がないが、 Expressions に記載がある ● 使い方は jobs..strategy.matrix に JSON を渡すだけ ○ 文字列として組み立てた場合には fromJSON() として受け取ることで matrix に展開することができる ○ GitHub Actions の各種コンテキストは JSON で渡ってくるのでそのまま渡せ ば使える

Slide 10

Slide 10 text

© DeNA Co., Ltd. 10 4 Input に JSON が使える

Slide 11

Slide 11 text

© DeNA Co., Ltd. 11 5 JSON を応用した使い方 これを使うと Workflow で利用する値を外部注入できるので、様々な応用ができる ● GitHub Actions の Contexts の情報を用いる ○ PR に付与されるラベルに応じて Job を組み立てたり、Workflow Dispatch の Input で動的に Job を組み立てるなど ○ Contexts はもともと JSON で渡ってくるので fromJSON() 不要 ● リポジトリ内の YAML や JSON ファイルに値を切り出す ○ Workflow からは checkout 後に対象のファイルを読んで fromJSON() するだけ

Slide 12

Slide 12 text

© DeNA Co., Ltd. 12 5 JSON を応用した使い方 ponkio-o/select-target-action はこれを応用した Action で、PR に付与したラベルに応じ て事前に定義した値を返してくれる。つまり PR のラベルでパラメータを注入できる https://github.com/ponkio-o/select-target-action

Slide 13

Slide 13 text

© DeNA Co., Ltd. 13 6 Tips: Secrets を扱いたい matrix で secrets の値を出し分けたい場面、直感的には matrix に ${{secrets.HOGE}} したくなるが、これはできない

Slide 14

Slide 14 text

© DeNA Co., Ltd. 14 6 Tips: Secrets を扱いたい ワークアラウンドとして ${{secrets[matrix.hoge]}} することで利用できる Secrets in matrix - https://github.com/orgs/community/discussions/26302

Slide 15

Slide 15 text

© DeNA Co., Ltd. 15 動的な Job の実行と Branch Protection

Slide 16

Slide 16 text

© DeNA Co., Ltd. 16 1 Branch Protection を設定したい PR 作成時に実行される Job には GitHub で設定可能な Branch protection rule を設定する ことが多い。例えば linter やテストなどの正常終了を強制したい場合

Slide 17

Slide 17 text

© DeNA Co., Ltd. 17 1 Branch Protection を設定したい Branch Protection Rule では GitHub Actions でいうところの “Job” を指定できる 例えば下記だと build-check / lint / test のいずれか (もしくは複数) を選択可能

Slide 18

Slide 18 text

© DeNA Co., Ltd. 18 1 Branch Protection を設定したい 先ほどの例だと PR 作成時点で全部通って欲しい Job なので下記のように設定してみる

Slide 19

Slide 19 text

© DeNA Co., Ltd. 19

Slide 20

Slide 20 text

© DeNA Co., Ltd. 20 よさそう💯

Slide 21

Slide 21 text

© DeNA Co., Ltd. 21 Job をフィルタリングしたい

Slide 22

Slide 22 text

© DeNA Co., Ltd. 22 2 Job をフィルタリングしたい ● CI が複雑になってくると実行する Job をフィルタリングしたくなってくる ○ 主な動機は Job の実行時間やコストを削減したいため ● 例えば README のみの更新で重たいビルド処理や関係ないテストが走ることを 防ぎたい

Slide 23

Slide 23 text

© DeNA Co., Ltd. 23 3 Actions で利用できる paths フィルター ● on.pull_request.paths などを利用すると、特定のファイルに変更があった時 のみ Workflow をトリガーさせることができる ○ 例えば下記だと Dockerfile が変更された時のみ実行される

Slide 24

Slide 24 text

© DeNA Co., Ltd. 24 4 paths フィルターと Branch Protection ただし on.pull_request などで利用できる paths は Workflow 全体の実行を制御するもの であり、条件に一致しなかった場合には Workflow 内に存在するいずれの Job も実行されず Pending になる

Slide 25

Slide 25 text

© DeNA Co., Ltd. 25 5 一部の Job が実行された場合 Branch Protection で設定したステータスチェックは全て満たす必要があるため、Workflow ファイルを分割して特定の Job だけが実行されたケースも同様に PASS したことにはならない

Slide 26

Slide 26 text

© DeNA Co., Ltd. 26 6 ここまでをおさらい ● Branch Protection には複数の Job を設定可能 ○ ただし設定した「すべての Job」を PASS させる必要がある ● GitHub Actions 組み込みの paths フィルターは、Workflow 全体を制御するため Branch Protection に設定した Job を内包する Workflow に対しては利用できない ○ 条件を満たさずに実行されなかった Job は Pending になるため → 条件に応じて Job を出し分けつつ、Branch Protection の Job を Pending にさせたくない

Slide 27

Slide 27 text

© DeNA Co., Ltd. 27 Filtering Job

Slide 28

Slide 28 text

© DeNA Co., Ltd. 28 7 dorny/paths-filter を利用したフィルタリング ● 前述のように Branch Protection で指定した Job を内包する Workflow が存在す る場合、その Workflow は必ず実行する必要がある ○ 組み込みの paths フィルターとの相性が悪い ● ステータスチェックを利用しつつ、Job のフィルタリングを実現するためのワーク アラウンドとして「フィルタリング用の Job」を設けるやり方がある ○ Workflow 全体でフィルタリングせずに Job を出し分ける ○ それを実現できるのが dorny/paths-filter

Slide 29

Slide 29 text

© DeNA Co., Ltd. 29 8 dorny/paths-filter の使い方 ファイルやディレクトリなどを指定すると、変更があったかどうかを output で返してくれる また変更の有無だけでなく、マッチしたファイル数やファイルの一覧なども利用可能 → これにより Workflow を実行しつつ Job をフィルタリングすることが可能になる

Slide 30

Slide 30 text

© DeNA Co., Ltd. 30 9 Tips: dorny/paths-filter の応用 フィルタ設定をファイルに切り出したり、YAML Anchor が利用できたり、Shell と組み合わせ て使う例など README の Examples が非常に充実している

Slide 31

Slide 31 text

© DeNA Co., Ltd. 31 Status Check Job

Slide 32

Slide 32 text

© DeNA Co., Ltd. 32 Status Check Job ● Status Check Job (勝手に呼んでいる) とは Branch Protection に設定する専用の Job を設けるワークアラウンド ● この Job を PASS させたり Fail させることで Branch Protection を機能させる 10

Slide 33

Slide 33 text

© DeNA Co., Ltd. 33 ステータスチェックが PASS する条件 ● Branch Protection で指定した Job が成功として扱われる(PASS する)条件は複数ある ○ Job が正常終了した場合 ■ よくある exit 0 で終了するパターン ○ jobs..if によってスキップされた場合 ■ フィルタリングによって Job が実行されないパターン ● スキップが許されるのは Workflow ではなく Job である点に注意 ○ Workflow の場合には Pending になる (前スライド参照) → これを踏まえて「ステータスチェック用の Job」を組み立てる 11

Slide 34

Slide 34 text

© DeNA Co., Ltd. 34 12 Status Check Job の使い方 下記のような Job を設けて jobs..needs に強制したい Job を列挙するのみ if: failure() は needs のいずれかの Job が失敗した場合に実行させるための条件

Slide 35

Slide 35 text

© DeNA Co., Ltd. 35

Slide 36

Slide 36 text

© DeNA Co., Ltd. 36

Slide 37

Slide 37 text

© DeNA Co., Ltd. 37 13 Tips: Status Check Job の書き方 別の書き方として、下記のように needs を満たしてから正常終了させる方法もあるが、この Job のために毎回ランナーが確保されて時間がかかるのでオススメしない (前述の通り、明示的なスキップは PASS の扱いになる)

Slide 38

Slide 38 text

© DeNA Co., Ltd. 38 GITHUB_TOKEN

Slide 39

Slide 39 text

© DeNA Co., Ltd. 39 1 GITHUB_TOKEN について ● 自動生成される GitHub Actions 上で利用可能な GitHub の Token ● Personal Access Token (PAT) や GitHub Apps の作成を行わなくても GitHub API を 実行することができる ○ ただしいくつか制約が存在する

Slide 40

Slide 40 text

© DeNA Co., Ltd. 40 2 GITHUB TOKEN は Workflow をトリガーできない ● GITHUB_TOKEN を利用してコミットを積むことができる ○ 例えば formatter によるフォーマットの修正を自動でコミットするなど ● ただし GITHUB_TOKEN によるコミットは Workflow をトリガーできない ○ > For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur. ● そのため Branch protection が設定されている場合には GitHub App で発行した Token もしくは PAT の利用が必要になる ○ GITHUB_TOKEN の場合にはトリガーされないため Pending で止まる

Slide 41

Slide 41 text

© DeNA Co., Ltd. 41 3 権限について ● デフォルト付与されている権限がまあまあ広い ○ ドキュメントの Permissions for the GITHUB_TOKEN に記載がある通り ● Workflow や Job レベルで必要最低限のものを付与するのが良い ○ permissions もしくは job..permissions で設定可能 ○ そもそも不要な場合には permissions:{} で無効化できる ● 1つでも permissions を指定した場合には、指定されたもの以外が暗黙的に拒否され るため注意 ○ 「OIDC を利用したくて id-token: write だけ指定したら checkout できなく なった」など

Slide 42

Slide 42 text

© DeNA Co., Ltd. 42 4  4 Tips: suzuki-shunsuke/ghalint で設定をチェックする @szkdash さん作の OSS で、GITHUB_TOKEN に限らず GitHub Actions の Workflow に関 する様々なセキュリティプラクティスを適用するための Linter https://github.com/suzuki-shunsuke/ghalint

Slide 43

Slide 43 text

© DeNA Co., Ltd. 43