TECH PLAY

Claude Code

イベント

マガジン

技術ブログ

.table-of-contents > li > ul > li > ul { display: none; } はじめに こんにちは、検索基盤部の倉澤です。ZOZOTOWNの検索機能のバックエンドの開発を担当しています。検索基盤部の一部システムではGoを採用しています。 2026年2月21日(土)にGo Conference mini in Sendai 2026が開催されました。本記事では、会場の様子や個人的に印象に残ったセッション・LTについて紹介します。また、私もLT枠で登壇したため当日話しきれなかった内容もあわせて紹介します。 目次 はじめに 目次 Go Conference mini in Sendai 2026とは 会場の様子 セッション AI時代のGo開発2026 爆速開発のためのガードレール 個人的に気になった点 Go パッケージのサプライチェーン攻撃を防ぐ CI を作ってみた 個人的に気になった点 Go 1.26 で生まれ変わった go fix をプロダクト開発の運用に乗せる 個人的に気になった点 encoding/json/v2のUnmarshalはこう変わった ~内部実装で見る設計改善~ このテーマを選んだきっかけ さいごに Go Conference mini in Sendai 2026とは Go Conferenceは、プログラミング言語Goに関するカンファレンスです。今回は「東北から広がるGoコミュニティ」というテーマで仙台にて4年ぶりに開催されました。18セッション(20分)と12のLT(5分)によって構成され、Goに関するさまざまなテーマについて発表されました。参加者は117人と大盛況のうちに終わりました。 sendaigo.jp 会場の様子 会場は仙台市青葉区にあるアーバンネットビル仙台中央 カンファレンスルームでした。ワンフロアにスポンサーブースと2部屋のセッションルームがあり、同時に発表が行われました。 オープニングの様子 スポンサーブースでは、参加者向けのさまざまなコンテンツが用意されていました。 株式会社UPSIDERさんのブース 株式会社UPSIDERさんのブースでは、「Goの挑戦Goっそり教えて!」をテーマに意見が募られていました。「TinyGoを使って何かを作ってみたい」等の声があり、TinyGoへの関心の高さがうかがえました。 株式会社SODAさんのブース 株式会社SODAさんのブースでは、「あなたのやらかしエピソードや懺悔したいことを教えてください」をテーマに意見が募られていました。生成AIが書いたコードによってやらかしたエピソードが昨今の開発事情を表していて面白いなと思いました。また、SODAさんのブースではGopherの16タイプに分ける診断を実施しておりました。 snkrdunk.github.io 私は、「数学的な賢者」でした! Gopherの16タイプ診断 会場では参加者全員にステッカーなどのノベルティが配布されており、どれもとても可愛らしいデザインでした。 ノベルティのステッカー また、ネームタグの裏側には「すぐに使える仙台弁」が記載されており、参加者同士の会話のきっかけになっていました。仙台開催ならではの遊び心が感じられる演出でした。 ネームタグ さらに登壇者にはTシャツが配布され、登壇の良い記念になりました。運営の皆さまのお心遣いに感謝です。 登壇者用のTシャツ セッション AI時代のGo開発2026 爆速開発のためのガードレール www.docswell.com こちらのセッションでは、生成AIにおける開発の「速さ」と「治安(コード秩序やルール)」をいかに両立させるのかについて紹介されています。 課題 生成AIの発達・普及により実装速度が飛躍的に向上した一方で、アーキテクチャのルール違反などコードの治安が悪化しやすくなっている。 対策 Rules/Skillsのような非決定的な制約(ソフト制約)だけに頼るのではなく、決定的な制約(ハード制約)をガードレールとして整備することが重要。 紹介されているハード制約の例 Goの internal パッケージによるアクセス制御 depguard 等のLintによる依存ルールの強制 Fuzzing testやMutation testによるテスト品質の担保 個人的に気になった点 アーキテクチャの依存ルールを生成AIに守らせるという観点で、Goの internal パッケージを用いるというのは面白い発想だと思いました。一方で、ドメイン単位でパッケージを分割する Package by Feature だからこそ威力を発揮する一面もあるのかなと思いました。私が携わっているプロジェクトでは、アーキテクチャの技術的な役割(レイヤー)毎にパッケージを分割する Package by Layer を採用しています。 internal パッケージの配下に各レイヤーのパッケージを切る構成が一般的です。この場合、 internal が守れるのは外部モジュールからのアクセスであり、 internal 内部のレイヤー間の依存方向までは防げません。 発表後に登壇者の方へ質問したところ、 Package by Layer でも internal パッケージが活きるケースを共有していただきました。各層でしか使わない関数を他の層から使われないように守るという観点です。例えば、 presentation 層でレスポンスに対して処理する関数を internal に配置すれば、他の層からの誤った利用を防げるとのことでした。レイヤー間の依存方向の制御とは別に、各層の内部実装の隠蔽という観点で internal が有効に機能するというのは納得感がありました。 Go パッケージのサプライチェーン攻撃を防ぐ CI を作ってみた speakerdeck.com こちらのセッションでは、Goパッケージのサプライチェーン攻撃をCIで防ぐ取り組みについて紹介されています。 課題 typosquatting (タイプミスを狙った攻撃)や slopsquatting (AIのハルシネーションを狙った攻撃)により、悪意のあるパッケージの混入リスクがある 対策 Googleが公開している capslock を活用し、パッケージがアクセスし得る特権的操作(ファイルシステム操作、ネットワーク通信など)を静的解析で検知 PRで新しいパッケージが追加された際に、 main ブランチとのCapabilityの差分をCIで検出 その結果をClaude Code Actionに読み込ませることで、セキュリティリスクを診断する仕組みを構築 個人的に気になった点 こちらのセッションは、昨年開催されたGo Conference 2025の「 サプライチェーン攻撃に学ぶmoduleの仕組みとセキュリティ対策 」に続く内容だと感じました。昨年の発表では、Goのパッケージ管理システムを利用したサプライチェーン攻撃が3年以上見つからず、その根本的な対策も難しいという話がありました。本発表はLT枠で5分と短かったですが、昨年のGo Conferenceで発表された課題に対して対策を検討し、同じくGo Conferenceで発表するという流れにとても感心しました。 発表内容で気になったのは、新しく追加されたパッケージのCapabilityから悪意の有無をClaude Codeがどう判断しているかという点です。登壇者の方に質問したところ、依存先パッケージのメソッド名や周辺の実装をもとに判断していると考えられるとのことでした。また、サードパーティの公式パッケージを追加した際にも、依存先パッケージでCapabilityの警告が出るケースもあったそうです。ただし公式パッケージである以上、対処は難しく、まだ改善の余地があるとのことでした。 Go 1.26 で生まれ変わった go fix をプロダクト開発の運用に乗せる speakerdeck.com こちらのセッションでは、Go 1.26で大幅に刷新された go fix コマンドをプロダクト開発の現場にどう組み込むかについて紹介されています。 運用フローの設計 「検知」と「適用」を分けて考えるのがポイント 検知(毎PR): golangci-lint の modernize を有効化し、CIで古い書き方を常時警告する 適用(Goバージョン更新時): go fix ./... を2回実行して既存コードを一括変換する go fixに関する3つのアプローチと使い分け modernize :組み込みルールによるコードのモダン化。go fixを実行するだけ SuggestedFix :自作Analyzerに修正提案を追加し、プロジェクト固有のパターンを自動修正する go:fix inline :非推奨関数に //go:fix inline を付与し、利用者側でgo fixを実行するだけでAPI移行を自動化する 個人的に気になった点 先日公開された公式ブログ「 Using go fix to modernize Go code 」を読んでおり、最近私も go fix を実行した経験がありました。そのため、運用観点の話はとても興味深い内容でした。特に気になっていたのは、 go fix の「2回実行が必要」という点の仕組み化です。ある modernize ルールの適用が別のルールの適用機会を生むため、公式ブログでも2回の実行が推奨されていますが、これを仕組み化するのは難しいと感じていました。登壇者の方に質問したところ、以下のような回答をいただきました。 まだ完全な仕組み化はできていないが、 pre-commit フックでコミット前に go fix を実行する方法を検討している ただしpre-commitの導入はチームにより意見が分かれるため、Claude CodeのSkillsで実行させるのも有効ではないか 生成AIのSkillsは、こうした「毎回やるべきだが柔軟さも求められるルール」の適用に向いているという点に納得感がありました。また、 golangci-lint の modernize リンターについても質問しました。内部的にはgo fixと同じ modernize アナライザが動いているため、こちらも同様に複数回の実行が必要とのことでした。 encoding/json/v2のUnmarshalはこう変わった ~内部実装で見る設計改善~ speakerdeck.com 私も今回LT枠で登壇いたしました。このセッションでは、Go 1.25で実験的に追加された encoding/json/v2 パッケージの Unmarshal 関数を取り上げました。従来の encoding/json パッケージが抱えているパフォーマンス上の課題と、v2での改善点を内部実装の観点から紹介しました。 v1での課題点 パッケージの構成 :1つのパッケージに「JSONを解析する処理」と「Goの構造体に変換する処理」がすべて混在しており、変更時の影響範囲も広かった エラーメッセージ :JSONのパース(解析)に失敗したとき、どの項目でなぜ失敗したのかがエラーメッセージから読み取りにくかった メモリの使い方 :Unmarshalを呼ぶたびに内部で使うオブジェクト(Decoder)を毎回新しく作成しており、高頻度で呼び出すとメモリ確保やGC(ガベージコレクション)の負担が大きかった データの読み取り方 :JSONデータを読み取るたびに内部でコピーが発生しており、メモリ効率が悪かった v2での改善点 パッケージの分離 :「JSONの解析」を担う jsontext パッケージと「Goの型へのマッピング」を担う json パッケージに分離し、それぞれの役割を明確にした 構造化されたエラー :エラー情報にJSONのどの位置で、どんなJSON型が原因で失敗したかを含めるようにし、原因の特定が容易になった オブジェクトの再利用 :sync.Poolパッケージを使い、一度作った Decoder を使い回すことで、メモリ確保の回数とGCの負担を大幅に削減した 効率的なバッファ管理 :1つのバッファ(データを一時的に保管する領域)を論理的に分割して管理することで、データのコピーなしに必要な部分へアクセスできるようになった このテーマを選んだきっかけ 普段の業務ではREST APIを実装する機会が多く、 encoding/json パッケージを利用する場面も多くありました。しかし、 encoding/json には以前から課題が多く、 golang/go#71497 でも長期にわたって議論が続いています。そんな中、Go 1.25で実験的にv2が追加されました。 go-json-experiment/jsonbench のベンチマーク結果を見ると、v2の Unmarshal 関数は以下の点で大きく改善されていることがわかります。 大幅な速度改善 :具象型で2.7〜10.2倍、RawValue型では最大21.1倍と、v1から劇的に高速化されている 安全性を犠牲にしていない : unsafe パッケージを使用せず、UTF-8の検証や重複キーの拒否などRFC準拠の正確性も向上している ストリーミング対応 :v1では非対応だった Unmarshal のストリーミングにも設計当初から対応している 速度・正確性・安全性のいずれも改善されているという結果から、「なぜこれほど改善できたのか?」を内部設計から理解したいと思い、 アドベントカレンダーの記事 で調査しました。その調査がきっかけとなり、今回プロポーザルを提出しました。 さいごに 今回LT枠ではありますが、初めてGo Conferenceにプロポーザルを提出し、採択していただきました。発表後には「あと20分くらい聞きたかった」や「よく5分でまとめましたね」などとても温かいお声をいただきました。登壇を機に、さまざまな方と繋がれたことは非常に貴重な経験でした。アウトプットがきっかけで生まれる繋がりの大切さを改めて実感しました。また、登壇を機に初めて仙台へ行きました。牛タンやずんだ餅など仙台グルメも堪能でき、カンファレンスと合わせて充実した思い出となりました。 最後に、このような素晴らしい場を作ってくださった運営の皆さまに心から感謝いたします。準備から当日の進行まで、細やかな配慮が行き届いており、登壇者・参加者いずれの立場でも安心して楽しむことができました。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
.entry .entry-content .table-of-contents > li > ul { display: none; } はじめに こんにちは、グローバルシステム部フロントエンドブロックの林です。 私が所属するチームでは ZOZOMETRY というBtoBサービスを開発しています。スマートフォンで身体を計測し、計測結果を3Dモデルやデータとして可視化・Web上で管理できるサービスです。 私たちのチームではAIにユニットテストを書かせ、マージまでの過程を改善する施策を実施しました。結果としては、2か月でテスト数が57%増え、カバレッジは約2倍になりました。 この取り組みはテストを増やすという面ではうまくいきましたが、AIが書いたコードを人間がどうレビューするかという点で、いくつかの壁にぶつかりました。 この記事では、以下の点を紹介します。 AIが書いたテストコードを素早くレビューするために、どのような仕組みを設計したのか 運用する中でどのような課題が見えてきて、どう対処したのか AIと協業する開発フローにおいて、人間が関与すべきポイントはどこだったのか 目次 はじめに 目次 背景と課題 テスト生成の仕組み Claude Codeコマンドの設計 統一フォーマット describeのネスト構造 テスト名と日本語コメント テスト対象ごとの実装パターン テストサマリの付与 成果 運用で見えた課題 AIの生成速度と人間のレビュー速度のミスマッチ 「ノールックでマージするのは怖い」 「インプットとアウトプットだけ見ればいい」仮説の崩壊 課題への対策 サマリの自動生成でレビューの入口のハードルを下げる 粒度の制御でレビュー1回あたりの負荷を下げる 目視確認のプロセス化 振り返り:AI協業における人間の関与ポイント AI生成コードのレビューで人間が見るべき範囲 生成速度とレビュー速度のバランス設計 導入コストを下げるアプローチ まとめ 背景と課題 私たちのチームでは、機能開発を優先するあまりテストが慢性的に不足しており、以下のような課題が続いていました。 品質管理はQAチームに大きく依存している状態 テスト作成の品質や粒度にばらつきがある テストの目的や内容を理解するためのドキュメントが十分に整備されておらず、「このテストは何を守っているのか」を説明しにくい 施策の開始時点でのテスト数は324件、カバレッジは4.72%でした。 この状況を改善するにあたって、いくつかの選択肢がありました。人手でテストを書くのが最も確実ですが、機能開発と並行して進めるリソースがありませんでした。AIにテストを生成させれば速度は出ますが、品質の保証は未知数です。 結果として、AIにテストコードを生成させ、人間がレビューする体制を選びました。とはいえ、最初からAIに品質を丸投げできるとは考えていませんでした。この実験にはもう1つの目的がありました。AIと協業するうえで、人間が関与すべきポイントはどこなのか。それを見出すための取り組みでもあったのです。 テスト生成の仕組み テスト生成の仕組みを以下の3点で構成しました。 Claude Codeコマンドによるテスト生成の定型化 統一フォーマットによるテスト構造の標準化 テストサマリの自動付与 Claude Codeコマンドの設計 Claude Codeのカスタムコマンド /create-unit-test を作成しました。このコマンドは対象ファイルのパスを受け取り、以下のワークフローを順に実行します。 対象ファイルの分析 :ファイルタイプ(フック / ユーティリティ / ストア / コンポーネント)を特定し、エクスポートされる関数の一覧や依存関係を把握する テスト設計書の作成 : docs/test-design/ にテスト設計書を生成し、テストケースを正常系・異常系・エッジケースに分類する テストファイルの作成 :設計書に基づいてテストコードを test/unit/ に配置する テスト実行と検証 : pnpm test でテストを実行し、カバレッジを確認する テストサマリの記録 : docs/test-summaries/test-summary.md にテスト内容を追記する # 実行例 /create-unit-test hooks/useClientData.ts /create-unit-test utils/detectGender.ts 各ステップでユーザーの承認を挟む設計にしています。AIに一気に生成させるのではなく、分析→設計→実装→検証の各段階で人間が判断する余地を残しました。 コマンドの設計で重視したのは再現性です。誰が実行しても同じ粒度・同じ構造のテストが生成されることで、レビューする側の認知負荷を一定に保つことを狙いました。 統一フォーマット 生成されるテストの構造を揃えるために、以下のルールを定めました。 describeのネスト構造 テスト対象の関数ごとに describe をグループ化し、その中を Success case / Error case / Edge cases に分類します。 describe ( 'useCreateClient' , () => { describe ( 'Success case' , () => { ... } ); describe ( 'Error case: Argument problems' , () => { ... } ); describe ( 'Error case: Response errors' , () => { ... } ); describe ( 'Edge cases' , () => { ... } ); } ); この構造が揃っていることで、レビュアは「このテストはどの分類のケースを見ているのか」をコードの構造から即座に判断できます。 テスト名と日本語コメント テスト名は should [期待される動作] の形式で統一しました。加えて、各 describe や it の前に日本語コメントを付けることで、テストの意図をコードを読み込まずとも把握できるようにしています。 // 性別判定機能のテスト describe ( 'detectGender' , () => { // 男性の場合、正しいメッセージを返すことを確認 it ( 'should return the correct message for MALE' , () => { expect (detectGender( 'MALE' )).toEqual( 'Male' ); } ); } ); テスト対象ごとの実装パターン 対象のファイルタイプに応じて、テストの書き方を使い分けています。テストケースが少ないフックには renderHook を使い、セットアップを簡潔に保ちます。テストケースが多いフックには直接呼び出しと describe のネストを組み合わせ、テストケースごとの独立性を確保します。ユーティリティ関数は入力と出力の対応を直接検証し、Zustandストアは act で状態更新をラップすることでReactの非同期性に対応しています。 この使い分けもコマンド側で自動的に判断するため、生成されたテストのパターンがばらつくことを防いでいます。 テストサマリの付与 テスト実行後、 docs/test-summaries/test-summary.md にサマリを追記する仕組みを導入しました。サマリには以下の情報を含めています。 テスト対象ファイルとタイプ テスト内容:関数シグネチャと、どの分類(正常系・異常系・エッジケース)をテストしたか テスト結果:成功数 / 全体数 以下は実際のサマリの例です。 ## ` utils/fileName.ts ` - 2025-12-04 14:28:00 **タイプ**: ユーティリティ **テストファイル**: ` test/unit/fileName.test.ts ` ### テスト内容 - ` getDisplayFileName(name, maxLength?, headLength?): string ` - 正常系(短い/長いファイル名、デフォルトパラメータ、境界値)、エッジケース(空文字列、日本語) - ` isValidFileName(name, maxLength?, includeExtension?): boolean ` - 正常系(英数字・日本語・記号)、異常系(不正な拡張子、長さ超過)、エッジケース(複数ドット、最小長) **結果**: ✅ 全テスト成功 (32/32) このサマリはPRのレビュー時にも参照します。レビュアはまずサマリを読んでテストの全体像を把握した後で、実際のコードに問題点がないかを確認するフローにしました。 成果 2か月の実施期間で、ユニットテスト数は324件から509件へ57%増加しました。カバレッジは4.72%から9.25%へ、約2倍に改善しています。 定量的な成果に加えて、以下の定性的な改善もありました。 テスト設計書とサマリが蓄積されたことで、テストの目的やカバー範囲をチーム全体で把握できるようになった テストの構造が統一されたことで、レビュー時に「何を見ればいいか」が明確になった 既存テストの品質を見直すきっかけにもなった 運用で見えた課題 成果は出ましたが、運用する中でレビュー面の課題が顕著になりました。課題の本質は「AIの出力品質」ではなく、正しいと判断するための「検証コスト」にありました。 AIの生成速度と人間のレビュー速度のミスマッチ AIによりPull Request(以下PR)の生成時間が大幅に短縮されたため、未レビューのPRが溜まるようになりました。PRを作った側にはレビュー依頼やリマインドへの心理的障壁が生まれました。レビューする側も次々と届くPRにプレッシャーを感じる状態でした。この状態でチームの生産性を最大化するのは難しいものでした。 「ノールックでマージするのは怖い」 AIが書いた、品質に直結する部分のコードをノールックでマージするのは怖いと感じました。チームで話し合った結果、人間が差分を目視で確認することにしました。 しかし目視確認にも課題が隠れていました。PRの粒度が大きくなりがちで、人間の認知負荷が増加したのです。 「インプットとアウトプットだけ見ればいい」仮説の崩壊 CI/CDで実行を管理しているので、変更されたコードを見なくてもインプット(プロンプト)とアウトプット(テスト実行結果)だけ確認すればいいのではないか。そういった仮説を立てました。 しかし現実には、インプットが本当に期待しているインプットなのかを判断するためのコンテキストが属人化していました。設計や詳細なコードを把握していないメンバーは自力で調査する時間が増え、かえって非効率になりました。この状態を改善しなければ、サービスの品質向上や本質的な改善は難しい状況でした。 課題への対策 これらの課題に対して、3つの施策で対処しました。 サマリの自動生成 AIにプランニングさせ粒度を制御する仕組み 人間が差分を目視で確認するプロセスを明示的に残す サマリの自動生成でレビューの入口のハードルを下げる テストされている箇所の設計や実装を把握していないメンバーでもレビューに入りやすくすることを目的としています。前述のサマリを活用したレビューフローを通じて、不慣れな領域でもテストの全体像をあらかじめ把握した状態でコードレビューへ臨めるようにしました。 これにより、不慣れな領域のレビューに対する心理的障壁を軽減し、迅速にレビューへ入れるようになりました。 粒度の制御でレビュー1回あたりの負荷を下げる コマンド実行時、どの範囲のテストを作成するかAIへプランニングさせる仕組みにしました。PRサイズは100行程度を目安に設定しています。 テストカバレッジを一度に大きく上げたくなりますが、レビューする側の認知負荷を超えないことでレビューに臨むハードルを下げることができました。 目視確認のプロセス化 「ノールックでマージしない」というチームの方針に基づき、人間が差分を目視で確認するプロセスを明示的に残しました。AIの出力を無条件に信頼するのではなく、品質の最終判断は人間が担う体制です。 これらの改善施策により、レビューまでのリードタイムが減りメンバーの心理的な負担も少なくなりました。 振り返り:AI協業における人間の関与ポイント この実験を通じて、AIと協業する開発フローにおけるいくつかの知見が得られました。 AI生成コードのレビューで人間が見るべき範囲 「インプットとアウトプットだけ見ればいい」という仮説は成立しませんでした。コンテキストの共有が前提条件として必要であり、それが属人化している状態では、コードの差分を目視で確認する以外に品質を担保する手段が見つかりませんでした。 チームが出した結論は「差分のコードを目視で確認するのは、やはり人間が担当すべき」というものです。レビューのコストが上がる課題は引き続き残りますが、品質の担保を優先しました。 生成速度とレビュー速度のバランス設計 AIの生成速度に人間が追いつけない構造的な問題に対しては、生成側で粒度を制御することが有効でした。レビュー側の運用を変えるのではなく、生成側の出力を調整するアプローチです。 導入コストを下げるアプローチ 完全に新しいプラクティスを一から導入するのはコストが高いため、現行の開発フローをコンポーネント化し、AIに任せられる部分だけを切り出すアプローチを取りました。大きく変えるのではなく、今あるものの一部を置き換えていく形です。 まとめ AIにテストコードを生成させる施策を通じて、テスト数を57%増やし、カバレッジを約2倍に改善しました。一方で、運用面の課題も見えてきました。AIの生成速度に人間のレビューが追いつかないこと、コンテキストの属人化によりインプット/アウトプットだけでは品質を担保できないことです。 これらの課題に対しては、サマリの自動生成と粒度の制御という仕組み側の改善で対処しました。しかし「人間が差分を目視で確認する」という部分は残しています。ここを自動化できる条件は、まだ見出せていません。 AIと協業する開発フローにおいて、人間が関与すべきポイントはどこなのか。この問いに対する私たちの暫定的な答えは、「コードの差分を確認し、品質を判断すること」です。この判断を下せるのは、コードを書いてきた経験の上に成り立つ審美眼があるからだと考えています。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
GitHub Actions の失敗ログ、まだ手動で読んでいませんか? ども!龍ちゃんです。 CI が落ちたときの対応、毎回こうなっていませんか? GitHub Actions の UI を開く 失敗した Run を探す 失敗したジョブを開く ログをスクロールしてエラー行を目視で探す エラーメッセージをコピーしてググる 地味に面倒なんですよね、これ。特にジョブが複数あるワークフローだと、どのジョブのどのステップで落ちたのかを探すだけで時間を食う。 これ、Agent Skills に任せたら1行で終わります。 Before After 操作 GitHub UI → ログ目視 → 手動分析 「CI失敗してるから原因を調べて」 所要時間 5〜10分 30秒 得られるもの エラー行のコピペ 原因分析 + 修正方針のレポート 本記事では、gh CLI を使った CI ログ自動分析スキルを GitHub Copilot の Agent Skills として実装する手順を解説します。Claude Code で同じスキルを作った「 gh CLI × Claude Code で GitHub Actions 失敗ログをチャットで即解決 」の Copilot 移植版です。 190行あった Claude Code 版の SKILL.md を、Copilot の 500 トークン制限に合わせて 58 行に圧縮する設計がメインの話題になります。 対象読者 Agent Skills で実用的なスキルを作りたい人 Claude Code のスキルを Copilot に移植したい人 CI/CD のデバッグを自動化したい人 Agent Skills の基本(ディレクトリ構造、SKILL.md の書き方)は「 【2026年版】Agent Skills 入門 」を参照してください。 GitHub Actions の失敗を Agent Skills で自動分析する 作り方の前に、まず完成形を見てください。こういうやりとりになります。 龍ちゃん CI失敗してるから原因を調べて GitHub Copilot 失敗した Run を特定します。 → gh run list –status failure –limit 5 → gh run view 22573804432 –json jobs → gh run view 22573804432 –log –job 65388009712 ## Failure Analysis Root Cause: integration test が HTTP 503 で失敗 Suggested Fix: サービスのヘルスチェックをテスト前に実行 1行のプロンプトで、失敗 Run の特定からログ取得、原因分析まで全自動。この動きを実現するスキルの作り方を、このあと順を追って解説します。 前提条件 VS Code + GitHub Copilot(Agent Mode が使える状態) gh CLI がインストール・認証済み( gh auth status で確認) .github/skills/gh-workflow/ にスキルが配置済み(本記事で作ります) テスト用の失敗ワークフロー(demo-failure.yml) 検証用に、意図的に失敗するワークフローを用意しました。 name: Demo - Failure Workflow on: workflow_dispatch: jobs: setup: name: Setup runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Verify environment run: | echo "Environment check..." echo "OS: $(uname -s)" echo "Setup completed." test: name: Test runs-on: ubuntu-latest needs: setup steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run unit tests run: | echo "Running unit tests..." echo "test_fetch_article ... PASSED" echo "test_parse_html ... PASSED" echo "Unit tests passed." - name: Run integration tests run: | echo "Running integration tests..." echo "" echo "FAILED: test_pipeline.py::test_full_pipeline" echo " AssertionError: Expected status code 200, got 503" echo " File: tests/test_pipeline.py, line 42" echo " assert response.status_code == 200" echo "" echo "1 passed, 1 failed in 3.42s" exit 1 deploy: name: Deploy runs-on: ubuntu-latest needs: test steps: - name: Deploy application run: echo "Deploying..." Setup → Test → Deploy の3ジョブ構成で、Test ジョブの integration tests が 503 エラーで exit 1 します。CI/CD でよくあるパターンを再現しています。 手動実行して失敗させておきます。 gh workflow run "Demo - Failure Workflow" # 30秒ほど待ってから確認 gh run list --workflow "demo-failure.yml" --limit 1 デモ 1:gh run list でクイックステータス確認 VS Code の Agent Mode で「CI確認して」と入力します。 スキルが発火すると、Copilot は SKILL.md の Mode 1(クイックステータス)に従い、 gh run list で最新の実行状況を一覧取得します。 実行されたコマンド: git branch --show-current gh run list --branch main --limit 10 --json databaseId,status,conclusion,name,headBranch,event,createdAt,displayTitle 出力(Copilot のレポート): 日時 ワークフロー名 ステータス Run ID 3/2 11:23 Demo – Failure Workflow failure 22573804432 2/26 06:20 Demo – Failure Workflow failure 22430458939 2/26 06:20 Demo – CI Pipeline success 22430440934 2/26 06:19 Demo – CI Pipeline success 22430416062 「最新の CI が失敗しています」と報告したうえで、「失敗ログを分析しますか?」と次のアクションを提案してくれます。ブランチ取得から一覧表示まで自動で、自分が打つのはプロンプト1行だけです。 デモ 2:gh run view –log で失敗ログを自動分析 ここがメインのデモです。「3/2に失敗したものを取得してほしい」と入力すると、スキルの Mode 4(ログ分析)が起動します。 Copilot は SKILL.md に書かれた Progressive Filtering (段階的絞り込み)の手順に従って、4ステップで自動分析します。 Step 1: 失敗 Run の特定 gh run view 22573804432 --json jobs,status,conclusion,createdAt,updatedAt,headBranch,event,workflowName Run 全体の情報を取得。3ジョブの中から Test ジョブが failure であることを特定。 Step 2: 失敗ジョブの絞り込み JSON レスポンスから失敗ジョブの ID(65388009712)を抽出。Step 4 の「Run integration tests」が failure であることを確認。 Step 3: ログ取得 gh run view 22573804432 --log --job 65388009712 --log は必ず --job と併用します。これは SKILL.md の Token Efficiency Rules で定義したルールです。 --job なしだと全ジョブのログが出力されてトークンを大量消費するので、失敗ジョブに絞って取得します。 Step 4: エラー分析とレポート出力 ## Failure Analysis **Run:** #22573804432 - Demo - Failure Workflow **Branch:** main | Job | Error Summary | |-----|--------------| | Test | AssertionError: Expected status code 200, got 503 | **Root Cause:** Integration test `test_pipeline.py::test_full_pipeline` が失敗。 外部サービスへの接続で HTTP 503 (Service Unavailable) を受信。 **Suggested Fix:** 1. サービスのヘルスチェックをテスト前に実行 2. テストエンドポイントへのネットワーク接続を確認 3. テストデータ・環境設定を見直し Run 全体 → 失敗ジョブ → 失敗ステップ → エラー行と、段階的に絞り込んで 503 エラーを特定し、原因と修正方針をレポートにまとめてくれました。これが Progressive Filtering の実際の動きです。 デモ 3:英語プロンプトでの発火確認 description に英語キーワードも埋め込んであるので、英語でも発火します。 「Analyze the GitHub Actions error logs」と入力すると、同じく Progressive Filtering が走り、英語で Failure Analysis Report が出力されました。日本語チームと英語チームが混在する環境でも使えます。 Copilot 用 SKILL.md の作り方:190行→58行に圧縮する設計 やっと本題です。ここが一番悩んだところで、Claude Code 版の SKILL.md(190行)を Copilot の制約に合わせて58行に圧縮する設計を解説します。 ディレクトリ構成と配置ルール .github/ ├── copilot-instructions.md ← ルーティング追記 ├── skills/ │ └── gh-workflow/ │ ├── SKILL.md ← 本体(58行・219語) │ └── references/ │ └── commands.md ← 詳細情報(79行・266語) └── workflows/ ├── demo-failure.yml ← テスト用(意図的に失敗) └── demo-success.yml ポイント: ファイル名は SKILL.md (大文字必須) ディレクトリ名は kebab-case で name フィールドと一致させる Claude Code 版( .claude/skills/gh-workflow/ )とは別ディレクトリなので、両方共存できる SKILL.md と references/ の分離基準 GitHub Copilot には SKILL.md に対する 500 トークン制限 (約60行・300語以内)があります。Claude Code にはこの制限がないので、190行の SKILL.md がそのまま動いていましたが、Copilot ではそうはいきません。 圧縮の方針は「SKILL.md はルーター、詳細は references/ に分離」です。 分類 SKILL.md に残す references/commands.md に分離 モード判定 4モードのテーブル(4行) – Token Efficiency Rules 必須ルール4項目 – 各モードの手順 概要(主なコマンド1行ずつ) JSON 出力パターン全文 レポートテンプレート – ステータス一覧 + 失敗分析テンプレート Status/Conclusion 一覧 – 12行の値テーブル Important Notes – 4項目の注意事項 残す基準 : Copilot がスキルを実行するときに「最初に読む必要がある情報」だけ残す。モード判定(何をすべきか)とトークン効率ルール(やってはいけないこと)。この2つがないと、Copilot は最初の一歩を踏み出せません。 分離する基準 : 必要になったタイミングで参照すればいい情報。JSON の出力パターンやレポートテンプレートは、実行が進んだ段階で references/ から読み込めば十分です。「あとで見ればいいもの」は全部 references/ に押し出す。割り切りが大事でした。 Copilot の Progressive Disclosure(関連度に基づいて必要なファイルだけ読み込む仕組み)がこの分離設計と噛み合います。SKILL.md を読んでモードを判定し、実行に必要な詳細情報を references/ から追加で読む、という流れになるわけです。 圧縮結果: Claude Code 版 Copilot 版 SKILL.md 190行 58行(219語) 参照ファイル なし(全部入り) references/commands.md(79行・266語) 合計 190行 137行(2ファイル) 行数の合計はあまり変わりませんが、SKILL.md 単体が 500 トークン予算の 73% に収まっているのがポイントです。 description の書き方:単一行で書く鉄則 description は Copilot がスキルを選ぶかどうかを判定する 最重要フィールド です。ここの設計が発火率を左右します。 鉄則:description は単一行で書く。 description: | の複数行記法は使わない。 # NG: 複数行記法 → Copilot が "|" だけ読み込んでしまう description: | GitHub Actions の Workflow 状態確認とログ分析を行うスキル。 Use when: CIが失敗した原因を調べたい。 # OK: 単一行 → Copilot が全文を正しく読み込む description: GitHub Actionsのワークフロー状態確認と失敗ログ分析を行うスキル。gh CLIでCI/CDのログ取得から原因分析まで実行する。Use when: CIが失敗した原因を調べたい、ワークフローの状態を確認したい、PRのチェック結果を見たい。Triggers on: CI確認, Workflow確認, CI失敗, ログ分析, GitHub Actions debug,CI status check, workflow failure, PRチェック, エラーログ, pipeline debug. GitHub Copilot のスキルローダーは YAML の複数行記法( description: | )を正しくパースできません。 | という文字列だけが description として読み込まれ、発火判定に使われる情報がほぼゼロになります。Claude Code ではこの問題は起きないので、移植時に見落としがちな落とし穴です。 description に含める3要素: 機能説明 — 何をするスキルか Use when — どういう場面で使うか(ユーザーの意図) Triggers on — 発火キーワード(日本語 + 英語) Copilot は description の文字列とユーザーの発話の 類似度 でスキルを選ぶので、「ユーザーが実際に言いそうな言葉」を入れておくのがコツです。 description の設計思想や、なぜ発火しないのかの原因分析は「 Claude CodeからGitHub Copilotへ移植したらAgent Skillsが動かない?原因と解決策 」で詳しく解説しています。本記事では実装だけ押さえて先に進みます。 copilot-instructions.md でスキル発火を安定させる description だけでは発火が不安定な場合の補強策として、 copilot-instructions.md にルーティングテーブルを追加します。copilot-instructions.md は Agent Mode で常に読み込まれるファイルなので、ここにスキルへの道しるべを書いておくと発火が安定します。 ## Agent Skills Routing | キーワード | スキル | パス | |-----------|--------|------| | CI確認, Workflow, GitHub Actions, ログ分析, CI失敗, pipeline debug | gh-workflow | `.github/skills/gh-workflow/SKILL.md` | 既存の copilot-instructions.md の末尾に追記するだけです。中身は触らない。 注意点として、ルーティングに登録するスキルは 重要なもの3〜5個に絞る べきです。copilot-instructions.md に書いた内容は毎回のコンテキストに含まれるので、スキル全部を登録するとトークンを無駄遣いします。 この手法の効果と限界は「 Agent Skillsが動かない? 」の「解決策③:Instructions ルーティング」セクションで検証データ付きで解説しています。 allowed-tools の検証:agentskills.io 仕様と実装のギャップ SKILL.md のフロントマターには allowed-tools というフィールドがあります。スキルが使ってよいツールを制限する仕組みです。今回のスキルでは以下のように書きました。 allowed-tools: Bash(gh:*) Bash(git:*) Bash(jq:*) Read 「gh CLI と git と jq のコマンド実行、それとファイル読み取りだけ許可する」という意味です。 agentskills.io Specification での定義 agentskills.io の仕様 では、 allowed-tools は正式なオプションフィールドとして定義されています。ただし Experimental(実験的) ステータスで、”Support for this field may vary between agent implementations” と注記されています。 記法は2パターンあります: # パターン記法(コマンドプレフィックス指定) allowed-tools: Bash(gh:*) Bash(git:*) Read # ツール名列挙(MCP ツール等) allowed-tools: list_workflow_runs summarize_job_log_failures get_job_logs GitHub Copilot での動作検証結果 結論から言うと、 現時点では allowed-tools の enforcement(強制)は実装されていません 。 今回の検証では、 allowed-tools を書いた状態でスキルは正常に発火し、gh CLI のコマンドも問題なく実行されました。一方で、 allowed-tools に列挙していないツールの使用を制限する動作は確認できませんでした。 確認項目 結果 スキルの発火 問題なし(allowed-tools が発火を妨げない) allowed-tools 内のツール使用 問題なし allowed-tools 外のツール制限 未確認(制限が効いている証拠なし) VS Code バリデータの警告 Issue #14131 として報告済み(Open、対応予定なし) allowed-tools はスキル選択時には参照されず、スキル実行時に SKILL.md の本文を読んだ段階で「ガイドライン」として機能している可能性があります。強制力のあるサンドボックスではなく、エージェントへの「お願い」に近い位置づけです。 コミュニティの allowed-tools 実装例 参考までに、 heilcheng/awesome-agent-skills の github-actions-failure-debugging スキルを見ると、 allowed-tools はフロントマターに書かず、本文テキスト内で手順として使用ツールを記述しています。 To debug failing GitHub Actions workflows: 1. Use `list_workflow_runs` to look up recent workflow runs 2. Use `summarize_job_log_failures` to get an AI summary of failed jobs 3. Use `get_job_logs` for full detailed failure logs if needed フロントマターの allowed-tools で制限するか、本文で手順として指示するか。enforcement が実装されていない現時点では、本文に書くほうが確実にエージェントに伝わります。 正直どちらにするか迷ったんですが、自分のスキルでは「両方書いておく」方針にしました。フロントマターは将来の enforcement が来たときの保険、本文は今のエージェントへの確実な指示。二重管理にはなりますが、壊れるリスクよりマシだと判断しています。 Claude Code 版 SKILL.md との違い(比較表) 同じ gh-workflow スキルの Claude Code 版と Copilot 版を比較します。 変わる点:description・トークン予算・ファイル構成 比較項目 Claude Code 版 Copilot 版 ファイルパス .claude/skills/gh-workflow/ .github/skills/gh-workflow/ SKILL.md 行数 190行(1ファイル完結) 58行 + references/commands.md description トリガー文字列列挙 単一行で Use when + Triggers on allowed-tools Bash, Read Bash(gh:*) Bash(git:*) Bash(jq:*) Read 参照ファイル分離 不要(全文コンテキストに読み込み) 必須(500トークン制限) copilot-instructions.md 不要 ルーティング追記推奨 一番大きいのは「トークン予算」です。Claude Code は SKILL.md を丸ごと読み込めるので圧縮の必要がなく、190行でも問題ありません。Copilot は 500 トークン制限があるので、references/ への分離が必須になります。 変わらない点:gh CLI コマンド・Progressive Filtering 比較項目 Claude Code / Copilot 共通 gh CLI コマンド 同一( gh run list , gh run view --log --job 等) Progressive Filtering 同一(一覧→ジョブ特定→ログ取得→分析の4ステップ) Token Efficiency Rules 同一( --log は --job と併用、 watch 禁止等) Report Template 同一(references/commands.md に移植済み) gh CLI のノウハウはそのまま使えます。変えるのはスキルの外側(配置・description・トークン予算)だけで、中身は同じものが動きます。 リポジトリ/ ├── .claude/skills/gh-workflow/SKILL.md ← Claude Code版(190行・1ファイル完結) ├── .github/skills/gh-workflow/ ← Copilot版(58行 + references/) │ ├── SKILL.md │ └── references/commands.md └── (両方共存可能・互いに干渉しない) ちなみに GitHub Copilot は .claude/skills/ 配下のファイルも読み込みます。つまり Claude Code 用に作ったスキルが Copilot 側でも認識される。ただし 190 行の SKILL.md だとトークン予算を超えるし、 description: | の複数行記法は Copilot で壊れるので、そのまま期待どおりに動くかは別問題です。Claude Code ユーザーが Copilot でも使いたいなら、本記事のように .github/skills/ に圧縮版を別途置くのが確実です。 まとめ CI が落ちたら「CI失敗してるから原因を調べて」。それだけで原因分析から修正方針までレポートが出てきます。 やることは .github/skills/gh-workflow/ に SKILL.md と references/commands.md を置くだけ。あとは copilot-instructions.md にルーティングを1行追記すれば完了です。 本記事のポイント: SKILL.md は 500 トークン以内に圧縮 — 190行→58行。モード判定とトークン効率ルールだけ残し、詳細は references/ に分離 description は単一行で書く — description: | の複数行記法は Copilot で読み込まれない。詳細は「 Agent Skillsが動かない? 」 allowed-tools は Experimental — 仕様にはあるが enforcement 未実装。書いておいて損はないが、過信しない gh CLI のノウハウは共通 — Claude Code と Copilot で変えるのは外側だけ ではまた! Claude Code で同じことをやるなら「 gh CLI × Claude Code で GitHub Actions 失敗ログをチャットで即解決 」を参照してください。 検証環境 検証日: 2026年3月2〜3日 環境: VS Code + GitHub Copilot(Agent Mode) モデル: claude-sonnet-4.5(Copilot 経由) 参考: VS Code Docs – Agent Skills , agentskills.io Specification 付録:SKILL.md / references/commands.md 全文コピー用 自分のリポジトリに導入するときは、以下のディレクトリ構成でファイルを配置してください。 .github/ ├── copilot-instructions.md ← 末尾にルーティングを追記 ├── skills/ │ └── gh-workflow/ │ ├── SKILL.md ← 下記「SKILL.md 全文」をコピー │ └── references/ │ └── commands.md ← 下記「commands.md 全文」をコピー └── workflows/ └── demo-failure.yml ← テスト用(本記事「テスト用の失敗ワークフロー」参照) .github/skills/gh-workflow/SKILL.md(58行・219語) --- name: gh-workflow description: GitHub Actionsのワークフロー状態確認と失敗ログ分析を行うスキル。gh CLIでCI/CDのログ取得から原因分析まで実行する。Use when: CIが失敗した原因を調べたい、ワークフローの状態を確認したい、PRのチェック結果を見たい。Triggers on: CI確認, Workflow確認, CI失敗, ログ分析, GitHub Actions debug,CI status check, workflow failure, PRチェック, エラーログ, pipeline debug. allowed-tools: Bash(gh:*) Bash(git:*) Bash(jq:*) Read --- # GitHub Actions Workflow Status & Log Analysis gh CLI を使って GitHub Actions の Workflow ステータス確認・ログ分析を行います。 ## Mode Selection ユーザーの指示から以下の4モードを自動判定して実行する。 | モード | トリガー例 | 主なコマンド | |--------|-----------|-------------| | クイックステータス | 「CI確認して」 | `gh run list` | | Run 詳細 | 「Run #123 の詳細」 | `gh run view <run-id>` | | PR チェック | 「PR #42 のチェック」 | `gh pr checks <pr-number>` | | ログ分析 | 「CI失敗してるから見て」 | `gh run view --log --job` | ## Token Efficiency Rules(必須) - `--log` は必ず `--job <job-id>` と併用(全ジョブログは膨大) - `gh run watch` / `gh pr checks --watch` は使用禁止(トークン大量消費) - JSON 出力 + jq で必要なフィールドのみ取得する - Progressive Filtering: 一覧→絞り込み→詳細の順に段階的に情報取得 ## 各モードの実行概要 ### Mode 1: クイックステータス `gh run list --branch $(git branch --show-current) --limit 10` で一覧取得→テンプレート報告。 ### Mode 2: Run 詳細 `gh run view <run-id> --json status,conclusion,jobs,createdAt,updatedAt,headBranch,event` で詳細取得。 ### Mode 3: PR チェック `gh pr checks <pr-number>` でチェック状況取得。PR番号不明時はブランチから自動検出。 ### Mode 4: ログ分析(メイン) 1. `gh run list --status failure` で失敗 Run 特定 2. `gh run view <run-id> --json jobs` で失敗ジョブ特定 3. `gh run view <run-id> --log --job <job-id>` でログ取得(必ず --job 指定) 4. エラー箇所を分析し原因と修正方針を報告 ## 詳細リファレンス JSON 出力パターン、レポートテンプレート、ステータス一覧は `references/commands.md` を参照。 .github/skills/gh-workflow/references/commands.md(79行・266語) # gh-workflow コマンドリファレンス > SKILL.md から参照される詳細情報。Copilot が必要に応じて読み込む。 ## JSON Output Patterns よく使う構造化データ取得パターン: ```bash # Run 一覧を JSON で取得 gh run list --limit 10 --json databaseId,displayTitle,status,conclusion,headBranch,createdAt,event # Run 内のジョブ詳細 gh run view <run-id> --json jobs --jq '.jobs[] | {id: .databaseId, name, status, conclusion, startedAt, completedAt}' # 失敗ジョブのみ抽出 gh run view <run-id> --json jobs --jq '.jobs[] | select(.conclusion == "failure") | {id: .databaseId, name}' # PR チェックの詳細(JSON) gh pr checks <pr-number> --json name,state,description,detailsUrl ``` ## Report Template 以下のテンプレートを使って結果を報告する。 ### ステータス一覧 ``` ## Workflow Status | # | Workflow | Branch | Status | Conclusion | Triggered | |---|---------|--------|--------|------------|-----------| | 1 | <name> | <branch> | <status> | <conclusion> | <event> | ``` ### 失敗分析 ``` ## Failure Analysis **Run:** #<run-id> - <workflow-name> **Branch:** <branch> **Failed Jobs:** | Job | Error Summary | |-----|--------------| | <job-name> | <error-summary> | **Root Cause:** <分析結果> **Suggested Fix:** <修正方針> ``` ## Status / Conclusion Reference | 値 | 種類 | 意味 | |----|------|------| | `queued` | status | キュー待ち | | `in_progress` | status | 実行中 | | `completed` | status | 完了 | | `waiting` | status | 承認待ち | | `success` | conclusion | 成功 | | `failure` | conclusion | 失敗 | | `cancelled` | conclusion | キャンセル済み | | `skipped` | conclusion | スキップ | | `timed_out` | conclusion | タイムアウト | | `action_required` | conclusion | アクション要求 | | `neutral` | conclusion | 中立(情報のみ) | | `stale` | conclusion | 古い結果 | ## Important Notes - **gh CLI 未認証の場合**: `gh auth status` で認証状態を確認し、未認証ならユーザーに通知 - **リポジトリ外で実行した場合**: エラーをユーザーに通知 - **大量のログ出力**: 必ず `--job` で絞り込み、それでも長い場合は主要なエラー行のみ抽出 - **進行中の Run**: ステータスが `in_progress` の場合、完了を待たずに現在の状態を報告(`watch` は使わない) copilot-instructions.md に追記するルーティング ## Agent Skills Routing | キーワード | スキル | パス | |-----------|--------|------| | CI確認, Workflow, GitHub Actions, ログ分析, CI失敗, pipeline debug | gh-workflow | `.github/skills/gh-workflow/SKILL.md` | 参考リンク 公式ドキュメント VS Code Docs – Agent Skills agentskills.io Specification VS Code Docs – Copilot Customization 関連 Issue microsoft/vscode-copilot-release#14131 — VS Code バリデータが allowed-tools を未認識 関連記事 【2026年版】Agent Skills 入門:SKILL.md の基本から実践まで Claude CodeからGitHub Copilotへ移植したらAgent Skillsが動かない?原因と解決策 gh CLI × Claude Code で GitHub Actions 失敗ログをチャットで即解決 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post GitHub Actions失敗ログ、まだ手動で読む?Copilot Agent Skills で CI デバッグを自動化する実装ガイド first appeared on SIOS Tech Lab .

動画

該当するコンテンツが見つかりませんでした

書籍