世界を動かす技術を、日本語で。

GitHub Actionsがエンジニアリングチームを徐々に疲弊させている

概要

  • CircleCI 初期メンバーによるCIシステムの実体験に基づく批判
  • GitHub Actions の使い勝手や設計の問題点を詳細に解説
  • YAML地獄Marketplace の危険性について言及
  • 自分の計算資源を持てない ことの不便さを指摘
  • 細かい不満点が積み重なり、 理想的なCI体験 からは程遠い現状を説明

GitHub Actionsの「体験」とは何か

  • CIシステム としてのGitHub Actionsの普及理由は、 リポジトリに統合されている ことのみ
  • ビルド失敗時 のUI遷移は複雑で、 エラー特定までに多くのクリック と待ち時間が発生
  • ログビューア は長大なログに対応できず、 ブラウザが頻繁にクラッシュ
  • 問題解決のために 生ログをダウンロード し、ローカルで確認する必要性
  • 戻るボタン の挙動が不安定で、 目的のPRページに戻れない ストレス

デバッグ・ループの苦痛

  • コミット→ビルド→失敗→修正 のサイクルが 非常に遅い
  • 小さな修正でも フィードバックループが20分 かかることも
  • 何度も繰り返す ことで、作業効率とモチベーションの低下

「YAML地獄」と表現言語

  • すべてのCIは結局 大量のYAML管理 に行き着く
  • GitHub Actions YAML は独自の表現言語や文脈モデル、複雑な補間ルールを持つ
  • 条件付き環境変数設定や式展開で 微妙なミスが頻発しやすい
  • ドキュメントよりも失敗から学ぶ 設計で、学習コストが高い

Marketplaceのリスク

  • Marketplace には質のばらつきが大きい サードパーティ製アクション が多数存在
  • 外部アクションを使うたびに、 リポジトリやシークレットへのアクセス権を他人に渡す リスク
  • 依存管理の「正常化」による セキュリティリスクの見落とし

計算資源の制約とランナー事情

  • Microsoftのランナーは遅く、カスタマイズ不可
  • 高速なビルド大規模リソース が必要な場合、追加料金が高額
  • サードパーティ企業(Namespace, BuildJet等)が「 速いGitHub Actionsランナー」をビジネスにする現状
  • セルフホストランナー も利用可能だが、 YAMLやUIの問題は解決しない

細かい不満点の蓄積

  • キャッシュ管理 が分かりにくく、 デバッグに多くの時間がかかる
  • 再利用ワークフロー の制限やテストしづらさ
  • GITHUB_TOKENの権限管理 が複雑で、細かい制御が困難
  • 同時実行制御の柔軟性不足
  • シークレットをif条件で使えない ため、ワークフローの分岐に工夫が必要

Nix Shopへの言及

  • Nix Shop の場合、 Garnix のような新世代CIツールで YAML不要の自動ビルド が可能
  • 多くの開発現場はNix Shopではないため、 一般的なCI利用者向けの問題提起

まとめとCIの理想像

  • Buildkite のような「 理想的なCI体験」と比較し、GitHub Actionsの現状を問題視
  • 細かい不満点が積み重なり、開発者体験が大きく損なわれている現実
  • 真に 開発者が求めるCI とは何か、再考を促す内容

Hackerたちの意見

作者が挙げているCIシステムは色々使ったけど、CircleCIやGitHub Actionsもたくさんやってきたけど、あんまり同じ結論には至ってないな。ただ一つ注意点があって、作者が推してるBuildkiteは使ったことがないんだよね。年々、CIツールは専門的なものから一般的なものに変わってきた。JenkinsはもともとJavaプロジェクトのビルドには優れてたけど、それ以外はあんまりだったし、TravisもRailsプロジェクト用の明確なステップがあった。CircleCIも昔はそんな感じだった。これは行き止まりだったんだ。CIは特別なものじゃないって、コミュニティとして気づいたんだよね。実際、CIジョブは多様で、ウェブフレームワークや言語の知識をCIシステムに組み込むのは良くないアイデアだって分かったから、CIシステムは一般的なワークフローオーケストレーターになったんだ。ログや合否のUIがちょっと乗っかってるだけ。これは良いことだよ!CircleCI 2からGitHub Actionsに移行したのも、まさにCircleCIが専門から一般モデルへの移行を失敗したからで、そのモデルではパフォーマンスが良くて正しいCIシステムを表現できなかったんだ。GHAではそれができた。GHAにも欠点はあるけど、ログブラウザ?どうでもいいよ、ファイルをダウンロードすればいいし、少なくともCIは動くから。YAML?まぁ、ちょっとYAMLじゃないけど、設定フォーマットに追加の意味を持たせるのは最初でも最後でもないし、全てのCIシステムには独自のクセがあるからね。プラグインがDockerイメージ?重いかもしれないけど、正直言って悪いUXではないよ。何が大事かって?自分のコンピュートを持つこと?そうだね!これは重要だけど、主要なCIシステムではどれでもできるから、差別化にはならない。ダイナミックパイプライン?それは本当に素晴らしいし、Buildkiteを選ぶ理由としてはいいね。これらのプラットフォームでの経験からの私の結論は、Actionsは本当に重要な点では「かなり良い」し、他の点では問題ないってこと。もし会社を始めるならBuildkiteを選ぶかもしれないけど、オープンソースプロジェクトにはActionsがいいよ。

