From be4a893d05ded69d8b3144ca66b0f5fb9404999f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 13:33:13 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20repo-maintenance=20=E3=81=AB?= =?UTF-8?q?=E6=8E=A8=E5=A5=A8=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E5=90=8C?= =?UTF-8?q?=E6=9C=9F=E3=82=B9=E3=83=86=E3=83=83=E3=83=97=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 3.22 として Config Template Sync を追加。 config リポジトリの推奨ワークフローやフックファイルを 他のリポジトリに自動同期する機能。 マネージドファイル(claude.yml, hooks等)は常に最新版で上書き、 テンプレートファイル(ci.yml, security.yml等)は差分確認後に更新。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/commands/repo-maintenance.md | 182 ++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/.claude/commands/repo-maintenance.md b/.claude/commands/repo-maintenance.md index 33945852..0578da24 100644 --- a/.claude/commands/repo-maintenance.md +++ b/.claude/commands/repo-maintenance.md @@ -1751,6 +1751,185 @@ echo " ✅ Wait timer: 5 minutes(任意)" - ⚠️ production 環境: 保護ルール未設定(設定手順を表示) - ⏭️ スキップ(GitHub Environments 未使用) +### 3.22 推奨ファイル同期 (Config Template Sync) + +config リポジトリ(`keito4/config`)の推奨テンプレートファイルと現在のリポジトリを比較し、差分があれば同期する。 + +**背景:** +`/setup-new-repo` で初期構築したリポジトリのワークフローやフックは、config リポジトリの更新に追従しない。 +このステップにより、推奨設定の変更(例: `cancel-in-progress` の修正)が全リポジトリに反映される。 + +**スキップ条件:** + +- 現在のリポジトリが `keito4/config` 自身の場合はスキップ +- `.devcontainer/devcontainer.json` に `config-base` イメージ参照がない場合はスキップ(config 管理外のリポジトリ) + +**同期対象ファイルの分類:** + +| カテゴリ | ファイル | 同期ポリシー | +| ------------ | ------------------------------------------ | ---------------------------- | +| マネージド | `.github/workflows/claude.yml` | 常に config の最新版で上書き | +| マネージド | `.github/workflows/claude-code-review.yml` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/block_git_no_verify.py` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/pre_git_quality_gates.py` | 常に config の最新版で上書き | +| マネージド | `.claude/hooks/post_git_push_ci.py` | 常に config の最新版で上書き | +| テンプレート | `.github/workflows/security.yml` | 差分表示 → 確認後に上書き | +| テンプレート | `.github/workflows/ci.yml` | 差分表示 → 確認後に上書き | +| テンプレート | `.github/ISSUE_TEMPLATE/*` | 欠落ファイルのみ追加 | +| テンプレート | `.github/pull_request_template.md` | 欠落時のみ追加 | + +**マネージドファイル**: config リポジトリが正規のソースであり、プロジェクト側でカスタマイズしない前提のファイル。 +**テンプレートファイル**: プロジェクト固有のカスタマイズが入る可能性があるため、差分確認を挟む。 + +**config リポジトリのソース取得:** + +```bash +# config リポジトリのローカルクローンを探す +CONFIG_REPO="" +SEARCH_PATHS=( + "$HOME/develop/github.com/keito4/config" + "$HOME/ghq/github.com/keito4/config" + "$HOME/src/github.com/keito4/config" +) +for path in "${SEARCH_PATHS[@]}"; do + if [ -d "$path/.github/workflows" ]; then + CONFIG_REPO="$path" + break + fi +done + +# ローカルに見つからない場合は GitHub API でフェッチ +if [ -z "$CONFIG_REPO" ]; then + TMPDIR=$(mktemp -d) + CONFIG_REPO="$TMPDIR" + gh api repos/keito4/config/tarball/main | tar xz -C "$TMPDIR" --strip-components=1 +fi +``` + +**マネージドファイルの同期ロジック:** + +```bash +MANAGED_FILES=( + ".github/workflows/claude.yml" + ".github/workflows/claude-code-review.yml" + ".claude/hooks/block_git_no_verify.py" + ".claude/hooks/pre_git_quality_gates.py" + ".claude/hooks/post_git_push_ci.py" +) + +UPDATED=() +SKIPPED=() + +for file in "${MANAGED_FILES[@]}"; do + SRC="$CONFIG_REPO/$file" + DST="./$file" + + if [ ! -f "$SRC" ]; then + continue + fi + + # ディレクトリが無ければ作成 + mkdir -p "$(dirname "$DST")" + + if [ ! -f "$DST" ]; then + # ファイルが存在しない → 新規コピー + cp "$SRC" "$DST" + UPDATED+=("$file (新規追加)") + elif ! diff -q "$SRC" "$DST" >/dev/null 2>&1; then + # 差分あり → 上書き + diff --color=auto -u "$DST" "$SRC" | head -30 + cp "$SRC" "$DST" + UPDATED+=("$file (更新)") + else + SKIPPED+=("$file (最新)") + fi +done +``` + +**テンプレートファイルの同期ロジック:** + +```bash +TEMPLATE_FILES=( + ".github/workflows/security.yml" + ".github/workflows/ci.yml" +) + +for file in "${TEMPLATE_FILES[@]}"; do + SRC="$CONFIG_REPO/$file" + DST="./$file" + + if [ ! -f "$SRC" ]; then + continue + fi + + mkdir -p "$(dirname "$DST")" + + if [ ! -f "$DST" ]; then + # 存在しない → コピー + cp "$SRC" "$DST" + UPDATED+=("$file (新規追加)") + elif ! diff -q "$SRC" "$DST" >/dev/null 2>&1; then + # 差分あり → diff を表示して確認 + echo "📄 $file に差分があります:" + diff --color=auto -u "$DST" "$SRC" | head -50 + # full mode: ユーザーに確認してから上書き + # check-only mode: 差分を報告のみ + if [ "$MODE" = "full" ]; then + echo "上書きしますか? (y/n)" + # Claude による対話的確認 + cp "$SRC" "$DST" + UPDATED+=("$file (更新)") + fi + else + SKIPPED+=("$file (最新)") + fi +done + +# Issue/PR テンプレート: 欠落ファイルのみ追加 +TEMPLATE_DIRS=( + ".github/ISSUE_TEMPLATE" +) +for dir in "${TEMPLATE_DIRS[@]}"; do + SRC_DIR="$CONFIG_REPO/$dir" + DST_DIR="./$dir" + if [ -d "$SRC_DIR" ]; then + mkdir -p "$DST_DIR" + for src_file in "$SRC_DIR"/*; do + dst_file="$DST_DIR/$(basename "$src_file")" + if [ ! -f "$dst_file" ]; then + cp "$src_file" "$dst_file" + UPDATED+=("$dir/$(basename "$src_file") (新規追加)") + fi + done + fi +done + +# PR テンプレート +PR_TEMPLATE_SRC="$CONFIG_REPO/.github/pull_request_template.md" +PR_TEMPLATE_DST="./.github/pull_request_template.md" +if [ -f "$PR_TEMPLATE_SRC" ] && [ ! -f "$PR_TEMPLATE_DST" ]; then + mkdir -p .github + cp "$PR_TEMPLATE_SRC" "$PR_TEMPLATE_DST" + UPDATED+=(".github/pull_request_template.md (新規追加)") +fi +``` + +**結果パターン:** + +| 状態 | 出力 | +| -------------------- | ------------------------------------------------- | +| 全ファイル最新 | ✅ Config Template Sync: 全ファイル最新 | +| 更新あり | 🔧 Config Template Sync: X 件更新 | +| 差分あり(確認待ち) | ⚠️ Config Template Sync: X 件の差分あり(要確認) | +| スキップ | ⏭️ スキップ(config リポジトリ自身 / 管理外) | + +**結果:** + +- ✅ Config Template Sync: 全ファイル最新 +- 🔧 Config Template Sync: X 件更新(更新ファイルをリスト表示) +- ⚠️ Config Template Sync: X 件の差分あり(テンプレートファイルの確認待ち) +- ⏭️ スキップ(config リポジトリ自身) + ## Step 4: Cleanup Category ### 4.1 Branch Cleanup @@ -2096,7 +2275,8 @@ fi ├── Renovate/Dependabot: ✅ Auto-update configured ├── Push Protection: ✅ Enabled (or ⚠️ Disabled) ├── Dependency Review: ✅ Configured (or ⚠️ Not configured) -└── Deploy Env Protection: ✅ Configured (or ⚠️ No reviewers / ⏭️ No environments) +├── Deploy Env Protection: ✅ Configured (or ⚠️ No reviewers / ⏭️ No environments) +└── Config Template Sync: ✅ All files up to date (or 🔧 X files updated / ⏭️ Skipped) ## Cleanup (3/4) ├── Branches: 🗑️ 8 merged branches can be deleted From dcbb61e539aa5f0fbd09cc128660fe47f5635f1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 13:43:18 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E6=8C=87=E6=91=98=E4=BA=8B=E9=A0=85=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - スキップ条件の具体的な判定ロジックを追加 - TMPDIR → TEMP_CONFIG_DIR に変更(システム予約変数のシャドウイング回避) - trap による一時ディレクトリのクリーンアップを追加 - テンプレートファイルの確認ロジックを明確化(MODE=full は Claude が確認、それ以外は報告のみ) - 空ディレクトリでの glob 対策を追加 - diff の --color=auto を削除(非インタラクティブ環境対応) Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/commands/repo-maintenance.md | 44 ++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/.claude/commands/repo-maintenance.md b/.claude/commands/repo-maintenance.md index 0578da24..4c0025f5 100644 --- a/.claude/commands/repo-maintenance.md +++ b/.claude/commands/repo-maintenance.md @@ -1759,10 +1759,26 @@ config リポジトリ(`keito4/config`)の推奨テンプレートファイ `/setup-new-repo` で初期構築したリポジトリのワークフローやフックは、config リポジトリの更新に追従しない。 このステップにより、推奨設定の変更(例: `cancel-in-progress` の修正)が全リポジトリに反映される。 +**前提:** `MODE` は Step 1 で定義済み(`full` / `quick` / `check-only`)。このステップは全モードで実行される。 + **スキップ条件:** -- 現在のリポジトリが `keito4/config` 自身の場合はスキップ -- `.devcontainer/devcontainer.json` に `config-base` イメージ参照がない場合はスキップ(config 管理外のリポジトリ) +```bash +# config リポジトリ自身かどうかを判定 +REPO_NAME=$(gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null || echo "") +if [ "$REPO_NAME" = "keito4/config" ]; then + echo "⏭️ スキップ(config リポジトリ自身)" + # このステップを終了 +fi + +# config-base 管理下かどうかを判定 +if [ -f ".devcontainer/devcontainer.json" ]; then + if ! grep -q "config-base" .devcontainer/devcontainer.json 2>/dev/null; then + echo "⏭️ スキップ(config 管理外のリポジトリ)" + # このステップを終了 + fi +fi +``` **同期対象ファイルの分類:** @@ -1799,10 +1815,12 @@ for path in "${SEARCH_PATHS[@]}"; do done # ローカルに見つからない場合は GitHub API でフェッチ +TEMP_CONFIG_DIR="" if [ -z "$CONFIG_REPO" ]; then - TMPDIR=$(mktemp -d) - CONFIG_REPO="$TMPDIR" - gh api repos/keito4/config/tarball/main | tar xz -C "$TMPDIR" --strip-components=1 + TEMP_CONFIG_DIR=$(mktemp -d) + trap 'rm -rf "$TEMP_CONFIG_DIR"' EXIT + CONFIG_REPO="$TEMP_CONFIG_DIR" + gh api repos/keito4/config/tarball/main | tar xz -C "$TEMP_CONFIG_DIR" --strip-components=1 fi ``` @@ -1869,16 +1887,17 @@ for file in "${TEMPLATE_FILES[@]}"; do cp "$SRC" "$DST" UPDATED+=("$file (新規追加)") elif ! diff -q "$SRC" "$DST" >/dev/null 2>&1; then - # 差分あり → diff を表示して確認 + # 差分あり → diff を表示 echo "📄 $file に差分があります:" - diff --color=auto -u "$DST" "$SRC" | head -50 - # full mode: ユーザーに確認してから上書き - # check-only mode: 差分を報告のみ + diff -u "$DST" "$SRC" | head -50 if [ "$MODE" = "full" ]; then - echo "上書きしますか? (y/n)" - # Claude による対話的確認 + # full mode: Claude が diff を確認し、ユーザーに対話的に確認してから上書き + # ※ このコマンドは Claude Code が実行するため、Claude がユーザーに確認を取る cp "$SRC" "$DST" - UPDATED+=("$file (更新)") + UPDATED+=("$file (確認後に更新)") + else + # quick / check-only mode: 差分を報告のみ + UPDATED+=("$file (差分あり・要確認)") fi else SKIPPED+=("$file (最新)") @@ -1895,6 +1914,7 @@ for dir in "${TEMPLATE_DIRS[@]}"; do if [ -d "$SRC_DIR" ]; then mkdir -p "$DST_DIR" for src_file in "$SRC_DIR"/*; do + [ ! -f "$src_file" ] && continue # 空ディレクトリでの glob 対策 dst_file="$DST_DIR/$(basename "$src_file")" if [ ! -f "$dst_file" ]; then cp "$src_file" "$dst_file"