From 8bbd9fc1ed5382f4c08ddcce59c563212cd90836 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 11 Jun 2026 23:44:05 +0900 Subject: [PATCH] =?UTF-8?q?feat(repo-maintenance):=20=E7=B5=84=E7=B9=94?= =?UTF-8?q?=E6=A8=AA=E6=96=AD=E7=9B=A3=E6=9F=BB=E3=81=AE=E7=9F=A5=E8=A6=8B?= =?UTF-8?q?=E3=82=92=E5=8F=8D=E6=98=A0=E3=81=97=E3=81=9F9=E3=81=A4?= =?UTF-8?q?=E3=81=AE=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=83=BB=E5=BC=B7=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10リポジトリの横断監査で頻出した運用課題を /repo-maintenance で検出・修正 できるようにする。 - 2.9 拡張: SHA固定チェックを first-party actions にも適用 - 3.1 強化: ブランチ保護の両輪検証(reviews + required checks)と delete_branch_on_merge の確認・自動修正 - 3.5.4 新設: 品質スクリプトの CI 参照確認と continue-on-error 検出 - 3.16 拡張: SECURITY.md のプレースホルダー残存・記載と実態の乖離検証 - 3.18 新設: CONTRIBUTING.md チェック(テンプレート配布) - 3.23 新設: カバレッジ閾値ラチェット方式チェック - 4.3 新設: 追跡生成物・大容量ファイル・ルートクラッター検出 - 4.4 新設: submodule ピン先の健全性確認 - 4.5 新設: stale PR・未マージ security ブランチ検出 Co-Authored-By: Claude Fable 5 --- .claude/commands/repo-maintenance.md | 351 +++++++++++++++++++++++++-- 1 file changed, 336 insertions(+), 15 deletions(-) diff --git a/.claude/commands/repo-maintenance.md b/.claude/commands/repo-maintenance.md index ae1fe456..7717d425 100644 --- a/.claude/commands/repo-maintenance.md +++ b/.claude/commands/repo-maintenance.md @@ -283,7 +283,7 @@ GitHub はフル SHA 固定を immutable な使い方として推奨しており | # | チェック | 推奨値 | リスク | | --- | ------------------------------ | ------------------------------------------ | ------------------------------ | -| 1 | 3rd-party actions の SHA 固定 | フルSHA(40文字)で参照 | タグ改ざんによるコード注入 | +| 1 | 全 actions の SHA 固定 | フルSHA(40文字)で参照 | タグ改ざんによるコード注入 | | 2 | `GITHUB_TOKEN` の権限制限 | workflow/job レベルで `permissions` を明示 | 過剰権限によるトークン悪用 | | 3 | 許可 actions の制限 | Repository Settings で制限 | 任意の actions 実行リスク | | 4 | `pull_request_target` の安全性 | 未使用 or secrets 非参照 | Fork PR 経由のシークレット漏洩 | @@ -298,15 +298,19 @@ for workflow in .github/workflows/*.yml; do BASENAME=$(basename "$workflow") CONTENT=$(cat "$workflow") - # 1. 3rd-party actions の SHA 固定チェック - # actions/ と github/ org 以外の actions を検出 - THIRD_PARTY=$(echo "$CONTENT" | grep -oE "uses: [^/]+/[^@]+@[^ ]+" | \ - grep -vE "^uses: (actions|github)/" | \ - grep -vE "@[0-9a-f]{40}") - if [ -n "$THIRD_PARTY" ]; then + # 1. actions の SHA 固定チェック(全 actions 対象) + # first-party(actions/, github/)もタグ参照のままの repo が多数あったため全件検出する。 + # 3rd-party は critical、first-party は warning として区別する + UNPINNED=$(echo "$CONTENT" | grep -oE "uses: [^/]+/[^@]+@[^ ]+" | \ + grep -vE "@[0-9a-f]{40}" | grep -v "uses: \./") + if [ -n "$UNPINNED" ]; then while IFS= read -r line; do - ISSUES+=("$BASENAME: SHA未固定の3rd-party action: $line") - done <<< "$THIRD_PARTY" + if echo "$line" | grep -qE "^uses: (actions|github)/"; then + ISSUES+=("$BASENAME: SHA未固定の first-party action (warning): $line") + else + ISSUES+=("$BASENAME: SHA未固定の 3rd-party action (critical): $line") + fi + done <<< "$UNPINNED" fi # 2. GITHUB_TOKEN 権限チェック(top-level permissions の有無) @@ -412,9 +416,38 @@ elif [ -n "$EXISTING_ENV_BRANCHES" ]; then fi ``` +**保護設定の実態検証(レビュー × 必須チェックの「両輪」確認):** + +最も頻出する設定不備は「レビュー必須 or 必須ステータスチェックの**片方しか**設定されていない」パターン。 +チェック欠落なら CI 赤のままマージ可能、レビュー欠落ならレビューなしマージが可能になる。 +/setup-team-protection の実行有無に関わらず、現在の実態を API で直接検証する: + +```bash +PROTECTION=$(gh api "repos/$REPO/branches/main/protection" 2>/dev/null) + +REVIEWS=$(echo "$PROTECTION" | jq -r '.required_pull_request_reviews.required_approving_review_count // 0') +CHECKS=$(echo "$PROTECTION" | jq -r '.required_status_checks.contexts // [] | length') +ENFORCE_ADMINS=$(echo "$PROTECTION" | jq -r '.enforce_admins.enabled // false') + +[ "$REVIEWS" -lt 1 ] && ISSUES+=("main: レビュー必須が未設定(0名)→ レビューなしでマージ可能") +[ "$CHECKS" -lt 1 ] && ISSUES+=("main: 必須ステータスチェックが未設定 → CI 赤のままマージ可能") +[ "$ENFORCE_ADMINS" != "true" ] && ISSUES+=("main: enforce_admins 無効 → 管理者は保護をバイパス可能") + +# マージ済みブランチの自動削除(無効だとリモートブランチが累積する) +DELETE_ON_MERGE=$(gh api "repos/$REPO" --jq '.delete_branch_on_merge' 2>/dev/null) +[ "$DELETE_ON_MERGE" != "true" ] && \ + ISSUES+=("repo: delete_branch_on_merge 無効 → マージ済みブランチが累積") +``` + +**MODE が `full` の場合の修正:** + +- レビュー / 必須チェックの欠落 → `/setup-team-protection` で両方を設定(必須チェックは `Quality Gate` を登録し、3.5.0.2 の fallback とセットで配布) +- `delete_branch_on_merge` → `gh api -X PATCH "repos/$REPO" -F delete_branch_on_merge=true` で自動修正 + 結果: -- ✅ 保護ルール設定済み +- ✅ 保護ルール設定済み(レビュー + 必須チェックの両輪) +- ⚠️ 片輪のみ設定(欠落側を明示: レビュー 0 名 / 必須チェックなし) - ⚠️ 未設定の保護ルールあり(詳細をリスト) - ⚠️ `pre-production` / `production` ブランチ未保護 → 保護を提案 - 🔧 設定を適用 @@ -1159,6 +1192,57 @@ grep -rn 'keito4/config' templates/ | grep -v 'README\|\.md' || echo "OK: no har このチェックは情報提供のみで、自動修正は行わない。 +### 3.5.4 CI Blocking Gate Check + +品質チェックが「CI に存在し、かつ blocking である」ことを確認: + +**背景:** +ローカルフック(husky / lint-staged)は `--no-verify` や別環境からの push で素通りできるため、 +CI 側に同じゲートがなければ品質保証にならない。実際に多くのリポジトリで以下の 2 パターンが発生していた: + +1. lint / typecheck がローカルフックのみで CI に存在しない +2. CI には存在するが `continue-on-error: true` で実質非ブロッキング(型エラーを数十件容認していた例あり) + +**確認ロジック:** + +```bash +# 1. package.json の品質スクリプトが CI から参照されているか +for script_name in lint typecheck type-check format:check test; do + jq -e --arg s "$script_name" '.scripts[$s]' package.json >/dev/null 2>&1 || continue + if ! grep -rqE "run (-w [^ ]+ )?$script_name\b|npx $script_name\b" .github/workflows/*.yml 2>/dev/null; then + ISSUES+=("品質スクリプト '$script_name' が CI のどのワークフローからも実行されていない(ローカルフックのみ)") + fi +done + +# 2. 品質ジョブの continue-on-error 検出 +for workflow in .github/workflows/*.yml; do + [ ! -f "$workflow" ] && continue + grep -q "continue-on-error: true" "$workflow" || continue + # lint/typecheck/test/coverage/audit を含むジョブ・ステップ近傍での使用を警告 + if grep -B5 "continue-on-error: true" "$workflow" | grep -qiE "(lint|typecheck|type-check|format|test|coverage)"; then + ISSUES+=("$(basename "$workflow"): 品質チェックに continue-on-error: true(実質非ブロッキング)") + fi +done +``` + +**結果パターン:** + +| 状態 | 対応 | +| ------------------------------------ | ----------------------------------------------------------- | +| 全品質スクリプトが CI で blocking | ✅ スキップ | +| CI 未参照の品質スクリプトあり | ⚠️ → full mode で ci.yml への追加を提案(テンプレート参照) | +| continue-on-error の品質チェックあり | ⚠️ → 解除可否を確認(段階導入中なら解除計画の Issue 化) | + +**Note**: npm audit 等のセキュリティ advisory は意図的に non-blocking とする運用もあるため、 +`continue-on-error` の検出は機械的に修正せず、意図を確認したうえで解除 or 理由のコメント追記を提案する。 + +**結果:** + +- ✅ CI Blocking Gates: 全品質チェックが CI で blocking +- ⚠️ CI 未参照の品質スクリプト: X 件(リスト表示) +- ⚠️ 非ブロッキングの品質チェック: X 件(リスト表示) +- ⏭️ スキップ(`package.json` なし) + ### 3.6 GitHub Actions Cost Optimization Check GitHub Actions のコスト最適化のため、全ワークフローの設定を確認: @@ -2086,10 +2170,40 @@ fi echo "🔧 SECURITY.md を追加しました" ``` +**内容の実態整合チェック:** + +SECURITY.md が存在する場合、プレースホルダーの残存と「記載と実態の乖離」を検証する。 +「secret scanning 有効」と記載しながら実際の GitHub 設定は無効、というドキュメントと実態の乖離は +誤った安心感を生むため、ファイルの存在チェックだけでは不十分: + +```bash +if [ "$HAS_SECURITY" = "true" ]; then + SEC_FILE=$([ -f "SECURITY.md" ] && echo "SECURITY.md" || echo ".github/SECURITY.md") + + # 1. プレースホルダー / TODO の残存 + if grep -qE "TODO|FIXME|security@example\.com|\[INSERT|