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

現代のCIは複雑すぎて方向性を誤っている (2021)

2025年8月20日原文(gregoryszorc.com)

概要

  • CIプラットフォーム の進化とその利点
  • 複雑化 による課題と本質的な問題提起
  • CIシステムとビルドシステム の境界の曖昧さ
  • 理想的なCIプラットフォームへの 要件考察
  • Taskcluster という先進的な事例の紹介

モダンCIプラットフォームの現状と課題

  • CIプラットフォーム の進化により、開発者や企業がより頻繁かつ信頼性の高いソフトウェアをリリース可能
  • GitHub ActionsGitLab PipelinesBitbucket などの集中型CIプラットフォームによるスケールメリット
    • インターネット上に豊富な情報やノウハウの蓄積
    • 検索すればすぐにコピペ可能なコード例の入手
  • CI設定 に時間を費やすのは誰も望まない現状
    • 目標は「とにかくリリースしたい」

CIシステムの複雑化

  • 進化とともに 設定や機能が複雑化
    • 本質的には「リモートコード実行サービス」として機能
    • ソフトウェアのビルド・テスト・デプロイを目的とした設計
  • GitHub Actions の例
    • 組み込みテンプレートシステムと独自の式言語
    • ジョブのトリガー、変数、条件付き実行、ジョブ間依存関係
    • Dockerベースの実行環境や暗号化シークレット
    • ステップ・アクションの豊富な標準機能
    • 3rdパーティのActionsも多数存在
  • 必要な機能が多く、 不要な機能の削減が難しい
    • YAMLのプログラミング言語的利用に対する妥協

CIとビルドシステムの境界

  • CIシステムの複雑化 =ビルドシステムとの区別が困難
    • MakefileBazel のようなビルドシステムとの類似性
    • CIはリモート・分散型、ビルドシステムはローカル・単一マシンという違いのみ
  • Bazel のようなモダンビルドシステムはリモート実行・キャッシュを標準装備
    • サーバーサイドのGitフックでBazelをトリガーすれば、それも一種のCIシステム
  • CIとビルドシステムの高次抽象化
    • どちらも「汎用計算リソース管理+専門的なビルド・デプロイ機能」
    • Kubernetes やバッチジョブシステムと本質的に近い構造

CIシステムの冗長性と理想像

  • 現状のCIシステムは「ビルドシステムの再発明」や「ロジックの分断」を招く
    • 複雑なYAML、キャッシュや依存関係の最適化でビルドシステムと同じ問題に直面
    • ビルドシステムとCIシステム、2つのDAG(有向非巡回グラフ)管理の煩雑さ
  • 本来CIはビルドシステムの拡張であるべき
    • ローカル開発ワークフローと統合されたCIの利便性
    • ローカルでCIジョブを即時実行可能な開発体験
  • UIやAPIによる集中管理・レポート機能 は必要だが、リモート実行やワーク定義はビルドシステムで十分

CIプラットフォームの抽象度と今後の方向性

  • 現代のCIサービス は適切な抽象レベルを狙えていない
    • GitHub ActionsGitLab CI は「製品」寄りで、柔軟なプラットフォーム性が不足
  • 理想的なCIプラットフォームの要件
    • API経由で任意のタスクグラフをスケジューリング可能
    • YAMLやリポジトリに縛られない「リモート実行サービス」としての柔軟性
  • GitLab Pipelines は親子パイプラインや動的パイプラインで一歩リード
    • ただし完全なAPIベースのスケジューリングは未対応
  • GitHub Actions はYAMLファイルベースに強く依存し、柔軟性に制約

プラットフォームと製品の違い

  • 製品型CI :意見の強いYAML設定+Web UI+APIのセット
  • プラットフォーム型CI :APIで任意の計算リソース・ワークフローを定義可能
  • プラットフォームとしての進化には「YAMLレスなAPIによるタスク定義」が不可欠

Taskcluster:エンジニア向けCIプラットフォームの事例

  • MozillaのTaskcluster は、汎用性の高いCIプラットフォーム
    • Firefox開発のため2014-2015年に設計・実装
    • 他のCIサービスとは一線を画す柔軟性とパワー
  • Taskcluster の特徴
    • API駆動型のタスク定義・スケジューリング
    • 開発者が独自のビルド・CI・バッチシステムを構築可能な自由度
    • 公式の用途にとどまらない多様な応用事例
  • エンジニア本位の設計思想 と、他サービスが見習うべきアイデアの宝庫

このように、現代のCIプラットフォームは進化しつつも、 ビルドシステムとの統合や抽象度の見直し が今後の課題。 Taskcluster のような先進事例を参考に、より柔軟で開発者本位なCIの実現が期待される。

Hackerたちの意見

最近のオンライン/有料のCIシステムは山ほどあって、将来どうなるかなんて誰にもわからないよね…。俺は昔ながらのJenkinsマシンを使ってるけど、これをセットアップするのにかなり時間がかかったけど、それ以来ずっと安定してるし、コストもかからないし、シャットダウンされることもない。GitHub Actionsとかの魅力はわかるけどね…。

GHアクションのデバッグをしなきゃいけなくなるまで、特にそれがメインでしか動かないか、メインにコミットしたときだけ実行されるタスクの一つだったら、神様助けてくれ。ローカルのエミュレーターやモックなんて使うだけ無駄だよ。

