自己維持可能なCI ── Goテストの失敗をClaudeで自動修復する仕組み
LayerXの技術ブログは、Goテストの失敗を検知するとClaudeが自動でログを分析し、担当チームに通知して修正PRまで作成する自己維持可能なCIシステムの設計と実装を紹介している。
キーポイント
CIテスト失敗時の課題解決
従来のCIテスト失敗時には開発者がログ分析・原因特定・修正依頼など多くの手作業が必要だったが、特に再現困難なrace conditionやflaky testでは対応が後回しになりがちだった課題を解決する。
Claudeによる自動分析・修正システム
Go testの失敗を検知するとClaudeが自動的にログを分析し、原因を特定して担当チームに通知し、修正PRまで作成する完全自動化されたワークフローを構築した。
設計と実装の詳細
記事では具体的なシステム設計と実装方法が紹介されており、-raceフラグの分離など技術的な詳細が含まれている。
開発者体験の向上
このシステムにより、開発者はテスト失敗時の手作業から解放され、より重要な開発作業に集中できるようになる。
影響分析・編集コメントを表示
影響分析
この記事は、LLMを活用したCI/CD自動化の具体的な実装例を示しており、開発現場の生産性向上に直接貢献する実用的なアプローチを提供している。企業内でのAI活用が単なる実験段階から実際の業務改善に移行していることを示す好事例と言える。
編集コメント
企業内での実用的なAI活用事例として非常に参考になる内容。技術ブログとしては詳細な実装情報が提供されており、同様の課題に直面している開発チームにとって具体的な導入のヒントとなる。
はじめに LayerX バクラク事業部 Platform Engineering 部 Enabling グループの shibutani です。 CIのテストが失敗したとき、開発者が対応すべきことは意外と多くあります。ログを読み、原因を特定し、担当者を探して修正を依頼する、あるいは自ら修正する。これがレースコンディションや不安定なテスト(flaky test)のように再現が困難な場合、対応はさらに後回しにされがちです。 今回、Go testの失敗を検知するとClaudeが自動的にログを分析し、担当チームに通知し、修正用のPR(プルリクエスト)まで作成する仕組みを構築しました。本記事ではその設計と実装を紹介します。 -race フラグの分離と、そ…
原文を表示
はじめに
LayerX バクラク事業部 Platform Engineering 部 Enabling グループの shibutani です。
CIのテストが落ちたとき、開発者がやることは意外と多いです。ログを読み、原因を特定し、担当者を探し修正依頼 or 自分で修正する。これがrace conditionやflaky testのように再現しにくいものだと、対応はさらに後回しにされがちです。
今回、Go testの失敗を検知したらClaudeが自動でログを分析し、担当チームに通知し、修正PRまで作成する仕組みを構築しました。本記事ではその設計と実装を紹介します。
-race フラグの分離と、その先の課題
出発点はPull Request作成時のCIの速度改善でした。これまではPull Request作成時のCIで -race フラグ付きの go test を実行していましたが、-race フラグはGoのrace detectorを有効にするオプションで、公式ドキュメントによるとメモリ使用量5〜10倍、実行時間2〜20倍のオーバーヘッドが発生します。Pull Requestのたびにこのコストがかかり、開発者のフィードバックループを遅くしていました。
Agentic codingの普及によりPull Requestの量が増えつつある今、CIのthroughputを上げることの重要性は高まっています(参考: ハーネスエンジニアリング:エージェントファーストの世界における Codex の活用)。そこで -race フラグをmainブランチへのpush後のCIに移し、Pull Request作成時のCIは -race なしで高速に実行する構成に変更しました。
しかし、単純に分離するだけでは新たな問題が生まれます。Pull Request作成時のCIで即座にフィードバックされていたrace conditionやflaky testが、mainブランチにマージされて初めて検出されるようになります。なお、バクラクではmainブランチへのマージが即本番デプロイされるわけではなく、QAなどの工程を経てリリースされるため、mainで検出しても本番への影響を防ぐ余地はあります。とはいえ、race conditionは「稀にしか起きない」「再現しにくい」、flaky testは「もう一回走らせたら通る」という性質から、mainブランチで失敗しても対応が後回しにされがちです。放置すればrace conditionは本番で影響の大きいバグとして発現し、flaky testはCIの信頼性を徐々に損ないます。
分離によるCI高速化のメリットを享受しつつ、検知した失敗が放置されない仕組みが必要でした。そこで、失敗の分析・担当チームへの通知・修正PRの作成までを自動化するパイプラインを構築しました。
全体のフロー
mainブランチへのpushをトリガーに、以下のフローで動作します。
NoYesYesNoYesNomainへのpushgo test -racetestwrapper経由失敗あり?通知なしClaudeによる失敗ログ分析既知のflakyのみ?通知なしCODEOWNERSからオーナーチームを特定Slackにグループメンション付きで通知DATA RACEあり?修正 Draft PR を作成Flaky Mark PR+ 修正 Draft PR を作成
ポイントは、すべての失敗を検知しつつ、既知のflaky testによるノイズは通知しないことです。通知の信頼性を保つことで、「またflakyか」と無視される状態を防ぎ、本当に対処が必要な失敗に開発者の注意を集中させます。
testwrapperによるテスト実行
通知の信頼性を保つためには、既知のflaky testと新規の失敗を区別する仕組みが必要です。
go test を直接実行する代わりに、社内で整備している testwrapper というCLIラッパーを経由して実行しています。この仕組みは Tailscaleのtestwrapper/flakytest を参考にしたもので、弊社の @upamuneが Go Conference 2025での発表 で詳しく解説しています。テスト関数内で flakytest.Mark() を呼ぶことで「このテストはflakyである」と宣言し、testwrapperがその情報を検知して自動的に最大3回までリトライします。
func TestSomething(t *testing.T) {
flakytest.Mark(t, "https://github.com/org/repo/issues/123")
}
flakytest.Mark() の第2引数にはTracking IssueのURLを渡します。なぜflaky化されているのか、いつ解消する予定かをIssueで管理する運用です。
既知のflaky testのみで失敗した場合は、testwrapperが自動リトライを試みます。リトライで通ればそのまま成功として扱い、リトライしても失敗が残った場合でもSlack通知やPR作成は行いません。既知のflaky testとして管理されている以上、対応済みと判断するためです。それ以外の失敗が含まれる場合に、次のClaudeによる分析フローに進みます。
テスト失敗を検知したら、Claudeがログ分析から修正PRの作成までを一気通貫で行います。この自動化はGitHub Actionsのカスタムアクションとして実装しており、Anthropic SDKを通じてClaude APIを呼び出しています。
ログの絞り込み
CIのログをそのままClaudeに渡すのではなく、関連度の高い部分に絞り込んでからプロンプトに含めています。DATA RACEブロックが検出された場合はそのブロックを優先的に抽出し、そうでない場合は --- FAIL: の前後20行を抽出します。
ログ全体を渡すとコンテキストウィンドウを消費するだけでなく、関係のない情報にClaudeが引きずられるリスクもあります。ノイズの除去が分析精度の向上に直結するため、この前処理は重要です。
オーナーチームへの通知
失敗したテストのパッケージパスからCODEOWNERSを逆引きしてオーナーチームを特定し、GitHubチームとSlackグループのマッピングを通じてグループメンションを送ります。「テストが失敗した → 担当チームに通知が届く」という流れを自動化することで、誰にも気づかれないまま放置されるリスクを減らしています。
SlackへのCI失敗通知の例
失敗種別に応じたPR自動作成
Claudeは失敗の種別に応じて、異なるPRを自動作成します。
DATA RACEが検出された場合、Claudeがソースコードを分析し、race conditionを修正するDraft PRを作成します。
DATA RACEなしだが未マークのテスト失敗の場合は、2種類のPRを作成します。
FlakyをMarkするPR: 該当テストに flakytest.Mark() を追加し、tracking Issueも同時に作成します。このPRをマージすると、次回以降はtestwrapperが自動リトライするようになり、Slackへの通知も止まります。
Flakyを修正するDraft PR: テストの非決定性を除去する修正案をClaudeが生成します。
いずれもDraft PRはエンジニアがレビューするまでマージされません。Claudeが自動でコードを書きますが、最終的な判断は人間が行う設計です。
FlakyをMarkするPRをマージするだけで、そのテストに起因する通知が次回から止まります。これにより、対処すればするほどノイズが減り、通知の信頼性が上がっていく好循環が生まれます。
おわりに
今回構築した仕組みのポイントをまとめます。
-race フラグをmainブランチのCIに分離し、Pull Request作成時のCIの高速化とrace condition検知を両立した
testwrapperと flakytest.Mark() で既知のflaky testを自動リトライし、通知のノイズを除去した
Claudeによるログ分析・PR自動作成で、検知から修正提案までを自動化した
CODEOWNERSの逆引きでオーナーチームにグループメンションし、通知の見落としを防いだ
race conditionもflaky testも、放置されがちな問題です。原因の特定が難しく、影響がすぐには見えにくいため、目の前のタスクに押されて後回しになりがちです。この仕組みでは、検知・通知・修正提案を自動化することで対処のハードルを下げ、開発者が本来の開発に集中できる環境を目指しました。
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み