CircleCI => GitHub Actions移行でのハマりどころと比較・2020夏
日本語docは翻訳が未完成なのは仕方ないとして、目次のページ内リンクが全て外れているのがかなり読みづらい
これだけでもチームの方には早めに直して欲しい。contributeできるっけ?
英語版が正なのは常として、GitHub Actionsの日本語docは結構Google検索indexで上位に来るようになっており、こちらの検索/言語設定をいじらない限り、いつもページ上部の言語設定を変える作業が挟まってダルい
GHAのcacheはcache-keyだけでなく、branchによって空間分離されている
当該branchと、そのbase branch、およびdefault branch(master)のcacheにはアクセスできるが、ほかの系統のbranchとはcache共有されない
CircleCIではcache-keyに.Branchなどの要素を盛り込まない限り、デフォルトでこのような分離はなかった
masterにまだmergeされていないファイルのhashを元にしているcache-keyを引こうとすると、結構missする。移行作業当初とかはありがち
Isolationという意味ではいいことでもあるので、覚書として
jobs.<job id>.needsを指定しているjobは、前提条件jobが1つ以上ifでスキップされた場合、起動しない
例えばビルド実行時間を短縮するために、git diffに含まれるファイルタイプを検知して無関係なjobをスキップなどしたい
ところが、スキップされうるjobを前提条件にしている後続jobが前提条件未達で起動しないと困ってしまう。skip = successとしてほしいのだが、挙動としてはskip = failureになってしまっているイメージ
当座の回避策としては、「skipしてもよい前提条件」としたいjobは、job自体はskipせずに常に起動するようにしつつ、stepのほうをskipさせる。これによってjob自体は起動→即成功するので条件を満たす
stepがたくさんあるjobだとconfigが膨らむが。。。runディレクティブが多いのであればrun: |記法で複数行のrunを結合してifを1箇所にまとめると少し圧縮できる
Repositoryのbranch protection ruleで、merge前に通過必須としてあるcheckを含むworkflowがon.<event>.pathsなどのオプションでskipされると、merge条件を満たさない
これも前項と似ていて、skip = successとしてほしいのだがskip = failureとなっている状態
やはり回避策も同じで、workflow及びjob自体は常に起動するようにしつつ、job の内部でstepごとにskipさせる
ちなみに、なんでこうまでして色々skipしたいかというと、
CIの実行時間が短ければ短いほど早くフィードバックを得られてPR/コードレビュー中心の開発は捗る
同じくデプロイ所要時間も短ければ短いほどよい。Monorepoで、master merge時に明らかに無関係なパートのテストなどはskipしてどんどんデプロイしたい
ただしこれは諸刃の剣で、思わぬモジュール間依存性を見逃す危険性を孕む。Layer cacheの効くself-hosted runnerなどを活用してフルテストを早めるアプローチもある
節約になる。例えばteam planの3000分という月間実行時間はなかなか絶妙な設定で、富豪的に回してると容易に上限突破する
Layer cacheオプションはまだない。Officialでない、シェアの低いコンテナイメージは基本的に起動時full-pullになりがち
使用してる言語によってはしょうがない
Self-hosted runnerで自分のニーズに合ったrunnerを用意(&容量が許す限りlayer cacheを保持)するのが現状では最も速くできる
actions/cacheでlayer cacheをworkflow cacheに保管してみたり、--cache-fromオプションでremote cacheを引いてきたりといろいろ試している記事が複数あるが、共通する結論としては「BuildKitを有効にするだけ」が最も非侵襲的で効果も保証される、という現状
cache hitしたらかなり速くなる方法はあるものの、必然的にcache miss時のcache保存処理で余計に時間がかかるのを避けられないため、正確な時短効果を見積もるにはcache hit率に基づく期待値を評価することになる。当然そのような見積もりも設定も手間ではあるので、面倒ならBuiltKitの適用だけにとどめて、公式のlayer cache対応を待つか、self-hosted runnerを検討するほうが良さそう
参考にした記事
on: scheduleによる定時起動はあまり厳密でない
リンク先ほどひどくはないが、最近でも20分くらいの遅延起動は観測できた
そもそもコードの変更に起因しない処理をどこまでGHAなどのクラウドCIにやらせるかは微妙な問題だと思っていて、ビジネス上重要であれば信頼性の高い専用の定時処理系を用意したほうがいい
CircleCIと比較して良いところ
outputsを使ってカジュアルにjob間・step間で情報を受け渡せるので、ifと組み合わせて細かな条件分岐や依存関係などを記述できる
これは逆の面もあり、outputsを始めとするworkflow設定のシンタックスに慣れないと読解できないので、Jenkinsおじさん、CIおじさんに連なる系譜のGHAおじさんが登場する見込み
マネージド実行環境(CircleCIでいうmachine executor)にインストールされてるツールが多く、特定コンテナ内でなくても実行できるjobなら起動時間・実行時間を大幅に削減できる
大きなところでいうと、docker-composeやawscliが最初から入っているので、テストにもデプロイにも便利
デフォルト実行環境のスペックがちょっとだけ高い(2vCPU, 7GB memory)
実行環境をself-hostできる
これはGitLab CIでもできた
self-host runnerは、GitHubが提供するrunner applicationを実行できさえすればあとは自由で、ニーズに応じて好きなものをインストールしたり、キャッシュを置いといたりできる
GitHubと密に連携できる
と、期待してはいるのだが、流石にまだCircleCIのほうが全体的に一日の長があると感じられる部分も多い。あくまでポテンシャル
たとえばworkflowの起動時間とかもそんなに速いわけではない。3rd partyと同様にwebhookで起動されているように見受けられる
とはいえ現段階でもすでにいいところはいくつかある
デフォルトでrepositoryに対し一定の権限を持ったGITHUB_TOKENが生成されるのが便利で、repositoryにAPI経由でフィードバックするworkflowを簡単に作れる
workflow設定内で、workflowを起動したeventオブジェクトを参照できるので、それを元に細かな条件記述が可能
逆に比較してまだ駄目なところ
UIの情報が少ない
例えばjob間の依存関係を視覚的に把握するとか。まあおまけではあるけど
チーム開発で重要なactionがまだまだ揃ってない
例えばslack連携のactionはGitHub/Slackいずれからも公式リリースがなく、非公式actionが乱立していて選定が必要
CI失敗時の通知などは必須だと思ってるのでデフォルト機能として持っててほしいくらいだが、まだない
AWSは頑張っていて、公式のaws-actionsが続々登場している