Jenkinsに+1。俺の職場では最近Gitランナーをセットアップしたんだ。今やってるプロジェクトは、OSが指定されてて、長い話だから聞かないで。OSはCentOS 7なんだけど、ランナーはこれをサポートしてない。Ubuntu 22.04に移行する努力もあるけど、ランナーもこれをサポートしてない。だから、Jenkinsのインスタンスをセットアップしてるところ。

でも、設定ファイルがDSLに堕ちるなら、もう本当のプログラミング言語を使っちゃいなよ。これ、マジで同意。デバッガー付きの本物のプログラミング言語を使おう。YAMLは最悪だし、Starlarkもあんまり良くないよね。

YAML化されたDSLにコードを埋め込み始めると、ボーナスポイントだね。

本物のプログラミング言語を使って、デバッガーも使おう。YAMLは最悪だし、Starlarkもあんまり良くない。君の意見には賛成だったけど、「Starlark」って言った瞬間から違和感を感じた。俺の経験では、StarlarkはYAMLの百万倍はマシだよ。なんでそう思わないの?

リッチ・ヒッキーのトークを思い出すな。彼はDatomicというデータベースについて話していて、「データベースの問題は、あっちにあることだ」と言ってた。データを不変の「事実」でモデル化することで、データベースのロジックの多くをアプリケーションに近づけられるんだ。彼の場合は、Clojureのデータ構造を使ってね。CIの問題も、あっちにあるのかもしれない。自分のノートパソコンで簡単にセットアップして何度も実行できるものじゃなくなると、もう手遅れだよ。ビルドシステムとの比較は的を射てるね。俺は、リモートキャッシュなしで自分のノートパソコンで作業しているデータベースをビルドできるし、たまにやってるよ。時間はかかるけど、そんなに長くはないし、「このシステムを維持している人たちはこれを試してない」ってエラーも出ない。CIシステムは、もう忘れた方がいい。問題の一部、いや、全体が、すべてを動かしてポータブルで最適化された環境を作れる可能性があっても、結局はあっちでしか動かないってことなんだよね。だから、どんどん悪化していく。これを解決するのは簡単じゃないだろうな。今日の統一された解決策が、明日のレガシーの沼になるかもしれない。でも、それがソフトウェアってもんだよ。

ビルドシステムは完全に宣言的であってほしいんだけど、DSLが必要なことをサポートしてないんだよね。テンプレートとかカスタムスクリプトを入れる場所がちょっとあればいいんだけど。おめでとう!これでチューリング完全なシステムが手に入ったよ。そう、記事によれば、これで仮想通貨のマイニングもできるってことだね。Ansible、Terraform、Maven、Gradle。残念なことに、これらのIT領域(ビルドやCI)は、2つの有名な滑りやすい坂の交差点にいるんだ。1) 設定 2) ワークフロー。この2つの滑りやすい坂は、どれだけクリーンでシンプルか、何でも簡単にできるかのデモで有名なんだよね。デモでは必要なことは何でもできるって。でも、しばらくはそのままでいるかもしれないけど、結局は…スクリプトスープになるよ。

問題の一部、いや、全体の問題かもしれないのは、すべてを動かせてポータブルで最適化できる環境を作れたとしても、結局はあっちでしか動かないってことなんだよね。だからカエルはずっと煮え続ける。コンテナ(またはVM)内でソフトウェアをビルドするのがいいよ。ビルドごとに新しい環境を用意して、キャッシュや以前のビルド成果物を明示的にマウントする感じ。そしたら、これみたいなものがあれば、ローカルでもビルドできるよ:https://docs.drone.io/quickstart/cli/ それで、必要なだけタートルをスタックできる。コンテナビルドの一部として実行されるビルドスクリプトを持ったり、Mavenや必要なものを中に入れたりね。意外とまともに機能するよ。CIサーバーが「docker build -t my_image ...」と同じことをして、その後何かをする感じ。ビルド中はbuild.shスクリプトが中にあるだけなんだけど。

トランザクションと一貫した真実のソース、可視性や時間的順序のことは、ほとんどの場所で中央集権的で「向こう側」にあるんだ。通信の速度に限界がある限り(光の速度とか)、イベントホライズンは存在する。データベースの目的は、変化と時間を中央で追跡することなんだ。やりたいからじゃなくて、他の方法が全部失敗したからなんだよね。競合するCRDTの変更マージやGitのマージも、すぐにややこしくなることがある。人々は10年ごとにデータベースを再発明する。ハードウェアは速くなる。楽しんで見てればいいよ。

だから、CIをローカルやGitHub Actionsで実行できるスクリプトにしちゃったんだ。そしたら、CIは単にそのスクリプトを実行するためのちょっとしたyamlになるだけ。

ビルドはこれでいい:build.bashだけ。それでコンテナビルドもトリガーできるし。CIビルドがローカルビルドと違う動きをするのをデバッグするのに、無駄に時間を使いすぎた。いつもCIサーバーに余計なものが加わってるせいなんだよね。業界でこの「パターン」に従わないビルドを見つけたことがない。環境設定はローカルマシンでもCI/CDサーバーでも同じように動くべきだし、DevOpsチームがAnsibleとか使って同じようにベアメタルにセットアップしてるはず。

Hacker Newsで議論の続きを見る