Actionsはいろんな役割を持ってる。イベントディスパッチャー、オーケストレーター、実行エンジンとランタイム、アーティファクトレジストリとキャッシングシステム、ワークフローモデラー、市場、シークレットマネージャー。これでもまだActionsの全てを挙げてないんだ。いくつかの点では優れてるけど、他の点ではそうでもない。私がGHAを使って設計するシステムは、通常は良い部分だけを使うことが多い。例えば、GitHubはイベントディスパッチャーとしては優秀だけど、ワークフローオーケストレーターとしてはあんまり良くない。だから、そういうのが得意なシステムに任せた方がいいよ。

でも…ログブラウザ?何が悪いの、ファイルをダウンロードすればいいじゃん、少なくともCIは動いてるし。彼らは「何が悪いの?」に対してかなり直接的に答えてるよ:>> ビルドログはターミナルの出力みたいに見える、だってターミナルの出力だから。ANSIカラーもちゃんと使えるし、テストフレームワークの素敵なフォーマットもそのまま表示される。エスケープコードが食われて文字化けしたウェブUIを見て目を細める必要もない。これは些細なことに聞こえるけど、全然そうじゃない。ビルドログを一日に何十回も読むんだから、その体験は快適な椅子が大事なように重要なんだ。悪い椅子に6時間座ってから、その重要さに気づくものだよ。生のログでANSIエスケープコードを無視しなきゃいけない(テキストを検索することすらできない)って、控えめに言ってもすごくイライラする。

実は、逆の意見なんだ。ゲーム開発ではビルドシステムにすごく気を使ってるんだけど、残念なことに、問題を解決するためにお金を投げてくれる会社がほとんどないんだよね。少数の会社はいるけど、めちゃくちゃ高い(Incredibuildとか)。ビルド時間が長いから、短縮するのが理想なんだ。だから、もしビルドシステムがビルドグラフを理解していなかったら、ビルドを待つ時間がさらに長くなるか、インクリメンタルな状態や汚れたワークスペースを持ち続けることになる(これが一時的なバグを引き起こすんだよね、だってコンパイラは結局インクリメンタルビルドをしなきゃいけないから)。だから、ビルドシステムはゲームの構築方法の複雑さをしっかり理解しておく必要があるんだ(UnrealEngine HordeやUBAみたいなものにつながる)。もし「汎用的な」アプローチを使ったら、場合によってはビルドに1日以上待たされることもあるよ、どんなにハードウェアが良くてもね。

最近のGitHubはどんどん信頼性が低くなってるから、これがますます真実になってる。先週見たことは: - actions/checkoutが理由もなく失敗して、3回目のリトライでやっと成功することもあった - リリースCIジョブが2回スケジュールされて失敗することがあった、だってもちろんリリースはすでに存在してるし - ジョブがスケジュールされないこともあった。時には40分も。数年間アクティブに使ってきたけど、作者が言ってることを置いといても、基本的な信頼性がどんどん悪くなってる。zigが正しかったんだろうね。Buildkiteを逃したのは残念だけど、Codebergは私の経験ではあんまり信頼性も速さもなかった。

そうだね、GitHub Actionsのクロンってちゃんと動くの?この前設定しようとしたら、ランがランダムにスキップされちゃった。全然信頼性がないっていうドキュメントもあったし。

これにはあまり賛同できないな。Nix/Buildkiteの宣伝みたいに見えるし… CIの呼び出しがスクリプトやビルドツール(makeとか)のターゲットを実行する以上のものであれば、CIシステムを必要以上に複雑にしてることになるよ。CIジョブはせいぜい、開発者がローカルでやるように環境や設定(認証情報、エンドポイントなど)を提供するだけでいいと思う。これによって、コードがCIに依存しなくなるから、システム間の移行もかなり簡単になるし、最小限のロジックで済むから、単なるコマンドの呼び出しになるんだ。

