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

私は情熱を持ってGitHub Actionsが嫌いです

2026年1月14日原文(xlii.space)

概要

  • GitHub Actions への強い不満と、その理由の説明
  • tmplrプロジェクト のCI構築中に発生した問題の経緯
  • Linux ARM環境 でのビルド失敗とその原因
  • フィードバックループ の非効率さへの苛立ち
  • Makefileへの移行 による問題解決と今後の教訓

GitHub Actionsへの憎悪

  • GitHub Actions に対する強烈な嫌悪感
  • これまで使った技術でここまで嫌ったものは他に無し
  • PHP も冗談のネタにするが、嫌悪までは感じなかった
  • GitHub Actionsだけは 情熱的に嫌い という感情

tmplrプロジェクトのCI構築

  • tmplr は、手軽にテンプレートを作成できるファイル/プロジェクトスキャフォールドツール
  • build.rs でCUEを使い、README.mdやCHANGELOG.mdなどを自動生成
  • 作業自体は楽しく、1.5時間程度で完了
  • 完成後、CIの結果を確認せずにいたため、後でビルド失敗に気付く

Linux ARMビルド失敗の原因

  • CUEバイナリ をbuild.rs内で利用
  • GitHub Actionsのマトリクスで4プラットフォーム向けにビルド
    • Linux ARM
    • macOS ARM
    • Linux x86_64
    • macOS x86_64
  • Linux ARM のみ「コマンドが見つからない」とエラー発生
  • 他の3環境ではCUEが正常動作
  • GitHub Actions のマトリクス実行環境が強く分離されているため、x86_64バイナリがarm64ランナーから隠蔽される仕様

非効率なフィードバックループ

  • 修正案を探して ci.yml を変更し、コミット・プッシュ
  • ActionsタブでLinux ARMのビルド結果を都度確認
  • 1回の変更につき2~3分かかり、非常に非効率
  • まるで 2分遅延するエディタカセットテープ時代のプログラム実行 のような体験
  • 2026年にもなってこの状況は許容できないと痛感

完全な解決策と教訓

  • ネットの格言:「 GitHub Actionsにロジックを持たせるな。自分で管理し、Actionsから呼び出せ
  • build.rs を削除し、Makefileで生成処理を管理
  • 生成ファイルをリポジトリにコミットし、CI設定も元に戻す
  • これで問題が解決し、精神的な負担も軽減

GitHub Actionsの功罪

  • GitHub Actions はmacOSビルドなど一部メリットも存在
  • 設定が簡単な点も評価
  • しかし、 ランナーのデバッグやビルド最適化 に多くの時間を浪費
  • 他にもっと良いシステムがあれば知りたいが、現状は逃げ場がない現実
  • 早い段階で問題に気付けて良かったという結論

まとめと余談

  • GitHub Actions は便利さと引き換えに多くのストレスをもたらす存在
  • 個人プロジェクトや小規模開発では、 Makefile等でロジックを管理 するのが賢明
  • PHPのミーム は今もお気に入りで、少しだけ救い

Hackerたちの意見

  1. bashは使わない方がいいよ。CIに優しいスクリプト言語を使おう。個人的にはpwshが好き。 2. ワークフローにロジックを入れないで。ワークフローはシンプルであるべき(KISS)で、スクリプトを呼び出すだけにしよう。 3. スタンドアロンのスクリプトを持っていれば、ローカルで開発・修正・テストができるから、地獄のループにハマることがないよ。 4. デバッグしやすいようにCIパイプライン全体を設計して、状態を出力するプリントを入れたり、バージョンをエコーしたりしよう。今は必要なくても、将来の自分が感謝することになるよ。 5. デバッグ機能が優れたサードパーティのランナーを使うことも考えてみて。

1については反対だな。シェル以上のものが必要になると、ちょっと臭いがする。ビルドやテストのプロセスは、もっとシンプルであるべきだと思う。

ステップ0. 意図的に時間を無駄にするCIサービスは使わないで、「SSHで再ビルド」みたいな機能があるCIサービスを使おう。前の議論から見ると(https://news.ycombinator.com/item?id=46592643)、Semaphore CIはまだそれを提供しているみたいだね。

アクションでの永続状態はどう扱ってる?私のアクションでは、依存関係をゼロからインストールするのに一番時間がかかるんだ。それを早くしたいけど、どうやっても分からなかった。依存関係をキャッシュするためのオプションは、どれも複雑そうだった。

pythonとかでCLIを作って、CIと同じことをやるようにすればいいよ。すべてのCIステージはそのサブコマンドを呼び出すだけで済む。

いや、それはダメ。Windowsの環境じゃない限り。

(1)には同意しないけど、(2)には賛成だな。リポジトリにMakefileを置いて、CIターゲットを設定するのをおすすめするよ。それで、make ci-testみたいなシンプルなコマンドでCIから簡単に呼び出せるし。Makefileは複雑にしすぎないようにね。もちろん、他のタスクランナーを使うのも全然アリだよ。

Bashは使うな 何それ?BashはCIフローに最適なスクリプト言語だよ。

以前、ビルドファームを管理するために雇われたことがあるんだ。すべてのビルドジョブは、さまざまなことをさまざまな順序で行うJenkinsプラグインの巨大なパイプラインだった。まじで悪夢だったよ。二度とやりたくない。それ以来、私が触ったすべてのCIセットアップは「make build」やそれに似たもののラッパーになっていて、すべての知恵はビルドしているコードの隣にあるGitに住んでる。これだけは譲れない。

#1のちょっとしたバリエーションだけど、bashやPowerShellで簡単にできる以上の複雑なことにはDenoのTypeScriptを使うようになったよ。pwshができることはすごく多いのは認めるけど、使い勝手が嫌いだし、慣れてない人には結構 awkward だと思う。逆に、TypeScriptやJavaScriptに近い開発者が多いと思うしね。DenoはTSを直接実行できるし、リポジトリやHTTPモジュールも別のインストールステップなしで直接参照できるから、pwsh以上のシェルスクリプトには便利だよ。例えば、DBMSクライアントを引っ張ってきて、テストや設定のために直接やり取りすることができる。だから、上記の理由から、e2eテストには他の言語よりもDenoを使うつもり。

ひどいCIプラットフォームに対処する方法は、すべてのCIプロセスをコンテナ内で行い、CIツールがそれを引っ張って実行することだよ。必要なときにローカルで簡単に実行できるしね。もちろん、プラットフォームはそれをやられるのを好まないけど、そうするとベンダーロックインが無効化されるから。

それが私がいつもGitLab CIパイプラインでやってたことだよ。異なる目的のために専用のイメージをデプロイするだけ。一般的なTerraformコード用のTerraformイメージを用意して、バージョンの標準化が簡単になった。依存関係が多いプロジェクト用に特定のイメージも作ったから、デプロイパイプラインを数秒で実行できるようになった。でも、今はDockerイメージも維持しなきゃいけない。結局、トレードオフだよね。

Hacker Newsで議論の続きを見る