これは広告じゃないって100%確認できるよ(少なくともBuildkiteのためのじゃない)し、チームにとっては素敵なサプライズだった。

ほんとそれ。数年前に別のCIシステムに移行したときのことを思い出す。秘密情報を引っ張ってきて、重い処理をやってくれる.shファイルを呼び出すパイプラインを全部作ってたんだ。移行にはいくつかの痛いポイントがあったけど、割と簡単だったよ。一方で、UIでパイプラインを作って、いくつかのステップに分けたチームは全然満足してなかった。

その通り。GitHub Actionsは今まで使った中で最悪のCIツールだよ(Jenkinsと同じくらいかも)で、Buildkiteが最高。Buildkiteのダイナミックパイプライン(投稿の最後の項目)は本当に役立つから、これなしでどうやってやってたのか不思議になるよ。ユニットテストのステップがテストに失敗したときだけ、テストのデフレークステップを生成するような超クールなことができるんだ。あるいは、テストしているコードの変更に基づいてテストの並列性を制御することもできる。これらすべてが、自分のランナープールを持つための堅牢なシステムの上で実現できるから、各CIジョブのために全く異なるマシンタイプや構成を使える。超おすすめだよ。

Jenkinsはいろいろ問題があって、使わなくてよかったと思ってるけど、Groovyでパイプラインを定義するのは好きだったな。YAMLよりもGroovyの方が全然いい。

Jenkinsの何が悪いの?戦闘テスト済みで、堅牢だし。何千ものタスクでも完璧に動くし、すぐに使える。個人的には、過去25年で書かれたベスト10の無料ソフトウェアの一つだと思う。

エンジニアチームを殺す?誇張したスレッドタイトルはもうやめてほしい。GitHub Actionsは普通に良いと思う。BitbucketやGitLabよりも好きだよ。

記事をクリックしたらGitLabのことだと思った。まぁ、CI/CDシステムが作るフィードバックループの異常な遅さについての批判は、GitLabにも当てはまるね。

うん、MicrosoftがGitHubで人を殺してるのをどう思ってるのか気になってたけど、記事を読んでがっかりした。

すべてのCI環境における勝利の戦略は、自分のマシン、CIのマシン、テスト/ UAT/本番環境で動くビルドシステムの模倣だよ。プロジェクトの要件に応じて、変更を最小限に抑えるのが大事。まずはMakefileから始める。Makefileがすべてを動かすんだ。Docker(compose)、CIビルドステップ、リンティングなどもね。時にはプロジェクトがそれを超えることもあるけど、そうじゃないこともある。でも、作業をトリガーするための単一のツールから始めるのが基本だよ。

同意するけど、これは中規模から大規模プロジェクトでは達成不可能な夢みたいなもんだよ。今の仕事で何年もこの問題に取り組んできたけど、開発者がローカルマシンでパイプラインの全体(またはほとんど)を実行できないようにすることで、どんどん進んでいく道に本当に悩んでたんだ…プロジェクトは別の方向に決まってしまって、今は各MRがパイプラインでちゃんとテストされるために約10回のビルド(試行錯誤)が必要な巨大なCIインフラに多くの時間とリソースを費やしてる。

この考え方がきっかけで、mkincl [0] を作ったんだ。これでMakefileをプロジェクト間でコンポーザブルで再利用可能にしてる。職場で導入してから数年経つけど、直感的で柔軟性があることが証明されたよ。[0]: https://github.com/mkincl/mkincl

問題はCI/CDじゃなくて、「設定でのプログラミング」だと思う。git commit -m "try fix"をして、10分待って、また繰り返すっていう開発ループが普通になっちゃってるんだ。CI環境のローカル再現が、ほとんどのチームにとってまだ欠けているリンクなんだよね。

GHAはソロ開発者にとってかなり力強いよ。俺は小さなマシンで開発して、重い作業は全部GHAにアウトソースしてる。エラーはClaudeに任せて、また繰り返すって感じ。

これがBuildkiteの広告かブログ記事のふりをしたものかはどうでもいいけど、正直言って、すごく真実を語ってると思う。

これは面白い読み物だった。GitHub Actionsが個人プロジェクトにしか良くないっていうのを聞いていた理由がわかるね。