Initial commit
This commit is contained in:
57
commands/branch-create.md
Normal file
57
commands/branch-create.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# ブランチ作成コマンド
|
||||
|
||||
新しいフィーチャーブランチを作成します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/branch-create [ブランチ名]
|
||||
```
|
||||
|
||||
## ブランチ命名規則
|
||||
- [Conventional Branch](https://conventional-branch.github.io/) に従う
|
||||
- 形式: `feature/[FeatureName]-[実装した機能名]`
|
||||
- 例: `feature/admin-user-role-edit-invite-form`
|
||||
|
||||
## 処理手順
|
||||
1. 現在の変更をstashして保存
|
||||
2. メインブランチから新しいブランチを作成
|
||||
3. stashした変更を適用
|
||||
4. ブランチの作成完了を確認
|
||||
|
||||
## 実装
|
||||
```bash
|
||||
# 現在の変更をstashに保存
|
||||
echo "💾 現在の変更をstashに保存中..."
|
||||
git stash push -m "branch-create: temporary stash before creating new branch"
|
||||
|
||||
# メインブランチに移動してリモートから最新を取得
|
||||
echo "🔄 メインブランチから最新の変更を取得中..."
|
||||
git checkout master 2>/dev/null || git checkout main
|
||||
git pull origin master 2>/dev/null || git pull origin main
|
||||
|
||||
# 新しいブランチを作成
|
||||
BRANCH_NAME="$1"
|
||||
if [ -z "$BRANCH_NAME" ]; then
|
||||
echo "❌ ブランチ名を指定してください"
|
||||
echo "使用方法: /branch-create feature/your-feature-name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🌿 新しいブランチを作成中: $BRANCH_NAME"
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
|
||||
# stashした変更を適用
|
||||
echo "📥 stashした変更を適用中..."
|
||||
git stash pop
|
||||
|
||||
echo "✅ ブランチ作成完了: $BRANCH_NAME"
|
||||
echo "📋 次のステップ:"
|
||||
echo "1. 必要な変更を実装"
|
||||
echo "2. /commit-create でコミット作成"
|
||||
echo "3. /push-current でリモートにpush"
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
- ブランチ名は意味のある名前にしてください
|
||||
- feature/ プレフィックスを使用してください
|
||||
- 既存のブランチ名と重複しないよう注意してください
|
||||
31
commands/branch-current.md
Normal file
31
commands/branch-current.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 現在のブランチ表示コマンド
|
||||
|
||||
現在のブランチ名をシンプルに表示します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/branch-current
|
||||
```
|
||||
|
||||
## 動作
|
||||
現在のブランチ名を表示します。
|
||||
|
||||
## 実装
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# 現在のブランチ名を取得して表示
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "$CURRENT_BRANCH"
|
||||
```
|
||||
|
||||
## 特徴
|
||||
- **シンプル**: 現在のブランチ名のみを表示
|
||||
- **高速**: 余計な処理なし
|
||||
|
||||
## 関連コマンド
|
||||
- `/branch-main`: メインブランチに移動して更新
|
||||
- `/branch-switch`: ブランチを切り替え
|
||||
- `/branch-create`: 新しいブランチを作成
|
||||
- `/commit`: 変更をコミット
|
||||
212
commands/branch-main.md
Normal file
212
commands/branch-main.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# メインブランチ最新化コマンド
|
||||
|
||||
メインブランチ(main/master)に移動して最新の状態に更新します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/branch-main
|
||||
```
|
||||
|
||||
## 動作
|
||||
1. メインブランチ名を自動検出(main または master)
|
||||
2. 作業中の変更を確認し、あれば自動的にstashで一時保存
|
||||
3. メインブランチに切り替え
|
||||
4. リモートから最新の変更を取得(pull)
|
||||
5. stashした変更を自動復元
|
||||
6. 更新後の状態を表示
|
||||
|
||||
## 実装
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# メインブランチ名を検出する関数
|
||||
detect_main_branch() {
|
||||
# リモートのメインブランチを確認
|
||||
if git ls-remote --heads origin main >/dev/null 2>&1; then
|
||||
echo "main"
|
||||
elif git ls-remote --heads origin master >/dev/null 2>&1; then
|
||||
echo "master"
|
||||
else
|
||||
# ローカルで確認
|
||||
if git show-ref --verify --quiet refs/heads/main; then
|
||||
echo "main"
|
||||
elif git show-ref --verify --quiet refs/heads/master; then
|
||||
echo "master"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# メインブランチ名を検出
|
||||
MAIN_BRANCH=$(detect_main_branch)
|
||||
|
||||
if [ -z "$MAIN_BRANCH" ]; then
|
||||
echo "❌ メインブランチ(main/master)が見つかりません"
|
||||
echo ""
|
||||
echo "💡 以下を確認してください:"
|
||||
echo "- git remote -v でリモート設定を確認"
|
||||
echo "- git branch -a でブランチ一覧を確認"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔄 メインブランチ更新処理を開始します"
|
||||
echo ""
|
||||
echo "📌 現在のブランチ: $CURRENT_BRANCH"
|
||||
echo "🎯 メインブランチ: $MAIN_BRANCH"
|
||||
|
||||
# 作業ツリーに変更があるか確認
|
||||
STASH_NEEDED=false
|
||||
if ! git diff-index --quiet HEAD -- 2>/dev/null || [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
||||
echo ""
|
||||
echo "📝 未コミットの変更を検出しました"
|
||||
echo ""
|
||||
echo "💡 変更内容:"
|
||||
git status --short
|
||||
echo ""
|
||||
echo "🔄 変更を一時保存(stash)します..."
|
||||
|
||||
# stashにメッセージ付きで保存
|
||||
STASH_MSG="Auto-stash by branch-main command from $CURRENT_BRANCH"
|
||||
if git stash push -m "$STASH_MSG" --include-untracked; then
|
||||
STASH_NEEDED=true
|
||||
echo "✅ 変更を一時保存しました"
|
||||
else
|
||||
echo "❌ 変更の一時保存に失敗しました"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 既にメインブランチにいる場合
|
||||
if [ "$CURRENT_BRANCH" = "$MAIN_BRANCH" ]; then
|
||||
echo ""
|
||||
echo "✅ 既に$MAIN_BRANCH ブランチにいます"
|
||||
else
|
||||
# メインブランチに切り替え
|
||||
echo ""
|
||||
echo "🔀 $MAIN_BRANCH ブランチに切り替え中..."
|
||||
if ! git checkout $MAIN_BRANCH; then
|
||||
echo "❌ ブランチの切り替えに失敗しました"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ $MAIN_BRANCH ブランチに切り替えました"
|
||||
fi
|
||||
|
||||
# 最新の変更を取得
|
||||
echo ""
|
||||
echo "🌐 リモートから最新の変更を取得中..."
|
||||
echo ""
|
||||
|
||||
if git pull origin $MAIN_BRANCH; then
|
||||
echo ""
|
||||
echo "✅ メインブランチの更新が完了しました!"
|
||||
echo ""
|
||||
|
||||
# 更新後の状態を表示
|
||||
echo "📊 更新後の状態:"
|
||||
echo "- ブランチ: $MAIN_BRANCH"
|
||||
echo "- 最新コミット: $(git log -1 --pretty=format:'%h - %s')"
|
||||
|
||||
# 元のブランチとの差分を表示(異なるブランチから来た場合)
|
||||
if [ "$CURRENT_BRANCH" != "$MAIN_BRANCH" ]; then
|
||||
echo ""
|
||||
echo "📝 元のブランチ ($CURRENT_BRANCH) との差分:"
|
||||
COMMITS_DIFF=$(git rev-list --count $CURRENT_BRANCH..$MAIN_BRANCH)
|
||||
if [ "$COMMITS_DIFF" -gt 0 ]; then
|
||||
echo "- $MAIN_BRANCH の方が $COMMITS_DIFF コミット進んでいます"
|
||||
else
|
||||
echo "- 差分はありません"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "💡 元のブランチに戻るには: git checkout $CURRENT_BRANCH"
|
||||
fi
|
||||
|
||||
# stashした変更を復元
|
||||
if [ "$STASH_NEEDED" = true ]; then
|
||||
echo ""
|
||||
echo "🔄 一時保存した変更を復元中..."
|
||||
if git stash pop; then
|
||||
echo "✅ 変更を復元しました"
|
||||
echo ""
|
||||
echo "📝 復元された変更:"
|
||||
git status --short
|
||||
else
|
||||
echo "⚠️ 変更の復元中にコンフリクトが発生しました"
|
||||
echo ""
|
||||
echo "💡 手動で解決してください:"
|
||||
echo "1. コンフリクトのあるファイルを編集"
|
||||
echo "2. git add <ファイル名> でステージング"
|
||||
echo "3. git stash drop で不要なstashを削除"
|
||||
echo ""
|
||||
echo "📋 stashリストを確認: git stash list"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
echo "❌ 更新中にエラーが発生しました"
|
||||
echo ""
|
||||
echo "💡 以下を確認してください:"
|
||||
echo "- インターネット接続"
|
||||
echo "- リモートリポジトリへのアクセス権限"
|
||||
echo "- コンフリクトの有無"
|
||||
|
||||
# コンフリクトがある場合
|
||||
if git status | grep -q "You have unmerged paths"; then
|
||||
echo ""
|
||||
echo "⚠️ マージコンフリクトが発生しています"
|
||||
echo ""
|
||||
echo "🔧 コンフリクトのあるファイル:"
|
||||
git diff --name-only --diff-filter=U
|
||||
echo ""
|
||||
echo "📝 解決手順:"
|
||||
echo "1. 上記のファイルを編集してコンフリクトを解決"
|
||||
echo "2. git add <ファイル名> で解決済みファイルをステージング"
|
||||
echo "3. git commit でマージを完了"
|
||||
fi
|
||||
|
||||
# エラーが発生してもstashした変更を復元
|
||||
if [ "$STASH_NEEDED" = true ]; then
|
||||
echo ""
|
||||
echo "🔄 一時保存した変更を復元中..."
|
||||
if git stash pop; then
|
||||
echo "✅ 変更を復元しました"
|
||||
else
|
||||
echo "⚠️ 変更の復元中にコンフリクトが発生しました"
|
||||
echo "📋 stashリストを確認: git stash list"
|
||||
fi
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "💡 次のステップ:"
|
||||
echo "- ブランチ一覧を確認: git branch"
|
||||
echo "- 新しいブランチを作成: git checkout -b feature/new-feature"
|
||||
echo "- 特定のブランチに切り替え: git checkout <ブランチ名>"
|
||||
```
|
||||
|
||||
## 特徴
|
||||
- **メインブランチ自動検出**: main/masterを自動的に判別
|
||||
- **自動ブランチ切り替え**: メインブランチへの自動切り替え
|
||||
- **自動stash機能**: 未コミットの変更を自動的に一時保存・復元
|
||||
- **追跡ファイル対応**: 新規ファイル(untracked)も含めてstash
|
||||
- **わかりやすい状態表示**: 更新後の状態と元のブランチとの差分を表示
|
||||
- **視覚的なフィードバック**: 絵文字を使用した進行状況の表示
|
||||
- **エラーハンドリング**: 各ステップでの適切なエラー処理とstash復元
|
||||
|
||||
## 注意事項
|
||||
- 作業中の変更は自動的にstashされ、更新後に復元されます
|
||||
- stash復元時にコンフリクトが発生した場合は手動解決が必要です
|
||||
- 異なるブランチから実行した場合、元のブランチに戻る方法を表示します
|
||||
- 更新後は必要に応じて新しいブランチを作成して作業を開始してください
|
||||
|
||||
## 関連コマンド
|
||||
- `/branch-create`: 新しいブランチを作成
|
||||
- `/branch-switch`: ブランチを切り替え
|
||||
- `/commit`: 変更をコミット
|
||||
- `/push-current`: 現在のブランチをプッシュ
|
||||
126
commands/branch-switch.md
Normal file
126
commands/branch-switch.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Branch Switch
|
||||
|
||||
指定したブランチに切り替えるカスタムコマンド。PR番号を指定することも可能。
|
||||
|
||||
```bash
|
||||
# 引数チェック
|
||||
if [ -z "$1" ]; then
|
||||
echo "📋 利用可能なブランチ一覧:"
|
||||
echo "=========================="
|
||||
|
||||
# ローカルブランチ一覧を表示
|
||||
echo ""
|
||||
echo "🏠 ローカルブランチ:"
|
||||
git branch --format=' %(if)%(HEAD)%(then)* %(else) %(end)%(refname:short) %(upstream:track)'
|
||||
|
||||
echo ""
|
||||
echo "☁️ リモートブランチ:"
|
||||
git branch -r --format=' %(refname:short)' | grep -v 'HEAD'
|
||||
|
||||
echo ""
|
||||
echo "使用方法: /branch-switch <ブランチ名 | PR番号>"
|
||||
echo "例: /branch-switch feature/new-feature"
|
||||
echo " /branch-switch main"
|
||||
echo " /branch-switch 123 (PR #123のブランチに切り替え)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
INPUT="$1"
|
||||
|
||||
# PR番号かどうかをチェック(数字のみの場合)
|
||||
if [[ "$INPUT" =~ ^[0-9]+$ ]]; then
|
||||
PR_NUMBER="$INPUT"
|
||||
echo "🔍 PR #$PR_NUMBER の情報を取得中..."
|
||||
|
||||
# GitHub CLIを使ってPR情報を取得
|
||||
if ! command -v gh &> /dev/null; then
|
||||
echo "❌ Error: GitHub CLI (gh) がインストールされていません"
|
||||
echo "インストール方法: https://cli.github.com/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# PR情報を取得
|
||||
PR_INFO=$(gh pr view "$PR_NUMBER" --json headRefName,state,mergeable 2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Error: PR #$PR_NUMBER が見つかりません"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ブランチ名を抽出
|
||||
BRANCH_NAME=$(echo "$PR_INFO" | jq -r '.headRefName')
|
||||
PR_STATE=$(echo "$PR_INFO" | jq -r '.state')
|
||||
|
||||
if [ "$PR_STATE" = "CLOSED" ] || [ "$PR_STATE" = "MERGED" ]; then
|
||||
echo "⚠️ 警告: PR #$PR_NUMBER は既に $PR_STATE されています"
|
||||
echo "ブランチ '$BRANCH_NAME' に切り替えます..."
|
||||
fi
|
||||
|
||||
echo "📋 PR #$PR_NUMBER のブランチ: $BRANCH_NAME"
|
||||
else
|
||||
BRANCH_NAME="$INPUT"
|
||||
fi
|
||||
|
||||
# 現在のブランチを取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
if [ "$CURRENT_BRANCH" = "$BRANCH_NAME" ]; then
|
||||
echo "✅ すでに '$BRANCH_NAME' ブランチにいます"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 未コミットの変更をチェック
|
||||
if ! git diff --quiet || ! git diff --staged --quiet; then
|
||||
echo "⚠️ 未コミットの変更があります:"
|
||||
git status --short
|
||||
echo ""
|
||||
echo "📦 変更をstashに自動保存して切り替えます..."
|
||||
git stash push -m "Auto-stash before switching to $BRANCH_NAME"
|
||||
STASHED=true
|
||||
fi
|
||||
|
||||
# ブランチが存在するかチェック
|
||||
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
|
||||
# ローカルブランチが存在する場合
|
||||
echo "🔄 ローカルブランチ '$BRANCH_NAME' に切り替え中..."
|
||||
git checkout "$BRANCH_NAME"
|
||||
elif git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then
|
||||
# リモートブランチのみ存在する場合
|
||||
echo "📥 リモートブランチ 'origin/$BRANCH_NAME' をチェックアウト中..."
|
||||
git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME"
|
||||
else
|
||||
# ブランチが存在しない場合
|
||||
echo "❌ Error: ブランチ '$BRANCH_NAME' が見つかりません"
|
||||
echo ""
|
||||
echo "🌱 新しいブランチ '$BRANCH_NAME' を作成中..."
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ ブランチ '$BRANCH_NAME' に切り替えました"
|
||||
|
||||
# リモートの最新情報を取得
|
||||
if git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then
|
||||
echo ""
|
||||
echo "🔄 リモートとの差分をチェック中..."
|
||||
git fetch origin "$BRANCH_NAME" --quiet
|
||||
|
||||
LOCAL=$(git rev-parse HEAD)
|
||||
REMOTE=$(git rev-parse "origin/$BRANCH_NAME" 2>/dev/null)
|
||||
|
||||
if [ "$LOCAL" != "$REMOTE" ]; then
|
||||
echo "⚠️ リモートブランチとの差分があります"
|
||||
echo " 最新の変更を取得するには: git pull"
|
||||
fi
|
||||
fi
|
||||
|
||||
# stashがある場合は通知
|
||||
if [ "$STASHED" = "true" ]; then
|
||||
echo ""
|
||||
echo "💡 stashに保存した変更を復元するには: git stash pop"
|
||||
fi
|
||||
else
|
||||
echo "❌ ブランチの切り替えに失敗しました"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
135
commands/ci-check.md
Normal file
135
commands/ci-check.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# GitHub PR CI チェックコマンド
|
||||
|
||||
現在のブランチのPRのCI状態をチェックし、失敗の詳細を取得します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/ci-check
|
||||
```
|
||||
|
||||
## 処理手順
|
||||
1. 現在のブランチ名を取得
|
||||
2. このブランチに関連するPRを検索
|
||||
3. GitHub CLIを使用してCI状態をチェック
|
||||
4. 失敗したチェックの詳細を表示
|
||||
5. 失敗したチェックのログを表示
|
||||
|
||||
## 実装
|
||||
まず、`git branch --show-current` を使用して現在のブランチを取得します。
|
||||
|
||||
### ステップ1: 現在のブランチとPRの取得
|
||||
```bash
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "🌿 現在のブランチ: $CURRENT_BRANCH"
|
||||
|
||||
# このブランチのPRを検索
|
||||
echo "🔍 ブランチに関連するPRを検索中..."
|
||||
PR_INFO=$(gh pr list --head "$CURRENT_BRANCH" --json number,title,url 2>/dev/null)
|
||||
|
||||
if [ -z "$PR_INFO" ] || [ "$PR_INFO" = "[]" ]; then
|
||||
echo "❌ 現在のブランチ ($CURRENT_BRANCH) に関連するPRが見つかりません"
|
||||
echo "💡 まずPRを作成してください: /pr-create"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PR_NUMBER=$(echo "$PR_INFO" | jq -r '.[0].number')
|
||||
PR_TITLE=$(echo "$PR_INFO" | jq -r '.[0].title')
|
||||
PR_URL=$(echo "$PR_INFO" | jq -r '.[0].url')
|
||||
|
||||
echo "📋 PR情報:"
|
||||
echo " 番号: #$PR_NUMBER"
|
||||
echo " タイトル: $PR_TITLE"
|
||||
echo " URL: $PR_URL"
|
||||
```
|
||||
|
||||
### ステップ2: CI チェック状態の取得
|
||||
```bash
|
||||
# PRのチェック状態を取得
|
||||
echo "🔍 CI チェック状態を確認中..."
|
||||
CHECK_RUNS=$(gh pr checks "$PR_NUMBER" 2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ CI チェック情報を取得できませんでした"
|
||||
echo "💡 GitHub CLIの権限を確認してください"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$CHECK_RUNS"
|
||||
```
|
||||
|
||||
### ステップ3: 失敗したチェックの詳細分析
|
||||
```bash
|
||||
# 失敗したチェックを特定
|
||||
echo "🔍 失敗したチェックの詳細を分析中..."
|
||||
|
||||
# チェック結果を解析して失敗したものを特定
|
||||
FAILED_CHECKS=$(echo "$CHECK_RUNS" | grep -E "(fail|error|✗)" || echo "")
|
||||
|
||||
if [ -z "$FAILED_CHECKS" ]; then
|
||||
echo "✅ すべてのCIチェックが成功しています!"
|
||||
echo "🎉 PRの準備が整いました"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "❌ 失敗したチェック:"
|
||||
echo "$FAILED_CHECKS"
|
||||
echo ""
|
||||
|
||||
# 失敗したワークフローの詳細ログを取得
|
||||
echo "📋 失敗の詳細ログ:"
|
||||
WORKFLOW_RUNS=$(gh run list --branch "$CURRENT_BRANCH" --json databaseId,status,conclusion,name --limit 5)
|
||||
echo "$WORKFLOW_RUNS" | jq -r '.[] | select(.conclusion == "failure") | "- \(.name): \(.conclusion)"'
|
||||
```
|
||||
|
||||
### ステップ4: 失敗の種類別分析と提案
|
||||
```bash
|
||||
# 一般的な失敗パターンを分析
|
||||
echo ""
|
||||
echo "🔧 よくある修正方法:"
|
||||
|
||||
if echo "$FAILED_CHECKS" | grep -qi "lint"; then
|
||||
echo "📝 リンティングエラー:"
|
||||
echo " - /ci-fix を実行して自動修正を試行"
|
||||
echo " - npm run lint または該当するlintコマンドを実行"
|
||||
fi
|
||||
|
||||
if echo "$FAILED_CHECKS" | grep -qi "test"; then
|
||||
echo "🧪 テストエラー:"
|
||||
echo " - ローカルでテストを実行: npm test"
|
||||
echo " - 失敗したテストを確認して修正"
|
||||
fi
|
||||
|
||||
if echo "$FAILED_CHECKS" | grep -qi "build"; then
|
||||
echo "🏗️ ビルドエラー:"
|
||||
echo " - 依存関係を確認: npm install"
|
||||
echo " - TypeScriptエラーを確認"
|
||||
fi
|
||||
|
||||
if echo "$FAILED_CHECKS" | grep -qi "security"; then
|
||||
echo "🔒 セキュリティ問題:"
|
||||
echo " - 依存関係の脆弱性を確認"
|
||||
echo " - npm audit fix を実行"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 上記の提案に従って問題を修正"
|
||||
echo "2. /ci-fix を使用して自動修正を試行"
|
||||
echo "3. 修正後に再度このコマンドで確認"
|
||||
```
|
||||
|
||||
## 表示形式
|
||||
結果を明確な形式で表示:
|
||||
- 現在のブランチと関連PR
|
||||
- 全体的なCI状態
|
||||
- 失敗したチェック名
|
||||
- エラーメッセージとログ
|
||||
- よくある修正方法の提案
|
||||
|
||||
現在のブランチにPRが存在しない場合は、まずPRを作成するよう提案します。
|
||||
|
||||
## 注意事項
|
||||
- GitHub CLIの認証が必要です
|
||||
- プライベートリポジトリでは適切な権限が必要です
|
||||
- CI システムが設定されている場合のみ有効です
|
||||
219
commands/ci-fix.md
Normal file
219
commands/ci-fix.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# GitHub PR CI 修正コマンド
|
||||
|
||||
現在のブランチのPRのCI失敗を自動的に修正します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/ci-fix
|
||||
```
|
||||
|
||||
## 処理手順
|
||||
1. まずPR CIチェックを実行して失敗を特定
|
||||
2. よくあるCI失敗パターンを分析
|
||||
3. 適切な修正を自動的に適用
|
||||
4. 可能な場合はローカルでテストを実行
|
||||
5. 修正内容の概要を表示(コミットはしない)
|
||||
|
||||
## 実装
|
||||
PR CIチェックコマンドを実行して失敗の詳細を取得することから開始します。
|
||||
|
||||
### ステップ1: CI失敗の分析
|
||||
```bash
|
||||
# まずCI状態をチェック
|
||||
echo "🔍 CI失敗を分析中..."
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
# PRの存在確認
|
||||
PR_INFO=$(gh pr list --head "$CURRENT_BRANCH" --json number 2>/dev/null)
|
||||
if [ -z "$PR_INFO" ] || [ "$PR_INFO" = "[]" ]; then
|
||||
echo "❌ 現在のブランチにPRが見つかりません"
|
||||
echo "💡 まず /pr-create でPRを作成してください"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PR_NUMBER=$(echo "$PR_INFO" | jq -r '.[0].number')
|
||||
echo "📋 PR #$PR_NUMBER のCI失敗を修正します"
|
||||
|
||||
# チェック状態を取得
|
||||
CHECK_RUNS=$(gh pr checks "$PR_NUMBER" 2>/dev/null)
|
||||
FAILED_CHECKS=$(echo "$CHECK_RUNS" | grep -E "(fail|error|✗)" || echo "")
|
||||
|
||||
if [ -z "$FAILED_CHECKS" ]; then
|
||||
echo "✅ CIに失敗はありません"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "❌ 検出された失敗:"
|
||||
echo "$FAILED_CHECKS"
|
||||
```
|
||||
|
||||
### ステップ2: 失敗の種類別自動修正
|
||||
実装する一般的なCI修正:
|
||||
|
||||
#### リンティングエラーの修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "lint"; then
|
||||
echo "📝 リンティングエラーを修正中..."
|
||||
|
||||
# よくあるリンターを実行
|
||||
if [ -f "package.json" ]; then
|
||||
echo "🔧 npm run lint --fix を実行中..."
|
||||
npm run lint --fix 2>/dev/null || echo "npm lintコマンドが見つかりません"
|
||||
fi
|
||||
|
||||
if command -v ruff >/dev/null 2>&1; then
|
||||
echo "🔧 ruff check --fix を実行中..."
|
||||
ruff check --fix .
|
||||
fi
|
||||
|
||||
if command -v golangci-lint >/dev/null 2>&1; then
|
||||
echo "🔧 golangci-lint を実行中..."
|
||||
golangci-lint run --fix
|
||||
fi
|
||||
|
||||
echo "✅ リンティング修正完了"
|
||||
fi
|
||||
```
|
||||
|
||||
#### 型エラーの修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "type\|typescript"; then
|
||||
echo "🏷️ 型エラーを分析中..."
|
||||
|
||||
if [ -f "tsconfig.json" ]; then
|
||||
echo "🔧 TypeScript型チェックを実行中..."
|
||||
npx tsc --noEmit 2>&1 | head -20
|
||||
echo ""
|
||||
echo "💡 型エラーの修正が必要です。上記のエラーを確認してください。"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
#### テスト失敗の修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "test"; then
|
||||
echo "🧪 テスト失敗を分析中..."
|
||||
|
||||
# テストをローカルで実行
|
||||
if [ -f "package.json" ]; then
|
||||
echo "🔧 npm test を実行中..."
|
||||
npm test 2>&1 | tail -20
|
||||
elif [ -f "pytest.ini" ] || [ -f "pyproject.toml" ]; then
|
||||
echo "🔧 pytest を実行中..."
|
||||
python -m pytest -v --tb=short 2>&1 | tail -20
|
||||
elif [ -f "go.mod" ]; then
|
||||
echo "🔧 go test を実行中..."
|
||||
go test ./... -v 2>&1 | tail -20
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "💡 テスト失敗の詳細を確認して手動で修正してください"
|
||||
fi
|
||||
```
|
||||
|
||||
#### ビルド失敗の修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "build"; then
|
||||
echo "🏗️ ビルドエラーを修正中..."
|
||||
|
||||
# 依存関係の更新
|
||||
if [ -f "package.json" ]; then
|
||||
echo "📦 依存関係を更新中..."
|
||||
npm install
|
||||
|
||||
echo "🔧 ビルドを試行中..."
|
||||
npm run build 2>&1 | tail -20
|
||||
fi
|
||||
|
||||
if [ -f "requirements.txt" ]; then
|
||||
echo "📦 Python依存関係を更新中..."
|
||||
pip install -r requirements.txt
|
||||
fi
|
||||
|
||||
if [ -f "go.mod" ]; then
|
||||
echo "📦 Go依存関係を更新中..."
|
||||
go mod tidy
|
||||
go build ./...
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
#### セキュリティ問題の修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "security"; then
|
||||
echo "🔒 セキュリティ問題を修正中..."
|
||||
|
||||
if [ -f "package.json" ]; then
|
||||
echo "🔧 npm audit fix を実行中..."
|
||||
npm audit fix
|
||||
fi
|
||||
|
||||
if [ -f "requirements.txt" ]; then
|
||||
echo "🔧 pip-audit を実行中..."
|
||||
pip-audit --fix 2>/dev/null || echo "pip-audit が利用できません"
|
||||
fi
|
||||
|
||||
echo "✅ セキュリティ修正完了"
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ3: 修正の検証と結果表示
|
||||
```bash
|
||||
# 修正内容を確認
|
||||
echo ""
|
||||
echo "📝 修正内容の確認:"
|
||||
git status --porcelain
|
||||
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "✅ 修正が適用されました"
|
||||
|
||||
# ローカルテストを実行(可能な場合)
|
||||
echo "🧪 修正の検証中..."
|
||||
if [ -f "package.json" ]; then
|
||||
npm test 2>/dev/null && echo "✅ テスト成功" || echo "⚠️ テストで問題が残っています"
|
||||
fi
|
||||
|
||||
# 変更の詳細を表示
|
||||
echo ""
|
||||
echo "📋 修正されたファイル:"
|
||||
git diff --name-only
|
||||
echo ""
|
||||
echo "📊 変更統計:"
|
||||
git diff --stat
|
||||
echo ""
|
||||
echo "✅ CI修正が適用されました!"
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 'git diff' で変更内容を詳細確認"
|
||||
echo "2. 追加のテストが必要な場合は実行"
|
||||
echo "3. /commit-create でコミット作成"
|
||||
echo "4. /push-current でリモートにpush"
|
||||
echo "5. 数分後に /ci-check で状態を確認"
|
||||
else
|
||||
echo "ℹ️ 自動修正可能な問題が見つかりませんでした"
|
||||
echo "💡 手動での修正が必要です"
|
||||
fi
|
||||
```
|
||||
|
||||
## 各失敗タイプの修正方法
|
||||
|
||||
### 1. **リンティングエラー**: リンターを実行して自動修正
|
||||
### 2. **型エラー**: TypeScript/型の問題を分析して修正
|
||||
### 3. **テスト失敗**: テストをローカルで実行して失敗したテストを修正
|
||||
### 4. **ビルド失敗**: 依存関係とビルド設定をチェック
|
||||
### 5. **セキュリティ問題**: 依存関係を更新してセキュリティ脆弱性を修正
|
||||
|
||||
各失敗タイプについて:
|
||||
1. エラーメッセージを解析して問題を理解
|
||||
2. 利用可能なツールを使用して適切な修正を適用
|
||||
3. 可能な場合はローカルで修正を検証
|
||||
4. 修正内容を表示して次のステップを案内
|
||||
|
||||
修正後は、ユーザーが手動で内容を確認してからコミット・pushできるようになります。
|
||||
|
||||
## 注意事項
|
||||
- すべてのCI失敗が自動修正できるわけではありません
|
||||
- 複雑なロジックエラーは手動での修正が必要です
|
||||
- 修正後は必ずローカルでテストを実行して検証してください
|
||||
- 修正内容を確認してから /commit-create でコミットしてください
|
||||
- セキュリティ関連の修正は慎重に確認してください
|
||||
381
commands/commit-split.md
Normal file
381
commands/commit-split.md
Normal file
@@ -0,0 +1,381 @@
|
||||
# コミット分割コマンド
|
||||
|
||||
Gitの差分をもとに適切にコミットを分割します。ファイル単位や機能単位で論理的にコミットを分けることで、レビューしやすく意味のあるコミット履歴を作成します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/commit-split [ベースブランチ] [分割方式]
|
||||
```
|
||||
|
||||
### パラメータ
|
||||
- `ベースブランチ`: 比較対象のブランチ(省略時は`master`または`main`を自動検出)
|
||||
- `分割方式`: `file`(ファイル単位)、`feature`(機能単位)、`interactive`(インタラクティブ)
|
||||
|
||||
## 処理手順
|
||||
1. 現在の変更状況を確認
|
||||
2. 差分の分析と分割方針の決定
|
||||
3. インタラクティブな分割実行
|
||||
4. 各コミットの作成と確認
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: 初期状態の確認
|
||||
```bash
|
||||
# 作業ディレクトリの状態を確認
|
||||
echo "📊 現在の作業状況を確認中..."
|
||||
git status --porcelain
|
||||
|
||||
# ステージされていない変更があるかチェック
|
||||
UNSTAGED_CHANGES=$(git diff --name-only)
|
||||
STAGED_CHANGES=$(git diff --cached --name-only)
|
||||
|
||||
if [ -n "$UNSTAGED_CHANGES" ] || [ -n "$STAGED_CHANGES" ]; then
|
||||
echo "⚠️ 未コミットの変更があります"
|
||||
echo "📝 ステージされていない変更: $(echo "$UNSTAGED_CHANGES" | wc -l) ファイル"
|
||||
echo "📝 ステージされた変更: $(echo "$STAGED_CHANGES" | wc -l) ファイル"
|
||||
else
|
||||
echo "✅ 作業ディレクトリはクリーンです"
|
||||
exit 0
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ2: ベースブランチの決定
|
||||
```bash
|
||||
# ベースブランチの自動検出または指定
|
||||
BASE_BRANCH="${1:-}"
|
||||
if [ -z "$BASE_BRANCH" ]; then
|
||||
if git show-ref --verify --quiet refs/heads/master; then
|
||||
BASE_BRANCH="master"
|
||||
elif git show-ref --verify --quiet refs/heads/main; then
|
||||
BASE_BRANCH="main"
|
||||
else
|
||||
echo "❌ ベースブランチを特定できません。明示的に指定してください。"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "🎯 ベースブランチ: $BASE_BRANCH"
|
||||
|
||||
# ベースブランチとの差分を確認
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "🌿 現在のブランチ: $CURRENT_BRANCH"
|
||||
```
|
||||
|
||||
### ステップ3: 差分の分析
|
||||
```bash
|
||||
# 変更されたファイルの一覧と統計
|
||||
echo "📈 差分の分析中..."
|
||||
CHANGED_FILES=$(git diff --name-only $BASE_BRANCH..HEAD 2>/dev/null || git diff --name-only)
|
||||
|
||||
if [ -z "$CHANGED_FILES" ]; then
|
||||
echo "📝 ベースブランチとの差分がありません"
|
||||
# 作業ディレクトリの変更のみ処理
|
||||
CHANGED_FILES=$(git diff --name-only)
|
||||
if [ -z "$CHANGED_FILES" ]; then
|
||||
CHANGED_FILES=$(git diff --cached --name-only)
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "📁 変更されたファイル一覧:"
|
||||
echo "$CHANGED_FILES" | nl
|
||||
|
||||
# ファイルタイプ別の分類
|
||||
DOCS_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(md|txt|rst)$' || true)
|
||||
CONFIG_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(json|yaml|yml|toml|ini|conf)$' || true)
|
||||
CODE_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(js|ts|py|go|rs|java|c|cpp|php|rb)$' || true)
|
||||
TEST_FILES=$(echo "$CHANGED_FILES" | grep -E '(test|spec)\.' || true)
|
||||
|
||||
echo ""
|
||||
echo "📊 ファイルタイプ別統計:"
|
||||
[ -n "$DOCS_FILES" ] && echo "📖 ドキュメント: $(echo "$DOCS_FILES" | wc -l) ファイル"
|
||||
[ -n "$CONFIG_FILES" ] && echo "⚙️ 設定ファイル: $(echo "$CONFIG_FILES" | wc -l) ファイル"
|
||||
[ -n "$CODE_FILES" ] && echo "💻 コードファイル: $(echo "$CODE_FILES" | wc -l) ファイル"
|
||||
[ -n "$TEST_FILES" ] && echo "🧪 テストファイル: $(echo "$TEST_FILES" | wc -l) ファイル"
|
||||
```
|
||||
|
||||
### ステップ4: 分割方式の決定
|
||||
```bash
|
||||
SPLIT_MODE="${2:-file}"
|
||||
|
||||
case "$SPLIT_MODE" in
|
||||
"file")
|
||||
echo "📂 ファイル単位での分割を実行します"
|
||||
commit_by_file
|
||||
;;
|
||||
"feature")
|
||||
echo "🎯 機能単位での分割を実行します"
|
||||
commit_by_feature
|
||||
;;
|
||||
"interactive"|*)
|
||||
echo "🤝 インタラクティブ分割を実行します"
|
||||
commit_interactive
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
### ステップ5: ファイル単位分割の実装
|
||||
```bash
|
||||
commit_by_file() {
|
||||
echo "$CHANGED_FILES" | while read -r file; do
|
||||
if [ -n "$file" ]; then
|
||||
echo ""
|
||||
echo "📝 処理中: $file"
|
||||
|
||||
# ファイルの変更内容を表示
|
||||
git diff --stat "$file" 2>/dev/null || git diff --cached --stat "$file" 2>/dev/null || true
|
||||
|
||||
# コミットメッセージの自動生成
|
||||
FILE_EXT="${file##*.}"
|
||||
DIR_NAME=$(dirname "$file")
|
||||
FILE_NAME=$(basename "$file")
|
||||
|
||||
# ファイルタイプに基づいたプレフィックス
|
||||
if echo "$file" | grep -q -E '\.(md|txt|rst)$'; then
|
||||
PREFIX="docs"
|
||||
elif echo "$file" | grep -q -E '\.(json|yaml|yml|toml|ini|conf)$'; then
|
||||
PREFIX="config"
|
||||
elif echo "$file" | grep -q -E '(test|spec)\.'; then
|
||||
PREFIX="test"
|
||||
else
|
||||
PREFIX="feat"
|
||||
fi
|
||||
|
||||
COMMIT_MSG="$PREFIX: update $FILE_NAME"
|
||||
|
||||
# 自動でコミット(確認なし)
|
||||
echo "💬 提案されたコミットメッセージ: $COMMIT_MSG"
|
||||
git add "$file"
|
||||
git commit -m "$COMMIT_MSG"
|
||||
echo "✅ コミット完了: $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
### ステップ6: 機能単位分割の実装
|
||||
```bash
|
||||
commit_by_feature() {
|
||||
# ディレクトリ構造に基づいた機能別グループ化
|
||||
echo "🔍 機能別にファイルをグループ化中..."
|
||||
|
||||
# ディレクトリごとにファイルをグループ化
|
||||
DIRECTORIES=$(echo "$CHANGED_FILES" | xargs dirname | sort | uniq)
|
||||
|
||||
echo "$DIRECTORIES" | while read -r dir; do
|
||||
if [ -n "$dir" ]; then
|
||||
DIR_FILES=$(echo "$CHANGED_FILES" | grep "^$dir/")
|
||||
|
||||
if [ -n "$DIR_FILES" ]; then
|
||||
echo ""
|
||||
echo "📁 ディレクトリ: $dir"
|
||||
echo "$DIR_FILES" | sed 's/^/ - /'
|
||||
|
||||
# ディレクトリ名に基づいたコミットメッセージ
|
||||
case "$dir" in
|
||||
"src"|"lib"|"app")
|
||||
PREFIX="feat"
|
||||
;;
|
||||
"test"|"tests"|"__tests__")
|
||||
PREFIX="test"
|
||||
;;
|
||||
"docs"|"doc")
|
||||
PREFIX="docs"
|
||||
;;
|
||||
"config"|".github")
|
||||
PREFIX="config"
|
||||
;;
|
||||
*)
|
||||
PREFIX="update"
|
||||
;;
|
||||
esac
|
||||
|
||||
COMMIT_MSG="$PREFIX: update $dir module"
|
||||
|
||||
echo "💬 提案されたコミットメッセージ: $COMMIT_MSG"
|
||||
echo "$DIR_FILES" | xargs git add
|
||||
git commit -m "$COMMIT_MSG"
|
||||
echo "✅ コミット完了: $dir"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
```
|
||||
|
||||
### ステップ7: インタラクティブ分割の実装
|
||||
```bash
|
||||
commit_interactive() {
|
||||
echo "🎮 自動モードでコミットを分割します"
|
||||
|
||||
# 現在の状態を確認
|
||||
REMAINING_UNSTAGED=$(git diff --name-only)
|
||||
REMAINING_STAGED=$(git diff --cached --name-only)
|
||||
|
||||
if [ -z "$REMAINING_UNSTAGED" ] && [ -z "$REMAINING_STAGED" ]; then
|
||||
echo "📝 変更がありません"
|
||||
return
|
||||
fi
|
||||
|
||||
# 全ファイルをステージして一度にコミット
|
||||
git add .
|
||||
commit_staged_changes
|
||||
|
||||
echo "🎉 すべての変更が処理されました!"
|
||||
}
|
||||
|
||||
select_files_for_staging() {
|
||||
ALL_CHANGED=$(git status --porcelain | awk '{print $2}')
|
||||
if [ -z "$ALL_CHANGED" ]; then
|
||||
echo "📝 変更されたファイルがありません"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "📁 変更されたファイル一覧:"
|
||||
echo "$ALL_CHANGED" | nl
|
||||
echo ""
|
||||
|
||||
# 全ファイルを自動でステージ
|
||||
echo "$ALL_CHANGED" | while read -r file; do
|
||||
if [ -n "$file" ]; then
|
||||
git add "$file"
|
||||
echo "✅ ステージ完了: $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
commit_staged_changes() {
|
||||
STAGED=$(git diff --cached --name-only)
|
||||
if [ -z "$STAGED" ]; then
|
||||
echo "📦 ステージされた変更がありません"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "📦 ステージされたファイル:"
|
||||
echo "$STAGED" | sed 's/^/ - /'
|
||||
echo ""
|
||||
|
||||
# 自動でコミット
|
||||
commit_msg="update: staged changes"
|
||||
git commit -m "$commit_msg"
|
||||
echo "✅ コミット完了!"
|
||||
}
|
||||
|
||||
show_diff_summary() {
|
||||
echo "📊 変更サマリー:"
|
||||
git diff --stat
|
||||
echo ""
|
||||
git diff --cached --stat
|
||||
echo ""
|
||||
# 詳細な差分を自動的に表示
|
||||
echo "📖 詳細な差分:"
|
||||
git diff
|
||||
git diff --cached
|
||||
}
|
||||
|
||||
auto_push_changes() {
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
echo "📤 リモートブランチにプッシュ中..."
|
||||
|
||||
# リモートブランチが存在するかチェック
|
||||
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
|
||||
# リモートブランチが存在する場合は通常のpush
|
||||
git push
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ プッシュ完了: $CURRENT_BRANCH"
|
||||
else
|
||||
echo "⚠️ プッシュでエラーが発生しました"
|
||||
fi
|
||||
else
|
||||
# リモートブランチが存在しない場合は -u オプション付きでpush
|
||||
git push -u origin "$CURRENT_BRANCH"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 新しいブランチを作成してプッシュ完了: $CURRENT_BRANCH"
|
||||
else
|
||||
echo "⚠️ プッシュでエラーが発生しました"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
show_help() {
|
||||
echo "📚 コミット分割ヘルプ"
|
||||
echo ""
|
||||
echo "🎯 目的: 大きな変更を論理的に分割して複数のコミットに分ける"
|
||||
echo ""
|
||||
echo "💡 推奨される分割方針:"
|
||||
echo " - 📁 ファイルタイプ別(設定、ドキュメント、コード、テスト)"
|
||||
echo " - 🎯 機能別(新機能、バグ修正、リファクタリング)"
|
||||
echo " - 📦 影響範囲別(フロントエンド、バックエンド、DB)"
|
||||
echo ""
|
||||
echo "🔧 便利なGitコマンド:"
|
||||
echo " - git add -p : パッチ単位での選択的ステージング"
|
||||
echo " - git diff --cached : ステージされた変更の確認"
|
||||
echo " - git reset <file> : ファイルのアンステージ"
|
||||
echo " - git status : 現在の状態確認"
|
||||
echo ""
|
||||
echo "📤 プッシュ機能:"
|
||||
echo " - 各コミット後に個別でプッシュするか選択可能"
|
||||
echo " - 最終処理で全てのコミットを一括プッシュ"
|
||||
}
|
||||
```
|
||||
|
||||
### ステップ8: 完了処理とプッシュ
|
||||
```bash
|
||||
# 最終確認と統計
|
||||
echo ""
|
||||
echo "🎉 コミット分割が完了しました!"
|
||||
echo ""
|
||||
echo "📈 作成されたコミット:"
|
||||
git log --oneline -10
|
||||
|
||||
echo ""
|
||||
echo "📤 自動プッシュを実行します..."
|
||||
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
# リモートブランチが存在するかチェック
|
||||
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
|
||||
# リモートブランチが存在する場合は通常のpush
|
||||
git push
|
||||
echo "✅ プッシュ完了: $CURRENT_BRANCH"
|
||||
else
|
||||
# リモートブランチが存在しない場合は -u オプション付きでpush
|
||||
git push -u origin "$CURRENT_BRANCH"
|
||||
echo "✅ 新しいブランチを作成してプッシュ完了: $CURRENT_BRANCH"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🚀 すべてのコミットがリモートに反映されました!"
|
||||
```
|
||||
|
||||
## 重要なルール
|
||||
- **段階的なコミット**: 関連する変更をまとめて、レビューしやすい単位でコミット
|
||||
- **意味のあるメッセージ**: 各コミットが何を変更したかを明確に記述
|
||||
- **ファイルタイプの考慮**: 設定ファイル、ドキュメント、コード、テストを適切に分離
|
||||
- **レビュー性の向上**: 1つのコミットで1つの論理的変更を実現
|
||||
- **自動プッシュ**: 各コミット後にプッシュ選択可能、最終的に全コミットをリモートに反映
|
||||
|
||||
## 使用例
|
||||
|
||||
### ファイル単位での分割
|
||||
```bash
|
||||
/commit-split master file
|
||||
```
|
||||
|
||||
### 機能単位での分割
|
||||
```bash
|
||||
/commit-split main feature
|
||||
```
|
||||
|
||||
### インタラクティブ分割
|
||||
```bash
|
||||
/commit-split
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
- 実行前に重要な変更はバックアップを取ってください
|
||||
- `git add -p` を使用する際は、パッチの内容をよく確認してください
|
||||
- 各コミット後にプッシュするかどうかを選択できます
|
||||
- 最終的にすべてのコミットがリモートに反映されます
|
||||
- リモートにプッシュ済みのコミットは分割しないでください
|
||||
72
commands/commit-staged.md
Normal file
72
commands/commit-staged.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# /commit-staged
|
||||
|
||||
## 概要
|
||||
stageされたファイルのみをコミットするためのコマンドです。適切なコミットメッセージを自動生成し、安全にコミットを実行します。
|
||||
|
||||
## 動作
|
||||
|
||||
1. `git status`でstageされたファイルを確認
|
||||
2. stageされたファイルがない場合は警告を表示して終了
|
||||
3. `git diff --cached`でstageされた変更内容を確認
|
||||
4. 最近のコミットメッセージを参照してスタイルを把握
|
||||
5. 変更内容に基づいて適切なコミットメッセージを生成
|
||||
6. コミットを実行
|
||||
7. コミット結果を確認
|
||||
|
||||
## 実装手順
|
||||
|
||||
### ステップ1: 事前チェック
|
||||
```bash
|
||||
# stageされたファイルを確認
|
||||
git status --porcelain | grep "^[MADRCU]"
|
||||
```
|
||||
- stageされたファイルがない場合は終了
|
||||
- unstageされた変更があっても無視(stageされたもののみを対象)
|
||||
|
||||
### ステップ2: 変更内容の分析
|
||||
```bash
|
||||
# stageされた変更の詳細を取得
|
||||
git diff --cached
|
||||
# 最近のコミットメッセージのスタイルを確認
|
||||
git log --oneline -10
|
||||
```
|
||||
|
||||
### ステップ3: コミットメッセージの生成
|
||||
変更内容を分析して以下の形式でメッセージを生成:
|
||||
- **feat**: 新機能の追加
|
||||
- **fix**: バグ修正
|
||||
- **refactor**: リファクタリング
|
||||
- **docs**: ドキュメントの更新
|
||||
- **style**: コードスタイルの修正
|
||||
- **test**: テストの追加・修正
|
||||
- **chore**: その他の変更
|
||||
|
||||
### ステップ4: コミット実行
|
||||
```bash
|
||||
# HEREDOCを使用してコミットメッセージを適用
|
||||
git commit -m "$(cat <<'EOF'
|
||||
[生成されたコミットメッセージ]
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
### ステップ5: 結果確認
|
||||
```bash
|
||||
# コミット結果を確認
|
||||
git status
|
||||
git log --oneline -1
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
- stageされていないファイルは含まれません
|
||||
- 機密情報が含まれていないかチェックします
|
||||
- プリコミットフックが失敗した場合は再試行を提案します
|
||||
- pushは自動実行しません(ユーザーの明示的な指示を待つ)
|
||||
- 空のコミットは作成しません
|
||||
|
||||
## 使用例
|
||||
```
|
||||
/commit-staged
|
||||
```
|
||||
|
||||
このコマンドにより、stageされたファイルのみが適切なコミットメッセージと共にコミットされます。
|
||||
23
commands/commit.md
Normal file
23
commands/commit.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# commitメッセージを作成
|
||||
|
||||
現在の変更をコミットし、自動的にリモートブランチにプッシュします。
|
||||
|
||||
## 実行手順
|
||||
1. `git status`でファイルを確認
|
||||
2. [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)に従ってコミットを実行
|
||||
3. 自動的に`git push`でリモートブランチに反映
|
||||
|
||||
## 形式の指定
|
||||
- type(scope): subject の形式に従う
|
||||
- タイトルは50文字以内、本文は72文字程度で改行
|
||||
- 動詞は原形を使用(add, fix, updateなど)
|
||||
- scope は原則記述するが、適切なものがない場合は省略可
|
||||
- コミットメッセージは小文字で始める
|
||||
|
||||
## 実装とテストが含まれる場合の優先ルール
|
||||
- 実装とテストコードが含まれている場合、typeはtestよりもfeat/fixを優先する
|
||||
|
||||
## プッシュの動作
|
||||
- コミット成功後、自動的に`git push`を実行
|
||||
- ブランチがリモートに存在しない場合は`git push -u origin <branch_name>`を実行
|
||||
- プッシュエラー時は適切なエラーメッセージを表示
|
||||
225
commands/dp-ci-fix.md
Normal file
225
commands/dp-ci-fix.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# Dependabot PR CI修正コマンド
|
||||
|
||||
DependabotのプルリクエストでCIエラーが発生しているものを自動的に修正します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/dp-ci-fix
|
||||
```
|
||||
|
||||
## 処理手順
|
||||
1. Dependabotが作成したPR一覧を取得
|
||||
2. CIが失敗しているPRを特定
|
||||
3. 各失敗PRに対してClaudeが修正を実行
|
||||
4. 修正結果をレポート
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: Dependabot PRとCIステータスの取得
|
||||
```bash
|
||||
# GitHub CLIの確認
|
||||
if ! command -v gh &> /dev/null; then
|
||||
echo "❌ Error: GitHub CLI (gh) がインストールされていません"
|
||||
echo "インストール方法: https://cli.github.com/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🤖 Dependabot PRのCIエラーを確認中..."
|
||||
echo "========================================"
|
||||
|
||||
# Dependabotが作成したPRを取得
|
||||
DEPENDABOT_PRS=$(gh pr list --state open --author "app/dependabot" --json number,title,headRefName,statusCheckRollup)
|
||||
|
||||
if [ "$DEPENDABOT_PRS" = "[]" ]; then
|
||||
echo "✨ Dependabotのオープン中のPRはありません"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# CIが失敗しているPRをフィルタリング
|
||||
FAILED_PRS=$(echo "$DEPENDABOT_PRS" | jq -r '.[] | select(.statusCheckRollup != null) | select(.statusCheckRollup | map(select(.conclusion == "FAILURE")) | length > 0) | @json')
|
||||
|
||||
if [ -z "$FAILED_PRS" ]; then
|
||||
echo "✅ CIエラーのあるDependabot PRはありません"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FAILED_COUNT=$(echo "$FAILED_PRS" | wc -l | tr -d ' ')
|
||||
echo "❌ CIエラーが見つかりました: ${FAILED_COUNT}件のPR"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### ステップ2: 各失敗PRの修正
|
||||
```bash
|
||||
# 元のブランチを保存
|
||||
ORIGINAL_BRANCH=$(git branch --show-current)
|
||||
echo "💾 元のブランチ: $ORIGINAL_BRANCH"
|
||||
echo ""
|
||||
|
||||
# 修正結果を記録
|
||||
SUCCESS_PRS=()
|
||||
FAILED_FIX_PRS=()
|
||||
|
||||
# 各PRを処理
|
||||
echo "$FAILED_PRS" | while IFS= read -r pr_json; do
|
||||
PR_NUMBER=$(echo "$pr_json" | jq -r '.number')
|
||||
PR_TITLE=$(echo "$pr_json" | jq -r '.title')
|
||||
PR_BRANCH=$(echo "$pr_json" | jq -r '.headRefName')
|
||||
|
||||
echo "🔧 PR #${PR_NUMBER} を修正中: ${PR_TITLE}"
|
||||
echo " ブランチ: ${PR_BRANCH}"
|
||||
|
||||
# ブランチをチェックアウト
|
||||
if ! git fetch origin "$PR_BRANCH" 2>/dev/null; then
|
||||
echo " ❌ ブランチの取得に失敗"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}")
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! git checkout "$PR_BRANCH" 2>/dev/null; then
|
||||
echo " ❌ チェックアウトに失敗"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}")
|
||||
continue
|
||||
fi
|
||||
|
||||
# 依存関係の再インストール(Claudeがリポジトリを確認して適切なコマンドを実行)
|
||||
echo " 📦 依存関係を再インストール中..."
|
||||
echo " ℹ️ Claudeがリポジトリの構成を確認して適切なインストールコマンドを実行します"
|
||||
|
||||
# CI失敗の種類を確認
|
||||
FAILED_CHECKS=$(gh pr checks "$PR_NUMBER" 2>/dev/null | grep -E "(fail|error|✗)" || echo "")
|
||||
|
||||
echo " 失敗したチェック:"
|
||||
echo "$FAILED_CHECKS" | while IFS= read -r check; do
|
||||
echo " - $check"
|
||||
done
|
||||
|
||||
# Claudeに修正を依頼
|
||||
echo " 🤖 Claudeに修正を依頼します"
|
||||
echo ""
|
||||
echo " 失敗したチェック内容に基づいて、以下の修正を行ってください:"
|
||||
echo "$FAILED_CHECKS"
|
||||
echo ""
|
||||
echo " ⚠️ 重要な制約:"
|
||||
echo " - lintエラー: できる限りignoreコメントを使わず実際のコードを修正すること"
|
||||
echo " - リポジトリの構成を確認して適切な修正方法を選択すること"
|
||||
echo ""
|
||||
|
||||
# メジャーバージョンアップの確認
|
||||
PR_DIFF=$(gh pr diff "$PR_NUMBER" 2>/dev/null || echo "")
|
||||
if echo "$PR_DIFF" | grep -qE '^\-.*"[^"]+": *"[0-9]+\.[0-9]+'; then
|
||||
OLD_VER=$(echo "$PR_DIFF" | grep -E '^\-.*"[^"]+": *"[0-9]+\.[0-9]+' | head -1 | sed -E 's/.*"([0-9]+)\..*/\1/')
|
||||
NEW_VER=$(echo "$PR_DIFF" | grep -E '^\+.*"[^"]+": *"[0-9]+\.[0-9]+' | head -1 | sed -E 's/.*"([0-9]+)\..*/\1/')
|
||||
PACKAGE=$(echo "$PR_DIFF" | grep -E '^\+.*"[^"]+": *"[0-9]+\.[0-9]+' | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
|
||||
if [ "$OLD_VER" != "$NEW_VER" ] && [ -n "$PACKAGE" ]; then
|
||||
echo " ⚠️ メジャーバージョンアップ: $PACKAGE ($OLD_VER.x → $NEW_VER.x)"
|
||||
echo " 🔍 マイグレーションガイドを確認中..."
|
||||
/gemini-search "$PACKAGE version $NEW_VER migration guide" 2>/dev/null | head -10 || true
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
# 変更があればコミット
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo " 💾 変更をコミット中..."
|
||||
|
||||
git add .
|
||||
git commit -m "fix: CI errors for dependabot PR
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# プッシュ
|
||||
echo " 📤 リモートにプッシュ中..."
|
||||
if git push origin "$PR_BRANCH"; then
|
||||
echo " ✅ プッシュ完了"
|
||||
|
||||
# CI結果を待機して確認
|
||||
echo " ⏳ CI実行を待機中(最大5分)..."
|
||||
sleep 30 # 初回実行開始を待つ
|
||||
|
||||
TIMEOUT=270 # 残り4分30秒
|
||||
INTERVAL=30
|
||||
CI_PASSED=false
|
||||
|
||||
while [ $TIMEOUT -gt 0 ]; do
|
||||
CI_STATUS=$(gh pr checks "$PR_NUMBER" --json state,conclusion 2>/dev/null || echo "")
|
||||
|
||||
# すべてのチェックが完了しているか確認
|
||||
if echo "$CI_STATUS" | jq -e 'all(.state == "COMPLETED")' >/dev/null 2>&1; then
|
||||
# すべて成功しているか確認
|
||||
if echo "$CI_STATUS" | jq -e 'all(.conclusion == "SUCCESS")' >/dev/null 2>&1; then
|
||||
echo " ✅ CI成功"
|
||||
CI_PASSED=true
|
||||
SUCCESS_PRS+=("#${PR_NUMBER}: ${PR_TITLE} ✓")
|
||||
break
|
||||
else
|
||||
echo " ❌ CI失敗"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}: ${PR_TITLE} (CI失敗)")
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep $INTERVAL
|
||||
TIMEOUT=$((TIMEOUT - INTERVAL))
|
||||
done
|
||||
|
||||
if [ "$CI_PASSED" = false ] && [ $TIMEOUT -le 0 ]; then
|
||||
echo " ⏱️ CI確認タイムアウト"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}: ${PR_TITLE} (CI確認中)")
|
||||
fi
|
||||
else
|
||||
echo " ❌ プッシュに失敗"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}: ${PR_TITLE}")
|
||||
fi
|
||||
else
|
||||
echo " ℹ️ 自動修正可能な変更なし"
|
||||
FAILED_FIX_PRS+=("#${PR_NUMBER}: ${PR_TITLE} (要手動修正)")
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
# 元のブランチに戻る
|
||||
echo "🔙 元のブランチに戻ります: $ORIGINAL_BRANCH"
|
||||
git checkout "$ORIGINAL_BRANCH"
|
||||
```
|
||||
|
||||
### ステップ4: 結果レポート
|
||||
```bash
|
||||
echo ""
|
||||
echo "📊 修正結果レポート"
|
||||
echo "========================================"
|
||||
|
||||
if [ ${#SUCCESS_PRS[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
echo "✅ 修正成功 (${#SUCCESS_PRS[@]}件):"
|
||||
for pr in "${SUCCESS_PRS[@]}"; do
|
||||
echo " - $pr"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${#FAILED_FIX_PRS[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
echo "❌ 修正失敗または手動対応が必要 (${#FAILED_FIX_PRS[@]}件):"
|
||||
for pr in "${FAILED_FIX_PRS[@]}"; do
|
||||
echo " - $pr"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 数分待ってCIが再実行されるのを確認"
|
||||
echo "2. 手動対応が必要なPRは個別に確認"
|
||||
echo "3. /pr-list でPRの状態を確認"
|
||||
echo ""
|
||||
echo "✅ Dependabot PR CI修正処理が完了しました"
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
- GitHub CLIが必要です
|
||||
- Claudeがリポジトリを確認して修正方法を判断します
|
||||
- すべてのエラーが自動修正できるわけではありません
|
||||
- 複雑なエラーは手動での修正が必要です
|
||||
- 修正後、CIの再実行には数分かかる場合があります
|
||||
127
commands/gemini-search.md
Normal file
127
commands/gemini-search.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Gemini ウェブ検索コマンド
|
||||
|
||||
Gemini AIを使用してGoogle検索を実行し、結果を要約して表示します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/gemini-search [検索クエリ]
|
||||
```
|
||||
|
||||
## 例
|
||||
```bash
|
||||
/gemini-search "Claude Code の最新機能"
|
||||
/gemini-search "TypeScript 5.0 新機能"
|
||||
/gemini-search "Next.js App Router ベストプラクティス"
|
||||
```
|
||||
|
||||
## 実装
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# gemini-cliがインストールされているかチェック
|
||||
if ! command -v gemini &> /dev/null; then
|
||||
echo "❌ gemini-cliがインストールされていません"
|
||||
echo ""
|
||||
echo "📦 インストール手順:"
|
||||
echo "npm install -g @google/gemini-cli"
|
||||
echo ""
|
||||
echo "🔑 初期化手順:"
|
||||
echo "gemini"
|
||||
echo ""
|
||||
echo "詳細: https://zenn.dev/mizchi/articles/gemini-cli-for-google-search"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 検索クエリが指定されているかチェック
|
||||
if [ -z "$1" ]; then
|
||||
echo "❌ 検索クエリを指定してください"
|
||||
echo ""
|
||||
echo "使用方法: /gemini-search [検索クエリ]"
|
||||
echo "例: /gemini-search \"Claude Code の最新機能\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 検索クエリを組み立て
|
||||
SEARCH_QUERY="$*"
|
||||
echo "🔍 検索中: $SEARCH_QUERY"
|
||||
echo ""
|
||||
|
||||
# 一時ファイルで結果をキャプチャ
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
# Gemini AIでウェブ検索を実行
|
||||
SEARCH_PROMPT="Webで「$SEARCH_QUERY」について調べて、以下の形式で回答してください:
|
||||
|
||||
## 🔍 検索結果の要約
|
||||
[検索結果の主要なポイントを3-5個の箇条書きで]
|
||||
|
||||
## 📝 詳細情報
|
||||
[重要な詳細情報や具体的な内容]
|
||||
|
||||
## 🔗 参考リンク
|
||||
[関連する重要なURLがあれば記載]
|
||||
|
||||
## 📅 最新性
|
||||
[情報の時期や最新性について]
|
||||
|
||||
回答は日本語で、読みやすく整理して提供してください。"
|
||||
|
||||
echo "🤖 Gemini AIで検索結果を分析中..."
|
||||
|
||||
# 検索を実行し、結果を一時ファイルに保存
|
||||
if gemini -p "$SEARCH_PROMPT" > "$TEMP_FILE" 2>&1; then
|
||||
echo ""
|
||||
echo "=" | tr -d '\n' | while read; do printf "=%.0s" {1..60}; done
|
||||
echo ""
|
||||
echo "📊 検索結果まとめ"
|
||||
echo "=" | tr -d '\n' | while read; do printf "=%.0s" {1..60}; done
|
||||
echo ""
|
||||
|
||||
# 結果を表示
|
||||
cat "$TEMP_FILE"
|
||||
|
||||
echo ""
|
||||
echo "=" | tr -d '\n' | while read; do printf "=%.0s" {1..60}; done
|
||||
echo ""
|
||||
echo "✅ 検索完了 - クエリ: \"$SEARCH_QUERY\""
|
||||
echo "💡 より詳細な情報が必要な場合は、具体的なキーワードで再検索してください"
|
||||
else
|
||||
echo ""
|
||||
echo "❌ 検索に失敗しました"
|
||||
echo ""
|
||||
echo "💡 トラブルシューティング:"
|
||||
echo "- gemini-cliの認証状態を確認: gemini"
|
||||
echo "- インターネット接続を確認"
|
||||
echo "- 検索クエリを変更して再試行"
|
||||
|
||||
# エラー内容も表示
|
||||
if [ -s "$TEMP_FILE" ]; then
|
||||
echo ""
|
||||
echo "エラー詳細:"
|
||||
cat "$TEMP_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 一時ファイルを削除
|
||||
rm -f "$TEMP_FILE"
|
||||
```
|
||||
|
||||
## 特徴
|
||||
- **リアルタイム検索**: Googleの最新情報にアクセス
|
||||
- **AI要約**: Gemini AIが検索結果を整理して表示
|
||||
- **統合された結果表示**: 検索結果を見やすい形式でまとめて表示
|
||||
- **視覚的な区切り**: 結果の開始と終了を明確に示すボーダー表示
|
||||
- **日本語対応**: 日本語クエリでの検索に最適化
|
||||
- **エラーハンドリング**: 適切なエラーメッセージとトラブルシューティング
|
||||
- **一時ファイル管理**: 結果を安全にキャプチャして表示
|
||||
|
||||
## 注意事項
|
||||
- gemini-cliの初回使用時はGoogleアカウントでの認証が必要です
|
||||
- 検索結果の品質はGemini AIの解析能力に依存します
|
||||
- 大量の検索を行う場合はAPI使用量にご注意ください
|
||||
|
||||
## 関連コマンド
|
||||
- `/pr-create`: プルリクエスト作成
|
||||
- `/commit`: コミットとプッシュ
|
||||
- `/review-diff`: コード差分レビュー
|
||||
50
commands/kiro.md
Normal file
50
commands/kiro.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# /kiro
|
||||
|
||||
## 概要
|
||||
Kiroスペックから実装を行うためのコマンドです。`.kiro/specs`ディレクトリ内のスペックを一覧表示し、選択したスペックの実装を開始します。
|
||||
|
||||
## 動作
|
||||
|
||||
1. `.kiro/specs`ディレクトリ内の全スペックを作成日時の降順で一覧表示
|
||||
2. ユーザーが番号を選択
|
||||
3. 選択されたスペックの`requirements.md`を読み込み
|
||||
4. 必要に応じて`design.md`や`tasks.md`も参照
|
||||
5. 実装を開始
|
||||
|
||||
## 実装手順
|
||||
|
||||
### ステップ1: スペック一覧の表示
|
||||
```bash
|
||||
# .kiro/specs配下のrequirements.mdファイルを検索し、作成日時でソート
|
||||
# macOSの場合
|
||||
find .kiro/specs -name "requirements.md" -type f -exec stat -f "%Sm %N" -t "%Y/%m/%d %H:%M" {} \; | sort -r
|
||||
# Linuxの場合
|
||||
find .kiro/specs -name "requirements.md" -type f -exec stat --format="%y %n" {} \; | sort -r
|
||||
```
|
||||
|
||||
各スペックについて以下を表示:
|
||||
- 番号(選択用)
|
||||
- スペック名(ディレクトリ名から取得)
|
||||
- 作成日時(YYYY/MM/DD形式)
|
||||
- 概要(requirements.mdの最初の段落から抽出)
|
||||
|
||||
### ステップ2: スペック選択
|
||||
ユーザーに番号入力を促し、対応するスペックを選択
|
||||
|
||||
### ステップ3: スペック内容の読み込み
|
||||
選択されたスペックのディレクトリから以下のファイルを読み込み:
|
||||
- `requirements.md`(必須): 要件定義
|
||||
- `design.md`(存在する場合): 設計詳細
|
||||
- `tasks.md`(存在する場合): タスクリスト
|
||||
|
||||
### ステップ4: 実装開始
|
||||
1. TodoWriteツールを使用してタスクリストを作成
|
||||
- tasks.mdがある場合はそれを基に作成
|
||||
- ない場合はrequirements.mdから主要タスクを抽出
|
||||
2. 各タスクを順番に実装
|
||||
3. 必要に応じてテストとリントを実行
|
||||
|
||||
## 注意事項
|
||||
- スペックファイルが存在しない場合は適切なエラーメッセージを表示
|
||||
- 実装前に現在のgitブランチを確認し、必要に応じて新しいブランチを作成することを提案
|
||||
- 実装完了後は自動的にコミットは行わない(ユーザーの明示的な指示を待つ)
|
||||
181
commands/pr-create.md
Normal file
181
commands/pr-create.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# プルリクエスト作成コマンド
|
||||
|
||||
現在のブランチからプルリクエストを作成します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/pr-create [タイトル] [説明]
|
||||
```
|
||||
|
||||
## 処理手順
|
||||
1. 現在のブランチの変更をpush(まだpushされていない場合)
|
||||
2. PRテンプレートを読み込み(存在する場合)
|
||||
3. コミット履歴から適切なタイトルと説明を生成
|
||||
4. ドラフトPRとして作成
|
||||
5. PR URLを表示
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: ブランチの状態確認
|
||||
```bash
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "🌿 現在のブランチ: $CURRENT_BRANCH"
|
||||
|
||||
# リモートブランチとの同期状態を確認
|
||||
git fetch origin
|
||||
|
||||
# pushが必要かチェック
|
||||
UNPUSHED_COMMITS=$(git rev-list --count origin/$CURRENT_BRANCH..$CURRENT_BRANCH 2>/dev/null || echo "new")
|
||||
if [ "$UNPUSHED_COMMITS" = "new" ] || [ "$UNPUSHED_COMMITS" -gt 0 ]; then
|
||||
echo "📤 リモートブランチにpushします..."
|
||||
git push -u origin $CURRENT_BRANCH
|
||||
else
|
||||
echo "✅ ブランチは既にpushされています"
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ2: PRテンプレートの確認
|
||||
```bash
|
||||
# PRテンプレートが存在するかチェック
|
||||
PR_TEMPLATE_FILE=""
|
||||
if [ -f ".github/PULL_REQUEST_TEMPLATE.md" ]; then
|
||||
PR_TEMPLATE_FILE=".github/PULL_REQUEST_TEMPLATE.md"
|
||||
echo "📋 PRテンプレートを発見: $PR_TEMPLATE_FILE"
|
||||
elif [ -f ".github/pull_request_template.md" ]; then
|
||||
PR_TEMPLATE_FILE=".github/pull_request_template.md"
|
||||
echo "📋 PRテンプレートを発見: $PR_TEMPLATE_FILE"
|
||||
else
|
||||
echo "📝 PRテンプレートが見つかりません。デフォルトの形式を使用します。"
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ3: PRタイトルと説明の生成
|
||||
```bash
|
||||
# コミット履歴からタイトルを生成(引数で指定されていない場合)
|
||||
if [ -z "$1" ]; then
|
||||
# 最新のコミットメッセージをタイトルに使用
|
||||
PR_TITLE=$(git log -1 --pretty=format:"%s")
|
||||
echo "💡 コミットメッセージからタイトルを生成: $PR_TITLE"
|
||||
else
|
||||
PR_TITLE="$1"
|
||||
echo "📝 指定されたタイトル: $PR_TITLE"
|
||||
fi
|
||||
|
||||
# PRの説明を生成
|
||||
if [ -z "$2" ]; then
|
||||
echo "📝 PR説明を生成中..."
|
||||
|
||||
# mainブランチからの変更履歴を取得
|
||||
COMMITS=$(git log --oneline master..$CURRENT_BRANCH 2>/dev/null || git log --oneline main..$CURRENT_BRANCH 2>/dev/null || git log --oneline -5)
|
||||
|
||||
# 変更されたファイルの一覧を取得
|
||||
CHANGED_FILES=$(git diff --name-only master..$CURRENT_BRANCH 2>/dev/null || git diff --name-only main..$CURRENT_BRANCH 2>/dev/null || git diff --name-only HEAD~5..HEAD)
|
||||
|
||||
if [ -n "$PR_TEMPLATE_FILE" ]; then
|
||||
echo "📋 PRテンプレートをベースに説明を生成します"
|
||||
# PRテンプレートをベースとして使用
|
||||
PR_BODY=$(cat "$PR_TEMPLATE_FILE")
|
||||
|
||||
# テンプレート内の特定のプレースホルダーを置換
|
||||
# 概要セクションに変更内容を自動挿入
|
||||
if echo "$PR_BODY" | grep -q "## 概要\|## Overview\|## Summary"; then
|
||||
# 概要セクションの後に変更内容を挿入
|
||||
PR_BODY=$(echo "$PR_BODY" | sed '/## 概要\|## Overview\|## Summary/a\\n**このPRの主な変更:**')
|
||||
if [ -n "$COMMITS" ]; then
|
||||
COMMIT_LIST=""
|
||||
echo "$COMMITS" | while read commit; do
|
||||
COMMIT_LIST="$COMMIT_LIST- $commit\n"
|
||||
done
|
||||
PR_BODY="$PR_BODY\n$COMMIT_LIST"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 変更されたファイルの情報を追加(テンプレートに該当セクションがない場合)
|
||||
if ! echo "$PR_BODY" | grep -q "変更.*ファイル\|Changed.*Files\|Files.*Changed"; then
|
||||
if [ -n "$CHANGED_FILES" ]; then
|
||||
PR_BODY="$PR_BODY\n\n## 変更されたファイル\n"
|
||||
echo "$CHANGED_FILES" | while read file; do
|
||||
PR_BODY="$PR_BODY- $file\n"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "📝 デフォルト形式でPR説明を生成します"
|
||||
# PRテンプレートがない場合のデフォルト形式
|
||||
PR_BODY="## 概要\n\nこの変更の目的と概要を記述してください\n\n"
|
||||
|
||||
if [ -n "$COMMITS" ]; then
|
||||
PR_BODY="$PR_BODY## 変更一覧\n"
|
||||
echo "$COMMITS" | while read commit; do
|
||||
PR_BODY="$PR_BODY- $commit\n"
|
||||
done
|
||||
PR_BODY="$PR_BODY\n"
|
||||
fi
|
||||
|
||||
if [ -n "$CHANGED_FILES" ]; then
|
||||
PR_BODY="$PR_BODY## 変更されたファイル\n"
|
||||
echo "$CHANGED_FILES" | while read file; do
|
||||
PR_BODY="$PR_BODY- $file\n"
|
||||
done
|
||||
PR_BODY="$PR_BODY\n"
|
||||
fi
|
||||
|
||||
PR_BODY="$PR_BODY## テスト計画\n- [ ] 手動テスト実行\n- [ ] 自動テスト確認\n\n## チェックリスト\n- [ ] コードレビュー準備完了\n- [ ] ドキュメント更新(必要に応じて)\n- [ ] 破壊的変更の確認"
|
||||
fi
|
||||
else
|
||||
PR_BODY="$2"
|
||||
echo "📝 指定された説明を使用"
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ4: PRの作成
|
||||
```bash
|
||||
# ドラフトPRとして作成
|
||||
echo "🚀 ドラフトPRを作成中..."
|
||||
|
||||
# PRを作成(HEREDOCを使用して適切にフォーマット)
|
||||
# bodyにHTMLコメントが含まれる場合の対応
|
||||
PR_BODY_FILE=$(mktemp)
|
||||
echo -e "$PR_BODY" > "$PR_BODY_FILE"
|
||||
gh pr create --draft --title "$PR_TITLE" --body-file "$PR_BODY_FILE"
|
||||
rm -f "$PR_BODY_FILE"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ ドラフトPRが正常に作成されました!"
|
||||
|
||||
# PR URLを取得して表示
|
||||
PR_URL=$(gh pr view --json url -q .url)
|
||||
echo "🔗 PR URL: $PR_URL"
|
||||
|
||||
echo ""
|
||||
echo "📋 次のステップ:"
|
||||
echo "1. PRの内容を確認・編集"
|
||||
echo "2. レビュアーを追加"
|
||||
echo "3. 準備ができたらドラフト状態を解除"
|
||||
echo "4. 必要に応じてラベルやマイルストーンを設定"
|
||||
else
|
||||
echo "❌ PR作成に失敗しました"
|
||||
echo "💡 トラブルシューティング:"
|
||||
echo "- GitHub CLIの認証状態を確認: gh auth status"
|
||||
echo "- リポジトリの権限を確認"
|
||||
echo "- ブランチが正しくpushされているか確認"
|
||||
fi
|
||||
```
|
||||
|
||||
## 重要なルール
|
||||
- **必ずドラフト状態で作成**: コードレビューの準備ができるまでドラフト状態を維持
|
||||
- **PRテンプレートをベースに使用**: `.github/PULL_REQUEST_TEMPLATE.md` が存在する場合は、その構造を基本として使用し、変更内容を自動で挿入
|
||||
- **適切なpush**: `git push -u origin <branch_name>` のように `--set-upstream` を指定
|
||||
- **意味のあるタイトル**: コミットメッセージや機能の概要を反映
|
||||
|
||||
## PRテンプレート活用の詳細
|
||||
- **テンプレートがある場合**: テンプレートの構造を維持し、概要セクションに変更内容を自動挿入
|
||||
- **テンプレートがない場合**: デフォルトの構造(概要、変更一覧、テスト計画、チェックリスト)を使用
|
||||
- **多言語対応**: 英語・日本語の一般的なセクション名に対応(Overview/概要、Summary/概要、Changed Files/変更されたファイル)
|
||||
|
||||
## 注意事項
|
||||
- PRテンプレートの既存構造を尊重し、必要な項目は自動補完します
|
||||
- コミットメッセージは意味のある内容にしてください
|
||||
- 破壊的変更がある場合は説明に明記してください
|
||||
- レビュアーの追加は手動で行ってください
|
||||
306
commands/pr-fix.md
Normal file
306
commands/pr-fix.md
Normal file
@@ -0,0 +1,306 @@
|
||||
# GitHub PR 自動修正コマンド
|
||||
|
||||
PRのレビューコメント(🚀リアクション付き)とCIエラーを自動的に修正します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/pr-fix [pr番号]
|
||||
```
|
||||
|
||||
PR番号が指定されない場合は、現在のブランチのPRを使用します。
|
||||
|
||||
**重要**: 修正したいレビューコメントに🚀リアクションを追加してから実行してください。🚀リアクションがついたコメントのみが修正対象になります。
|
||||
|
||||
## 処理手順
|
||||
1. PRとレビューコメント(🚀リアクション付き)を取得
|
||||
2. CIの失敗状況を確認
|
||||
3. レビューコメントの修正を適用
|
||||
4. CIエラーを修正
|
||||
5. テストとリンティングを実行して検証
|
||||
6. コミットせずに変更内容の概要を表示
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: PR情報の取得
|
||||
```bash
|
||||
# PR番号の取得または指定
|
||||
if [ -z "$1" ]; then
|
||||
# 現在のブランチのPRを取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "🌿 現在のブランチ: $CURRENT_BRANCH"
|
||||
|
||||
PR_INFO=$(gh pr list --head "$CURRENT_BRANCH" --json number 2>/dev/null)
|
||||
if [ -z "$PR_INFO" ] || [ "$PR_INFO" = "[]" ]; then
|
||||
echo "❌ 現在のブランチにPRが見つかりません"
|
||||
echo "💡 /pr-create でPRを作成するか、PR番号を指定してください: /pr-fix <PR番号>"
|
||||
exit 1
|
||||
fi
|
||||
PR_NUMBER=$(echo "$PR_INFO" | jq -r '.[0].number')
|
||||
else
|
||||
PR_NUMBER=$1
|
||||
fi
|
||||
|
||||
echo "📋 PR #$PR_NUMBER を修正します"
|
||||
echo ""
|
||||
```
|
||||
|
||||
### ステップ2: レビューコメント(🚀リアクション付き)の取得
|
||||
```bash
|
||||
echo "🚀 🚀リアクション付きレビューコメントを取得中..."
|
||||
|
||||
# PRのレビューコメントを取得
|
||||
COMMENTS=$(gh api "repos/:owner/:repo/pulls/$PR_NUMBER/comments" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$COMMENTS" ] || [ "$COMMENTS" = "[]" ]; then
|
||||
echo "ℹ️ レビューコメントが見つかりません"
|
||||
REVIEW_COMMENTS=""
|
||||
else
|
||||
# 🚀リアクション(rocket)がついたコメントのみを抽出
|
||||
REVIEW_COMMENTS=$(echo "$COMMENTS" | jq -r '.[] | select(.reactions.rocket > 0) | {path: .path, line: .position, body: .body, id: .id} | @json')
|
||||
|
||||
if [ -z "$REVIEW_COMMENTS" ]; then
|
||||
echo "ℹ️ 🚀リアクションがついたレビューコメントが見つかりません"
|
||||
echo "💡 修正したいコメントに🚀リアクションを追加してから再実行してください"
|
||||
else
|
||||
COMMENT_COUNT=$(echo "$REVIEW_COMMENTS" | wc -l | tr -d ' ')
|
||||
echo "📋 🚀リアクション付きコメント: ${COMMENT_COUNT}件"
|
||||
echo ""
|
||||
echo "$REVIEW_COMMENTS" | jq -r '. | "- \(.path):\(.line) - \(.body)"'
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ3: CIエラーの確認
|
||||
```bash
|
||||
echo "🔍 CIエラーを確認中..."
|
||||
|
||||
# PRのチェック状態を取得
|
||||
CHECK_RUNS=$(gh pr checks "$PR_NUMBER" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$CHECK_RUNS" ]; then
|
||||
FAILED_CHECKS=$(echo "$CHECK_RUNS" | grep -E "(fail|error|✗)" || echo "")
|
||||
|
||||
if [ -n "$FAILED_CHECKS" ]; then
|
||||
echo "❌ CIエラーが見つかりました:"
|
||||
echo "$FAILED_CHECKS"
|
||||
echo ""
|
||||
else
|
||||
echo "✅ CIエラーはありません"
|
||||
FAILED_CHECKS=""
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ CI情報を取得できませんでした"
|
||||
FAILED_CHECKS=""
|
||||
fi
|
||||
|
||||
# 修正対象が何もない場合は終了
|
||||
if [ -z "$REVIEW_COMMENTS" ] && [ -z "$FAILED_CHECKS" ]; then
|
||||
echo "✅ 修正対象が見つかりませんでした"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔧 修正を開始します..."
|
||||
echo ""
|
||||
```
|
||||
|
||||
### ステップ4: レビューコメントの修正適用
|
||||
レビューコメントの種類に応じて適切な修正を実行:
|
||||
|
||||
1. **コードの提案**: 提案されたコード変更を直接適用
|
||||
2. **スタイル/フォーマット**: リンターやフォーマッターを実行
|
||||
3. **ロジックの問題**: 要求されたロジック変更を実装
|
||||
4. **ドキュメント**: コメント、README、ドキュメントを更新
|
||||
5. **テスト**: テストを追加または修正
|
||||
6. **セキュリティ**: セキュリティ関連の修正を実施
|
||||
|
||||
```bash
|
||||
if [ -n "$REVIEW_COMMENTS" ]; then
|
||||
echo "📝 レビューコメントの修正を適用中..."
|
||||
echo ""
|
||||
echo "以下のレビューコメントを修正してください:"
|
||||
echo "$REVIEW_COMMENTS" | jq -r '. | "\(.path):\(.line) - \(.body)"'
|
||||
echo ""
|
||||
echo "⚠️ 重要な制約:"
|
||||
echo " - コードの品質を保ちながら修正すること"
|
||||
echo " - 既存のコードスタイルに従うこと"
|
||||
echo " - テストが通ることを確認すること"
|
||||
echo ""
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ5: CIエラーの修正
|
||||
CIエラーの種類に応じて自動修正を実行:
|
||||
|
||||
#### リンティングエラーの修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "lint"; then
|
||||
echo "📝 リンティングエラーを修正中..."
|
||||
|
||||
if [ -f "package.json" ]; then
|
||||
echo "🔧 npm run lint --fix を実行中..."
|
||||
npm run lint --fix 2>/dev/null || npm run lint:fix 2>/dev/null || echo "lintコマンドが見つかりません"
|
||||
fi
|
||||
|
||||
if command -v ruff >/dev/null 2>&1; then
|
||||
echo "🔧 ruff check --fix を実行中..."
|
||||
ruff check --fix .
|
||||
fi
|
||||
|
||||
if command -v golangci-lint >/dev/null 2>&1; then
|
||||
echo "🔧 golangci-lint を実行中..."
|
||||
golangci-lint run --fix
|
||||
fi
|
||||
|
||||
echo "✅ リンティング修正完了"
|
||||
echo ""
|
||||
fi
|
||||
```
|
||||
|
||||
#### 型エラーの修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "type\|typescript"; then
|
||||
echo "🏷️ 型エラーを分析中..."
|
||||
|
||||
if [ -f "tsconfig.json" ]; then
|
||||
echo "🔧 TypeScript型チェックを実行中..."
|
||||
npx tsc --noEmit 2>&1 | head -30
|
||||
echo ""
|
||||
echo "💡 上記の型エラーを修正してください"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
#### テスト失敗の修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "test"; then
|
||||
echo "🧪 テスト失敗を分析中..."
|
||||
|
||||
if [ -f "package.json" ]; then
|
||||
echo "🔧 npm test を実行中..."
|
||||
npm test 2>&1 | tail -30
|
||||
elif [ -f "pytest.ini" ] || [ -f "pyproject.toml" ]; then
|
||||
echo "🔧 pytest を実行中..."
|
||||
python -m pytest -v --tb=short 2>&1 | tail -30
|
||||
elif [ -f "go.mod" ]; then
|
||||
echo "🔧 go test を実行中..."
|
||||
go test ./... -v 2>&1 | tail -30
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "💡 テスト失敗の詳細を確認して修正してください"
|
||||
echo ""
|
||||
fi
|
||||
```
|
||||
|
||||
#### ビルドエラーの修正
|
||||
```bash
|
||||
if echo "$FAILED_CHECKS" | grep -qi "build"; then
|
||||
echo "🏗️ ビルドエラーを修正中..."
|
||||
|
||||
if [ -f "package.json" ]; then
|
||||
echo "📦 依存関係を更新中..."
|
||||
npm install
|
||||
|
||||
echo "🔧 ビルドを試行中..."
|
||||
npm run build 2>&1 | tail -30
|
||||
fi
|
||||
|
||||
if [ -f "requirements.txt" ]; then
|
||||
echo "📦 Python依存関係を更新中..."
|
||||
pip install -r requirements.txt
|
||||
fi
|
||||
|
||||
if [ -f "go.mod" ]; then
|
||||
echo "📦 Go依存関係を更新中..."
|
||||
go mod tidy
|
||||
go build ./...
|
||||
fi
|
||||
|
||||
echo ""
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ6: 修正の検証
|
||||
```bash
|
||||
echo "🧪 修正の検証中..."
|
||||
echo ""
|
||||
|
||||
# リンティングチェック
|
||||
echo "🔍 リンティングチェックを実行中..."
|
||||
if [ -f "package.json" ]; then
|
||||
npm run lint 2>/dev/null || echo "lintコマンドをスキップ"
|
||||
fi
|
||||
|
||||
# テスト実行
|
||||
echo "🧪 テストを実行中..."
|
||||
if [ -f "package.json" ]; then
|
||||
npm test 2>/dev/null && echo "✅ テスト成功" || echo "⚠️ テストで問題が残っています"
|
||||
elif [ -f "pytest.ini" ] || [ -f "pyproject.toml" ]; then
|
||||
python -m pytest 2>/dev/null && echo "✅ テスト成功" || echo "⚠️ テストで問題が残っています"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
```
|
||||
|
||||
### ステップ7: 修正結果の表示
|
||||
```bash
|
||||
# 変更内容の確認
|
||||
echo "📝 修正内容の確認:"
|
||||
git status --porcelain
|
||||
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo ""
|
||||
echo "📋 修正されたファイル:"
|
||||
git diff --name-only
|
||||
echo ""
|
||||
echo "📊 変更統計:"
|
||||
git diff --stat
|
||||
echo ""
|
||||
echo "✅ 修正が適用されました!"
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 'git diff' で変更内容を詳細確認"
|
||||
echo "2. 必要に応じて追加の修正を実施"
|
||||
echo "3. /commit でコミット作成"
|
||||
echo "4. /push-current でリモートにpush"
|
||||
echo "5. 数分後に /ci-check で状態を確認"
|
||||
else
|
||||
echo ""
|
||||
echo "ℹ️ 自動修正可能な変更が見つかりませんでした"
|
||||
echo "💡 以下の対応が必要です:"
|
||||
if [ -n "$REVIEW_COMMENTS" ]; then
|
||||
echo " - レビューコメントの手動修正"
|
||||
fi
|
||||
if [ -n "$FAILED_CHECKS" ]; then
|
||||
echo " - CIエラーの手動修正"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
## 修正対象のまとめ
|
||||
|
||||
### レビューコメント修正
|
||||
- 🚀リアクションがついたコメントのみを対象
|
||||
- コードの提案を直接適用
|
||||
- スタイル、ロジック、ドキュメント、テストの修正
|
||||
|
||||
### CIエラー修正
|
||||
1. **リンティングエラー**: 自動修正ツールを実行
|
||||
2. **型エラー**: TypeScript等の型チェックと分析
|
||||
3. **テスト失敗**: テストを実行して失敗箇所を特定
|
||||
4. **ビルドエラー**: 依存関係の更新とビルド実行
|
||||
|
||||
## エラーハンドリング
|
||||
- PRが存在しない場合は適切なメッセージを表示
|
||||
- GitHub CLIの権限エラー時は対処法を案内
|
||||
- レビューコメントが不明確な場合はTODOコメントを追加
|
||||
- 自動修正が不可能な場合は手動修正の必要性を通知
|
||||
|
||||
## 注意事項
|
||||
- **🚀リアクション必須**: 修正したいコメントに🚀リアクションを追加してください
|
||||
- すべてのエラーが自動修正できるわけではありません
|
||||
- 複雑なロジックエラーは手動での修正が必要です
|
||||
- 修正後は必ずローカルでテストを実行して検証してください
|
||||
- コミットとプッシュは手動で実行してください
|
||||
38
commands/pr-list.md
Normal file
38
commands/pr-list.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# PR List
|
||||
|
||||
オープン中のPR一覧を表示するカスタムコマンド。
|
||||
|
||||
```bash
|
||||
# GitHub CLIの確認
|
||||
if ! command -v gh &> /dev/null; then
|
||||
echo "❌ Error: GitHub CLI (gh) がインストールされていません"
|
||||
echo "インストール方法: https://cli.github.com/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📋 オープン中のPR一覧:"
|
||||
echo "=========================="
|
||||
|
||||
# オープン中のPRを取得して表示
|
||||
PR_COUNT=$(gh pr list --state open --json number | jq length)
|
||||
|
||||
if [ "$PR_COUNT" -eq 0 ]; then
|
||||
echo ""
|
||||
echo "✨ 現在オープン中のPRはありません"
|
||||
else
|
||||
# jqクエリを一時ファイルに保存して実行
|
||||
cat << 'EOF' > /tmp/pr-list-format.jq
|
||||
.[] |
|
||||
"🔹 #\(.number) \(.title)
|
||||
📂 Branch: \(.headRefName)
|
||||
👤 Author: \(.author.login)
|
||||
📅 Created: \(.createdAt)
|
||||
\(if .statusCheckRollup and (.statusCheckRollup | length) > 0 then "🔍 CI Status: \(.statusCheckRollup | group_by(.conclusion) | map(if .[0].conclusion == "SUCCESS" then "✅ 成功: \(length)" elif .[0].conclusion == "FAILURE" then "❌ 失敗: \(length)" elif .[0].conclusion == null then "🔄 実行中: \(length)" else "\(.[0].conclusion): \(length)" end) | join(", "))" else "🔍 CI Status: No checks" end)
|
||||
🔗 URL: \(.url)
|
||||
"
|
||||
EOF
|
||||
|
||||
gh pr list --state open --json number,title,headRefName,author,createdAt,url,statusCheckRollup | jq -r -f /tmp/pr-list-format.jq
|
||||
rm -f /tmp/pr-list-format.jq
|
||||
fi
|
||||
```
|
||||
170
commands/pr-review.md
Normal file
170
commands/pr-review.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# PRレビュー - 包括的なコードレビュー実行
|
||||
|
||||
指定されたPull Requestを詳細にレビューし、改善提案を行います。
|
||||
|
||||
## 使用方法
|
||||
`/pr-review <PR番号またはURL>`
|
||||
|
||||
例:
|
||||
- `/pr-review 123`
|
||||
- `/pr-review https://github.com/owner/repo/pull/123`
|
||||
|
||||
## 実行手順
|
||||
|
||||
### 1. PR情報の取得と検証
|
||||
- `gh pr view <PR番号> --json` でPR詳細情報を取得
|
||||
- タイトル、説明、作成者、ステータスを確認
|
||||
- ターゲットブランチとソースブランチの確認
|
||||
- 認証エラー時はフォールバック処理を実行
|
||||
|
||||
### 2. 変更内容の分析
|
||||
- `gh pr diff <PR番号>` で差分を取得
|
||||
- 変更されたファイル一覧を取得 (`gh pr view --json files`)
|
||||
- 追加・削除された行数の統計情報を収集
|
||||
- コミット履歴の確認 (`gh pr view --json commits`)
|
||||
|
||||
### 3. コードレビューの実施
|
||||
|
||||
#### 3.1 自動チェック項目
|
||||
|
||||
- **セキュリティ(最重要・厚めにチェック)**
|
||||
- **認証・認可**
|
||||
- ハードコードされた認証情報(API key, password, token等)
|
||||
- 認証トークンの安全な保管方法
|
||||
- 認可チェックの実装(権限検証の欠落)
|
||||
- セッション管理の安全性
|
||||
- **インジェクション攻撃**
|
||||
- SQLインジェクション脆弱性
|
||||
- NoSQLインジェクション
|
||||
- コマンドインジェクション
|
||||
- XSS(Stored/Reflected/DOM-based)
|
||||
- LDAP/XMLインジェクション
|
||||
- **入力検証とサニタイゼーション**
|
||||
- ユーザー入力の検証不足
|
||||
- ファイルアップロードの検証
|
||||
- Content-Type検証
|
||||
- サイズ制限の実装
|
||||
- ホワイトリスト方式の採用
|
||||
- **データ保護**
|
||||
- 機密情報のログ出力
|
||||
- 暗号化の適切な実装
|
||||
- 安全でない乱数生成
|
||||
- パスワードのハッシュ化(bcrypt、Argon2等)
|
||||
- **API/ネットワークセキュリティ**
|
||||
- CORS設定の安全性
|
||||
- CSRF対策の実装
|
||||
- Rate limiting の実装
|
||||
- HTTPSの強制
|
||||
- **依存関係のセキュリティ**
|
||||
- 既知の脆弱性を持つライブラリ
|
||||
- 最新版への更新の必要性
|
||||
- **その他のセキュリティ**
|
||||
- パストラバーサル脆弱性
|
||||
- XXE(XML External Entity)攻撃
|
||||
- サーバーサイドリクエストフォージェリ(SSRF)
|
||||
- 安全でないデシリアライゼーション
|
||||
|
||||
- **テストケース(重要・厚めにチェック)**
|
||||
- **テストカバレッジ**
|
||||
- 新規機能に対するテストの有無
|
||||
- 既存機能への影響範囲のテスト
|
||||
- エッジケースのカバー状況
|
||||
- エラーケースのテスト
|
||||
- **テストの種類と品質**
|
||||
- 単体テスト(Unit Test)の適切性
|
||||
- 統合テスト(Integration Test)の必要性
|
||||
- E2Eテストの必要性
|
||||
- テストの可読性と保守性
|
||||
- **テストケースの十分性**
|
||||
- 正常系のテスト
|
||||
- 異常系のテスト(バリデーションエラー、ネットワークエラー等)
|
||||
- 境界値テスト
|
||||
- 並行処理のテスト(該当する場合)
|
||||
- **セキュリティテスト**
|
||||
- 認証・認可のテスト
|
||||
- 入力検証のテスト
|
||||
- エラーハンドリングのテスト
|
||||
- **モックとテストデータ**
|
||||
- 外部依存のモック化
|
||||
- テストデータの適切性
|
||||
- テスト環境の分離
|
||||
- **パフォーマンステスト**
|
||||
- 負荷テストの必要性評価
|
||||
- レスポンスタイムの検証
|
||||
- **過剰なテストの検出**
|
||||
- 実装の詳細に依存しすぎたテスト(脆弱なテスト)
|
||||
- 重複したテストケース
|
||||
- 価値の低いテスト(自明な処理のテスト)
|
||||
- メンテナンスコストが高すぎるテスト
|
||||
- 不要にモックが多すぎるテスト
|
||||
|
||||
- **コード品質**
|
||||
- 命名規則の一貫性
|
||||
- 重複コードの検出
|
||||
- 複雑度の評価
|
||||
- デッドコードの検出
|
||||
|
||||
- **パフォーマンス**
|
||||
- N+1クエリの検出
|
||||
- 非効率なループ処理
|
||||
- 不要な再レンダリング(フロントエンド)
|
||||
- メモリリークの可能性
|
||||
|
||||
- **保守性**
|
||||
- 適切なコメントの有無
|
||||
- エラーハンドリングの実装
|
||||
- ログ出力の適切性
|
||||
- ドキュメントの更新
|
||||
|
||||
#### 3.2 プロジェクト固有のチェック
|
||||
- プロジェクトのコーディング規約への準拠
|
||||
- 既存のアーキテクチャとの整合性
|
||||
- 依存関係の適切な管理
|
||||
|
||||
### 4. レビュー結果のフォーマット
|
||||
|
||||
#### 4.1 サマリー
|
||||
- 全体的な評価(Approve/Request Changes/Comment)
|
||||
- 主要な問題点の要約
|
||||
- 良い点の強調
|
||||
|
||||
#### 4.2 詳細フィードバック
|
||||
各ファイルごとに:
|
||||
- 問題点の指摘(行番号付き)
|
||||
- 改善提案と具体的なコード例
|
||||
- 参考となるドキュメントやベストプラクティスへのリンク
|
||||
|
||||
#### 4.3 アクションアイテム
|
||||
- 必須の修正項目(ブロッカー)
|
||||
- 推奨される改善項目
|
||||
- 将来的な改善提案
|
||||
|
||||
### 5. GitHub上でのコメント投稿(オプション)
|
||||
- `gh pr comment` を使用してレビューコメントを投稿
|
||||
- 行単位のインラインコメント
|
||||
- 全体的なレビューコメント
|
||||
|
||||
## エラーハンドリング
|
||||
|
||||
### GitHub CLI認証エラー
|
||||
プライベートリポジトリで認証エラーが発生した場合:
|
||||
1. エラーメッセージを表示
|
||||
2. 手動でPRを確認するためのURLを提供
|
||||
3. 認証の再設定方法を案内:
|
||||
- `gh auth refresh -s repo,read:org`
|
||||
- GITHUB_TOKEN環境変数の確認
|
||||
|
||||
### API制限
|
||||
- レート制限に達した場合の待機処理
|
||||
- 部分的な結果での続行オプション
|
||||
|
||||
## 設定オプション
|
||||
- `--format`: 出力形式(markdown/json/html)
|
||||
- `--severity`: レビューの厳密さ(strict/normal/lenient)
|
||||
- `--focus`: 特定の観点に絞る(security/performance/style)
|
||||
- `--no-comment`: GitHubへのコメント投稿をスキップ
|
||||
|
||||
## 前提条件
|
||||
- GitHub CLIがインストールされ認証済みであること
|
||||
- 対象リポジトリへの読み取りアクセス権限
|
||||
- PR番号またはURLが有効であること
|
||||
64
commands/pr-zero.md
Normal file
64
commands/pr-zero.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Git Full Workflow - ブランチ作成からPR作成まで
|
||||
|
||||
ブランチ作成、コミット分割、PR作成を一連で実行するワークフロー
|
||||
|
||||
## 実行手順
|
||||
|
||||
### 1. ブランチ作成
|
||||
- ブランチ名は [Conventional Branch](https://conventional-branch.github.io/) に従う
|
||||
- feature/[FeatureName]-[実装した機能名] の形式
|
||||
- 例: `feature/admin-user-role-edit-invite-form`
|
||||
- 現在の変更をstashしてから新しいブランチを作成
|
||||
|
||||
### 2. 変更内容の確認と分析
|
||||
- `git status` で変更ファイルを確認
|
||||
- `git diff` で変更内容を確認
|
||||
- 論理的な単位で複数のコミットに分割する計画を立てる
|
||||
|
||||
### 3. コミット分割と作成
|
||||
- 関連する変更をグループ化して段階的にコミット
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) に従う
|
||||
- type(scope): subject の形式(例: feat(auth): add user login validation)
|
||||
- タイトルは50文字以内、本文は72文字程度で改行
|
||||
- 動詞は原形を使用(add, fix, updateなど)
|
||||
- コミットメッセージは小文字で始める
|
||||
|
||||
### 4. プッシュとPR作成
|
||||
- `git push -u origin <branch_name>` でプッシュ
|
||||
- GitHub CLI認証状態を確認
|
||||
- プライベートリポジトリの場合、認証エラー時はフォールバック処理を実行
|
||||
- PRテンプレートの確認:
|
||||
- 以下の順序で検索:
|
||||
1. `.github/PULL_REQUEST_TEMPLATE.md`
|
||||
2. `.github/pull_request_template.md`
|
||||
3. `.github/PULL_REQUEST_TEMPLATE/*.md`
|
||||
4. `find . -name "*PULL_REQUEST_TEMPLATE*" -o -name "*pull_request_template*"`
|
||||
- テンプレートが存在する場合は、その構造をベースとして使用
|
||||
- 概要セクション(## 概要/## Overview/## Summary)に変更内容を自動挿入
|
||||
- 変更ファイル情報も適切なセクションに追加
|
||||
- `gh pr create --draft` でドラフトPRを作成
|
||||
- 認証エラーの場合、手動PR作成URLを提供
|
||||
|
||||
## パラメータ
|
||||
- branch_name: 作成するブランチ名(feature/で始まる)
|
||||
- commit_strategy: auto(自動分割)または manual(手動確認)
|
||||
|
||||
## 注意事項
|
||||
- 実装とテストが含まれる場合、typeはfeat/fixを優先
|
||||
- PRはDraftで作成し、レビュー準備ができてからDraftを外す
|
||||
- コミット分割は論理的な変更単位を意識する
|
||||
- プライベートリポジトリでは認証スコープ不足時に自動フォールバック
|
||||
- GitHub CLIエラー時は手動PR作成用のURLを提供する
|
||||
- PRテンプレートがある場合は、既存の構造を尊重しつつ必要な情報を自動補完
|
||||
- 多言語対応:英語・日本語の一般的なセクション名に対応
|
||||
|
||||
## エラーハンドリング
|
||||
### GitHub CLI認証エラー
|
||||
- プライベートリポジトリで "Could not resolve to a Repository" エラーが発生した場合
|
||||
- 以下の手動PR作成URLを提供:
|
||||
`https://github.com/{owner}/{repo}/compare/{base}...{branch}`
|
||||
- 必要に応じて認証の再設定を案内
|
||||
|
||||
### 認証スコープ不足
|
||||
- GITHUB_TOKEN環境変数使用時は、十分なスコープ(repo, read:org)が必要
|
||||
- 環境変数未設定の場合は `gh auth refresh -s repo,read:org` で再認証
|
||||
38
commands/push-current.md
Normal file
38
commands/push-current.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Git Push Current Branch
|
||||
|
||||
現在のブランチをリモートにpushするカスタムコマンド
|
||||
|
||||
```bash
|
||||
# 現在のブランチ名を取得
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
if [ -z "$CURRENT_BRANCH" ]; then
|
||||
echo "Error: ブランチ名を取得できませんでした"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "現在のブランチ: $CURRENT_BRANCH"
|
||||
|
||||
# メインブランチのチェック
|
||||
if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
|
||||
echo "❌ Error: メインブランチ ($CURRENT_BRANCH) への直接pushは禁止されています"
|
||||
echo "フィーチャーブランチを作成してください"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# リモートブランチの存在確認
|
||||
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
|
||||
echo "リモートブランチが存在します。pushを実行..."
|
||||
git push origin "$CURRENT_BRANCH"
|
||||
else
|
||||
echo "リモートにブランチが存在しません。upstream設定付きでpushを実行..."
|
||||
git push -u origin "$CURRENT_BRANCH"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ push完了: $CURRENT_BRANCH"
|
||||
else
|
||||
echo "❌ pushに失敗しました"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
482
commands/review-diff.md
Normal file
482
commands/review-diff.md
Normal file
@@ -0,0 +1,482 @@
|
||||
# コード差分レビューコマンド
|
||||
|
||||
現在のコード差分を分析し、コーディング規約とベストプラクティスに従ったレビューを実施します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/review-diff [対象ファイル・ディレクトリ]
|
||||
```
|
||||
|
||||
対象が指定されない場合は、すべての変更されたファイルをレビューします。
|
||||
|
||||
## 処理手順
|
||||
1. 現在の変更差分を取得・分析
|
||||
2. プロジェクトのコーディング規約を特定
|
||||
3. 使用技術のベストプラクティスを適用
|
||||
4. 問題点と改善提案を整理
|
||||
5. 詳細なレビューレポートを生成
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: 変更差分の取得
|
||||
```bash
|
||||
# git statusで変更ファイルを確認
|
||||
echo "📋 変更されたファイルを確認中..."
|
||||
CHANGED_FILES=$(git status --porcelain)
|
||||
|
||||
if [ -z "$CHANGED_FILES" ]; then
|
||||
echo "ℹ️ レビュー対象の変更がありません"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📝 変更されたファイル:"
|
||||
echo "$CHANGED_FILES"
|
||||
echo ""
|
||||
|
||||
# 詳細差分を取得
|
||||
echo "🔍 差分を分析中..."
|
||||
DIFF_CONTENT=$(git diff --no-color)
|
||||
STAGED_DIFF=$(git diff --cached --no-color)
|
||||
|
||||
if [ -n "$STAGED_DIFF" ]; then
|
||||
echo "📦 ステージング済みの変更も含めて分析します"
|
||||
DIFF_CONTENT="$DIFF_CONTENT\n\n=== STAGED CHANGES ===\n$STAGED_DIFF"
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ2: プロジェクト環境の分析
|
||||
```bash
|
||||
# プロジェクトの技術スタックを特定
|
||||
echo "🔍 プロジェクト環境を分析中..."
|
||||
|
||||
PROJECT_TYPE=""
|
||||
LANGUAGES=()
|
||||
FRAMEWORKS=()
|
||||
CONFIG_FILES=()
|
||||
|
||||
# 言語・フレームワークの検出
|
||||
if [ -f "package.json" ]; then
|
||||
PROJECT_TYPE="Node.js"
|
||||
LANGUAGES+=("JavaScript" "TypeScript")
|
||||
echo "📦 Node.js プロジェクトを検出"
|
||||
|
||||
# フレームワーク検出
|
||||
if grep -q "react" package.json; then
|
||||
FRAMEWORKS+=("React")
|
||||
fi
|
||||
if grep -q "vue" package.json; then
|
||||
FRAMEWORKS+=("Vue.js")
|
||||
fi
|
||||
if grep -q "next" package.json; then
|
||||
FRAMEWORKS+=("Next.js")
|
||||
fi
|
||||
if grep -q "express" package.json; then
|
||||
FRAMEWORKS+=("Express")
|
||||
fi
|
||||
|
||||
CONFIG_FILES+=("package.json" ".eslintrc*" ".prettierrc*" "tsconfig.json")
|
||||
fi
|
||||
|
||||
if [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
|
||||
PROJECT_TYPE="Python"
|
||||
LANGUAGES+=("Python")
|
||||
echo "🐍 Python プロジェクトを検出"
|
||||
|
||||
if grep -q "django" requirements.txt 2>/dev/null; then
|
||||
FRAMEWORKS+=("Django")
|
||||
fi
|
||||
if grep -q "flask" requirements.txt 2>/dev/null; then
|
||||
FRAMEWORKS+=("Flask")
|
||||
fi
|
||||
if grep -q "fastapi" requirements.txt 2>/dev/null; then
|
||||
FRAMEWORKS+=("FastAPI")
|
||||
fi
|
||||
|
||||
CONFIG_FILES+=("requirements.txt" "pyproject.toml" ".flake8" "mypy.ini")
|
||||
fi
|
||||
|
||||
if [ -f "go.mod" ]; then
|
||||
PROJECT_TYPE="Go"
|
||||
LANGUAGES+=("Go")
|
||||
echo "🔷 Go プロジェクトを検出"
|
||||
CONFIG_FILES+=("go.mod" "go.sum")
|
||||
fi
|
||||
|
||||
if [ -f "Cargo.toml" ]; then
|
||||
PROJECT_TYPE="Rust"
|
||||
LANGUAGES+=("Rust")
|
||||
echo "🦀 Rust プロジェクトを検出"
|
||||
CONFIG_FILES+=("Cargo.toml" "Cargo.lock")
|
||||
fi
|
||||
|
||||
# その他の設定ファイル
|
||||
CONFIG_FILES+=(".gitignore" "README.md" ".editorconfig")
|
||||
|
||||
echo "🏗️ 検出された技術スタック:"
|
||||
echo " 言語: ${LANGUAGES[*]}"
|
||||
echo " フレームワーク: ${FRAMEWORKS[*]}"
|
||||
```
|
||||
|
||||
### ステップ3: レビュー基準の設定
|
||||
```bash
|
||||
# レビュー基準を設定
|
||||
echo "📐 レビュー基準を設定中..."
|
||||
|
||||
REVIEW_CRITERIA=()
|
||||
|
||||
# 共通基準
|
||||
REVIEW_CRITERIA+=(
|
||||
"コードの可読性と保守性"
|
||||
"命名規則の一貫性"
|
||||
"セキュリティベストプラクティス"
|
||||
"パフォーマンス最適化"
|
||||
"エラーハンドリング"
|
||||
"テスタビリティ"
|
||||
"ドキュメント整備"
|
||||
)
|
||||
|
||||
# 言語固有の基準
|
||||
for lang in "${LANGUAGES[@]}"; do
|
||||
case $lang in
|
||||
"JavaScript"|"TypeScript")
|
||||
REVIEW_CRITERIA+=(
|
||||
"ESLint/Prettier準拠"
|
||||
"型安全性(TypeScript)"
|
||||
"非同期処理のベストプラクティス"
|
||||
"メモリリーク対策"
|
||||
"バンドルサイズ最適化"
|
||||
)
|
||||
;;
|
||||
"Python")
|
||||
REVIEW_CRITERIA+=(
|
||||
"PEP 8準拠"
|
||||
"型ヒント使用"
|
||||
"例外処理の適切性"
|
||||
"パッケージ構造"
|
||||
"docstring記述"
|
||||
)
|
||||
;;
|
||||
"Go")
|
||||
REVIEW_CRITERIA+=(
|
||||
"Go Convention準拠"
|
||||
"エラーハンドリング"
|
||||
"Goroutineとチャネルの使用"
|
||||
"メモリ効率"
|
||||
"テストカバレッジ"
|
||||
)
|
||||
;;
|
||||
"Rust")
|
||||
REVIEW_CRITERIA+=(
|
||||
"Rust Convention準拠"
|
||||
"所有権とライフタイム"
|
||||
"Result型でのエラーハンドリング"
|
||||
"メモリ安全性"
|
||||
"パフォーマンス"
|
||||
)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "📋 適用されるレビュー基準:"
|
||||
for criteria in "${REVIEW_CRITERIA[@]}"; do
|
||||
echo " - $criteria"
|
||||
done
|
||||
```
|
||||
|
||||
### ステップ4: 自動チェックの実行
|
||||
```bash
|
||||
# 利用可能なリンター・チェッカーを実行
|
||||
echo "🔧 自動チェックを実行中..."
|
||||
|
||||
LINT_RESULTS=()
|
||||
|
||||
# JavaScript/TypeScript
|
||||
if command -v npm >/dev/null 2>&1 && [ -f "package.json" ]; then
|
||||
echo "📝 ESLint チェック実行中..."
|
||||
if npm run lint --silent 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ ESLint: 問題なし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ ESLint: 問題が検出されました")
|
||||
fi
|
||||
|
||||
if command -v tsc >/dev/null 2>&1 && [ -f "tsconfig.json" ]; then
|
||||
echo "🏷️ TypeScript型チェック実行中..."
|
||||
if npx tsc --noEmit --skipLibCheck 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ TypeScript: 型エラーなし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ TypeScript: 型エラーが検出されました")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Python
|
||||
if command -v ruff >/dev/null 2>&1; then
|
||||
echo "🐍 Ruff チェック実行中..."
|
||||
if ruff check . --quiet 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ Ruff: 問題なし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ Ruff: 問題が検出されました")
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v mypy >/dev/null 2>&1; then
|
||||
echo "🏷️ MyPy型チェック実行中..."
|
||||
if mypy . --ignore-missing-imports --quiet 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ MyPy: 型エラーなし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ MyPy: 型エラーが検出されました")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Go
|
||||
if command -v golangci-lint >/dev/null 2>&1 && [ -f "go.mod" ]; then
|
||||
echo "🔷 golangci-lint チェック実行中..."
|
||||
if golangci-lint run --quiet 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ golangci-lint: 問題なし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ golangci-lint: 問題が検出されました")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Rust
|
||||
if command -v cargo >/dev/null 2>&1 && [ -f "Cargo.toml" ]; then
|
||||
echo "🦀 Cargo clippy チェック実行中..."
|
||||
if cargo clippy --quiet -- -D warnings 2>/dev/null; then
|
||||
LINT_RESULTS+=("✅ Clippy: 問題なし")
|
||||
else
|
||||
LINT_RESULTS+=("❌ Clippy: 問題が検出されました")
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "🔍 自動チェック結果:"
|
||||
for result in "${LINT_RESULTS[@]}"; do
|
||||
echo " $result"
|
||||
done
|
||||
```
|
||||
|
||||
### ステップ5: レビューレポート生成
|
||||
```bash
|
||||
# レビューレポートを生成
|
||||
echo ""
|
||||
echo "📊 コード差分レビューレポート"
|
||||
echo "=================================="
|
||||
echo ""
|
||||
echo "📅 レビュー実施日時: $(date '+%Y年%m月%d日 %H:%M:%S')"
|
||||
echo "🏗️ プロジェクトタイプ: $PROJECT_TYPE"
|
||||
echo "💻 検出言語: ${LANGUAGES[*]}"
|
||||
echo "🚀 使用フレームワーク: ${FRAMEWORKS[*]}"
|
||||
echo ""
|
||||
|
||||
echo "## 📋 変更ファイル一覧"
|
||||
git status --porcelain | while read -r line; do
|
||||
status=${line:0:2}
|
||||
file=${line:3}
|
||||
case $status in
|
||||
"M ") echo " 📝 変更: $file" ;;
|
||||
"A ") echo " ➕ 追加: $file" ;;
|
||||
"D ") echo " ❌ 削除: $file" ;;
|
||||
"R ") echo " 🔄 リネーム: $file" ;;
|
||||
"??") echo " ❓ 未追跡: $file" ;;
|
||||
*) echo " 📄 $status: $file" ;;
|
||||
esac
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "## 🔧 自動チェック結果"
|
||||
for result in "${LINT_RESULTS[@]}"; do
|
||||
echo " $result"
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "## 📐 レビューポイント"
|
||||
echo ""
|
||||
echo "### ✅ 良い点"
|
||||
echo "- Conventional Commits形式でのコミットメッセージ作成"
|
||||
echo "- 適切なファイル構造とディレクトリ組織"
|
||||
echo "- 設定ファイルの適切な管理"
|
||||
echo ""
|
||||
|
||||
echo "### 🔍 改善提案"
|
||||
echo ""
|
||||
|
||||
# ファイル別の具体的な改善提案
|
||||
git diff --name-only | while read -r file; do
|
||||
echo "#### 📄 $file"
|
||||
|
||||
case $file in
|
||||
*.js|*.ts|*.jsx|*.tsx)
|
||||
echo "- **JavaScript/TypeScript ベストプラクティス**"
|
||||
echo " - console.log の削除を確認"
|
||||
echo " - 未使用インポートの削除"
|
||||
echo " - 適切な型定義の使用"
|
||||
echo " - エラーハンドリングの実装"
|
||||
;;
|
||||
*.py)
|
||||
echo "- **Python ベストプラクティス**"
|
||||
echo " - PEP 8準拠の確認"
|
||||
echo " - 型ヒントの追加"
|
||||
echo " - docstringの記述"
|
||||
echo " - 例外処理の適切な実装"
|
||||
;;
|
||||
*.go)
|
||||
echo "- **Go ベストプラクティス**"
|
||||
echo " - エラーハンドリングの確認"
|
||||
echo " - 未使用変数の削除"
|
||||
echo " - 適切なパッケージ構造"
|
||||
echo " - テストの追加"
|
||||
;;
|
||||
*.rs)
|
||||
echo "- **Rust ベストプラクティス**"
|
||||
echo " - 所有権とライフタイムの確認"
|
||||
echo " - Result型の適切な使用"
|
||||
echo " - パフォーマンス最適化"
|
||||
echo " - 安全性の確認"
|
||||
;;
|
||||
*.md)
|
||||
echo "- **Markdown ドキュメント**"
|
||||
echo " - リンクの有効性確認"
|
||||
echo " - 見出し構造の整理"
|
||||
echo " - コードブロックの言語指定"
|
||||
echo " - 誤字脱字の確認"
|
||||
;;
|
||||
*.json)
|
||||
echo "- **JSON設定ファイル**"
|
||||
echo " - フォーマットの統一"
|
||||
echo " - 不要なプロパティの削除"
|
||||
echo " - セキュリティ設定の確認"
|
||||
;;
|
||||
*)
|
||||
echo "- **一般的な改善点**"
|
||||
echo " - ファイル形式の適切性"
|
||||
echo " - 文字エンコーディングの確認"
|
||||
echo " - 改行コードの統一"
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "### 🚀 次のステップ"
|
||||
echo "1. 自動チェックで検出された問題の修正"
|
||||
echo "2. 改善提案の検討・実装"
|
||||
echo "3. テストの実行・追加"
|
||||
echo "4. ドキュメントの更新"
|
||||
echo "5. コードレビューの依頼"
|
||||
echo ""
|
||||
|
||||
echo "## 📈 品質メトリクス"
|
||||
echo ""
|
||||
TOTAL_FILES=$(git diff --name-only | wc -l)
|
||||
ADDED_LINES=$(git diff --numstat | awk '{add+=$1} END {print add+0}')
|
||||
DELETED_LINES=$(git diff --numstat | awk '{del+=$2} END {print del+0}')
|
||||
|
||||
echo "📊 変更統計:"
|
||||
echo " - 変更ファイル数: $TOTAL_FILES"
|
||||
echo " - 追加行数: +$ADDED_LINES"
|
||||
echo " - 削除行数: -$DELETED_LINES"
|
||||
echo " - 正味変更: $((ADDED_LINES - DELETED_LINES))"
|
||||
echo ""
|
||||
|
||||
echo "🎯 レビュー完了!改善提案を参考にコードの品質向上を図ってください。"
|
||||
```
|
||||
|
||||
## レビュー対象
|
||||
|
||||
### **セキュリティ(最重要・厚めにチェック)**
|
||||
- **認証・認可**
|
||||
- ハードコードされた認証情報(API key, password, token等)
|
||||
- 認証トークンの安全な保管方法
|
||||
- 認可チェックの実装(権限検証の欠落)
|
||||
- セッション管理の安全性
|
||||
- **インジェクション攻撃**
|
||||
- SQLインジェクション脆弱性
|
||||
- NoSQLインジェクション
|
||||
- コマンドインジェクション
|
||||
- XSS(Stored/Reflected/DOM-based)
|
||||
- LDAP/XMLインジェクション
|
||||
- **入力検証とサニタイゼーション**
|
||||
- ユーザー入力の検証不足
|
||||
- ファイルアップロードの検証
|
||||
- Content-Type検証
|
||||
- サイズ制限の実装
|
||||
- ホワイトリスト方式の採用
|
||||
- **データ保護**
|
||||
- 機密情報のログ出力
|
||||
- 暗号化の適切な実装
|
||||
- 安全でない乱数生成
|
||||
- パスワードのハッシュ化(bcrypt、Argon2等)
|
||||
- **API/ネットワークセキュリティ**
|
||||
- CORS設定の安全性
|
||||
- CSRF対策の実装
|
||||
- Rate limiting の実装
|
||||
- HTTPSの強制
|
||||
- **依存関係のセキュリティ**
|
||||
- 既知の脆弱性を持つライブラリ
|
||||
- 最新版への更新の必要性
|
||||
- **その他のセキュリティ**
|
||||
- パストラバーサル脆弱性
|
||||
- XXE(XML External Entity)攻撃
|
||||
- サーバーサイドリクエストフォージェリ(SSRF)
|
||||
- 安全でないデシリアライゼーション
|
||||
|
||||
### **テストケース(重要・厚めにチェック)**
|
||||
- **テストカバレッジ**
|
||||
- 新規機能に対するテストの有無
|
||||
- 既存機能への影響範囲のテスト
|
||||
- エッジケースのカバー状況
|
||||
- エラーケースのテスト
|
||||
- **テストの種類と品質**
|
||||
- 単体テスト(Unit Test)の適切性
|
||||
- 統合テスト(Integration Test)の必要性
|
||||
- E2Eテストの必要性
|
||||
- テストの可読性と保守性
|
||||
- **テストケースの十分性**
|
||||
- 正常系のテスト
|
||||
- 異常系のテスト(バリデーションエラー、ネットワークエラー等)
|
||||
- 境界値テスト
|
||||
- 並行処理のテスト(該当する場合)
|
||||
- **セキュリティテスト**
|
||||
- 認証・認可のテスト
|
||||
- 入力検証のテスト
|
||||
- エラーハンドリングのテスト
|
||||
- **モックとテストデータ**
|
||||
- 外部依存のモック化
|
||||
- テストデータの適切性
|
||||
- テスト環境の分離
|
||||
- **パフォーマンステスト**
|
||||
- 負荷テストの必要性評価
|
||||
- レスポンスタイムの検証
|
||||
- **過剰なテストの検出**
|
||||
- 実装の詳細に依存しすぎたテスト(脆弱なテスト)
|
||||
- 重複したテストケース
|
||||
- 価値の低いテスト(自明な処理のテスト)
|
||||
- メンテナンスコストが高すぎるテスト
|
||||
- 不要にモックが多すぎるテスト
|
||||
|
||||
### **コード品質**
|
||||
- 可読性、保守性、パフォーマンス
|
||||
- 命名規則の一貫性
|
||||
- 重複コードの検出
|
||||
- 複雑度の評価
|
||||
- デッドコードの検出
|
||||
|
||||
### **ベストプラクティス**
|
||||
- 言語・フレームワーク固有の推奨事項
|
||||
- 既存のアーキテクチャとの整合性
|
||||
- 適切なエラーハンドリング
|
||||
|
||||
### **ドキュメント**
|
||||
- README、コメント、型定義
|
||||
- API仕様の更新
|
||||
- 変更履歴の記録
|
||||
|
||||
## 技術スタック別対応
|
||||
- **Node.js**: ESLint、Prettier、TypeScript
|
||||
- **Python**: Ruff、MyPy、PEP 8
|
||||
- **Go**: golangci-lint、Go Convention
|
||||
- **Rust**: Clippy、Rust Convention
|
||||
|
||||
## 注意事項
|
||||
- 自動チェックツールが利用可能な場合のみ実行
|
||||
- プロジェクト固有のルールがある場合は設定ファイルを参照
|
||||
- レビュー結果は参考として活用し、最終判断は開発者が行う
|
||||
- セキュリティに関わる問題は特に注意深く確認
|
||||
163
commands/review-fix.md
Normal file
163
commands/review-fix.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# GitHub PR レビューコメント修正コマンド
|
||||
|
||||
PRのレビューコメントを自動的にチェックして、要求された修正を適用します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/review-fix [pr番号]
|
||||
```
|
||||
|
||||
PR番号が指定されない場合は、現在のブランチのPRを使用します。
|
||||
|
||||
**重要**: 修正したいレビューコメントに👍リアクションを追加してから実行してください。👍リアクションがついたコメントのみが修正対象になります。
|
||||
|
||||
## 処理手順
|
||||
1. GitHub CLIを使ってPRとレビューコメントを取得
|
||||
2. 各レビューコメントを分析して実行可能なフィードバックを特定
|
||||
3. 可能な限り要求された変更を自動適用
|
||||
4. テストとリンティングを実行して修正を検証
|
||||
5. コミットせずに変更内容の概要を表示
|
||||
|
||||
## 実装
|
||||
PRの情報とレビューコメントの取得から開始します。
|
||||
|
||||
### ステップ1: PR情報の取得
|
||||
```bash
|
||||
# GitHub CLIの認証とスコープを最初にチェック
|
||||
echo "🔍 GitHub CLIの設定を確認中..."
|
||||
gh auth status
|
||||
|
||||
# PR番号が指定されていない場合は現在のブランチのPRを取得(フォールバック処理付き)
|
||||
PR_INFO=$(gh pr view --json number,reviews,url 2>/dev/null || echo "")
|
||||
if [ -z "$PR_INFO" ]; then
|
||||
echo "❌ PR情報を取得できません。考えられる原因:"
|
||||
echo " - 現在のブランチにPRが存在しない"
|
||||
echo " - GitHub CLIに追加のスコープが必要 (read:org, read:discussion)"
|
||||
echo " - 認証の問題"
|
||||
echo ""
|
||||
echo "💡 GitHub CLIのスコープを修正するには:"
|
||||
echo " 1. https://github.com/settings/tokens にアクセス"
|
||||
echo " 2. トークンに'read:org'と'read:discussion'スコープを追加"
|
||||
echo " 3. 実行: gh auth login --with-token < your_token_file"
|
||||
echo ""
|
||||
echo "🔄 代替方法: PR番号を手動で指定 /review-fix <pr番号>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 後続のコマンドで使用するためにPR番号を抽出
|
||||
PR_NUMBER=$(echo "$PR_INFO" | jq -r '.number')
|
||||
echo "📋 PR #$PR_NUMBER を発見"
|
||||
```
|
||||
|
||||
### ステップ2: レビューコメントの取得
|
||||
```bash
|
||||
# 包括的なエラーハンドリングでレビューコメントを取得
|
||||
echo "📥 PR #$PR_NUMBER のレビューコメントを取得中..."
|
||||
|
||||
# レビューデータを取得する複数の方法を試行
|
||||
REVIEWS=$(gh pr view $PR_NUMBER --json reviews 2>/dev/null || echo "")
|
||||
COMMENTS=$(gh api "repos/:owner/:repo/pulls/$PR_NUMBER/comments" 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$REVIEWS" ] && [ -z "$COMMENTS" ]; then
|
||||
echo "❌ レビューコメントを取得できません。GitHub CLIの権限を確認してください。"
|
||||
echo "💡 必要なスコープ: repo, read:org, read:discussion"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# レビューサマリーを解析して表示
|
||||
echo "📊 レビューサマリー:"
|
||||
if [ -n "$REVIEWS" ]; then
|
||||
echo "$REVIEWS" | jq -r '.reviews[] | "- \(.state) by \(.user.login): \(.body // "コメントなし")"'
|
||||
fi
|
||||
|
||||
if [ -n "$COMMENTS" ]; then
|
||||
echo "💬 行コメント:"
|
||||
echo "$COMMENTS" | jq -r '.[] | "- \(.path):\(.line) - \(.body)"'
|
||||
fi
|
||||
```
|
||||
|
||||
### ステップ3: 修正対象コメントの特定
|
||||
```bash
|
||||
# 👍リアクションがついたコメントを修正対象として特定
|
||||
echo "🔍 修正対象のレビューコメントを特定中..."
|
||||
|
||||
# 👍リアクションがついているコメントのみを抽出
|
||||
TARGET_COMMENTS=$(echo "$COMMENTS" | jq -r '.[] | select(.reactions."+1" > 0) | {path: .path, line: .line, body: .body}')
|
||||
|
||||
if [ -z "$TARGET_COMMENTS" ] || [ "$TARGET_COMMENTS" = "null" ]; then
|
||||
echo "ℹ️ 👍リアクションがついたレビューコメントが見つかりません"
|
||||
echo "💡 修正したいコメントに👍リアクションを追加してから再実行してください"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📋 修正対象のコメント:"
|
||||
echo "$TARGET_COMMENTS" | jq -r '"- \(.path):\(.line) - \(.body)"'
|
||||
```
|
||||
|
||||
### ステップ4: コメントの解析と分類
|
||||
👍リアクションがついた各レビューコメントについて:
|
||||
1. **コードの提案**: 提案されたコード変更を直接適用
|
||||
2. **スタイル/フォーマット**: 適切なリンターやフォーマッターを実行
|
||||
3. **ロジックの問題**: 要求されたロジック変更を分析して実装
|
||||
4. **ドキュメント**: 要求に応じてコメント、README、ドキュメントを更新
|
||||
5. **テスト**: 提案に従ってテストを追加または修正
|
||||
6. **セキュリティ懸念**: セキュリティ関連のフィードバックに対処
|
||||
|
||||
### ステップ5: 修正の体系的適用
|
||||
- レビューコメントのファイルパスと行番号を使用して、必要な変更箇所を正確に特定
|
||||
- コードの提案については、提案されたdiffを直接適用
|
||||
- より幅広いフィードバックについては、包括的な修正を実装
|
||||
- 各修正が既存の機能を破損しないことを検証
|
||||
|
||||
### ステップ6: 変更の検証
|
||||
```bash
|
||||
# 修正を検証するためにテストを実行(利用可能な場合)
|
||||
echo "🧪 修正を検証するためにテストを実行中..."
|
||||
npm test || python -m pytest || go test || cargo test || echo "テストコマンドが見つかりません"
|
||||
|
||||
# コードスタイルをチェックするためにリンティングを実行
|
||||
echo "🔍 リンティングチェックを実行中..."
|
||||
npm run lint || ruff check || golangci-lint run || echo "リントコマンドが見つかりません"
|
||||
|
||||
# 行われた変更を表示するためにgit statusを表示
|
||||
echo "📝 行われた変更の概要:"
|
||||
git status --porcelain
|
||||
echo ""
|
||||
echo "📋 詳細diff:"
|
||||
git diff --stat
|
||||
echo ""
|
||||
echo "✅ レビュー修正が正常に適用されました!"
|
||||
echo "💡 準備ができたら /commit-create を使用してこれらの変更をコミットしてください"
|
||||
```
|
||||
|
||||
### ステップ7: サマリーレポート
|
||||
```bash
|
||||
# 適用された修正のサマリーを生成
|
||||
echo "🤖 レビュー修正サマリー:"
|
||||
echo "- PRレビューコメントの問題を修正"
|
||||
echo "- 可能な限りコードの提案を適用"
|
||||
echo "- スタイル/フォーマットの問題を解決"
|
||||
echo "- 要求に応じてドキュメントを更新"
|
||||
echo ""
|
||||
echo "📊 変更されたファイル数: $(git diff --name-only | wc -l)"
|
||||
echo "📈 変更された行数: +$(git diff --numstat | awk '{add+=$1} END {print add}') -$(git diff --numstat | awk '{del+=$2} END {print del}')"
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 'git diff' で変更内容を確認"
|
||||
echo "2. 必要に応じて追加のテストを実行"
|
||||
echo "3. 満足したら /commit-create を使用してコミット"
|
||||
```
|
||||
|
||||
## エラーハンドリング
|
||||
- レビューコメントが不明確な場合は、手動レビュー用のTODOコメントを表示
|
||||
- 自動修正が不可能な場合は、コード内にTODOコメントを作成
|
||||
- 修正後にテストが失敗した場合は、失敗詳細を表示してガイダンスを求める
|
||||
- マージコンフリクトを適切に処理し、発見されたコンフリクトを報告
|
||||
|
||||
## 注意事項
|
||||
- **👍リアクション必須**: 修正したいコメントに👍リアクションを追加してください
|
||||
- 明確に要求され、安全な変更のみを適用
|
||||
- 複雑なロジック変更については、保守的に実装し確認を求める
|
||||
- 既存のコードスタイルとパターンを保持
|
||||
- 修正を検証するために必ずテストを実行するが、自動的にはコミットしない
|
||||
- レビュー後に変更をコミットするには /commit-create コマンドを使用
|
||||
433
commands/test-create.md
Normal file
433
commands/test-create.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# テスト自動生成コマンド
|
||||
|
||||
現在の差分から変更されたファイルを検出し、既存のテスト実装パターンに基づいてテストを自動生成します。
|
||||
|
||||
## 使用方法
|
||||
```bash
|
||||
/test-create
|
||||
```
|
||||
|
||||
## 処理手順
|
||||
1. `git diff`で変更されたファイルを検出
|
||||
2. 各ファイルの言語・フレームワークを識別
|
||||
3. 既存のテストファイルからパターンを学習
|
||||
4. 新規または更新されたテストファイルを生成
|
||||
5. 生成されたテストの概要を表示
|
||||
|
||||
## 実装
|
||||
|
||||
### ステップ1: 変更ファイルの検出と分析
|
||||
```bash
|
||||
echo "🔍 変更されたファイルを検出中..."
|
||||
|
||||
# ステージングされた変更とステージングされていない変更の両方を取得
|
||||
STAGED_FILES=$(git diff --cached --name-only)
|
||||
UNSTAGED_FILES=$(git diff --name-only)
|
||||
ALL_CHANGED_FILES=$(echo -e "$STAGED_FILES\n$UNSTAGED_FILES" | sort -u | grep -v "^$")
|
||||
|
||||
if [ -z "$ALL_CHANGED_FILES" ]; then
|
||||
echo "❌ 変更されたファイルが見つかりません"
|
||||
echo "💡 ファイルを変更してから再度実行してください"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📝 変更されたファイル:"
|
||||
echo "$ALL_CHANGED_FILES" | while read -r file; do
|
||||
echo " - $file"
|
||||
done
|
||||
echo ""
|
||||
```
|
||||
|
||||
### ステップ2: 各ファイルに対するテスト生成
|
||||
|
||||
変更されたファイルごとに:
|
||||
1. ファイルの拡張子から言語を識別
|
||||
2. 既存のテストパターンを検索
|
||||
3. 適切なテストファイルを生成または更新
|
||||
|
||||
#### TypeScript/JavaScript ファイル
|
||||
```bash
|
||||
# TypeScript/JavaScript ファイルの処理
|
||||
echo "$ALL_CHANGED_FILES" | grep -E "\.(ts|tsx|js|jsx)$" | while read -r file; do
|
||||
if [ -z "$file" ]; then continue; fi
|
||||
|
||||
echo "📄 処理中: $file"
|
||||
|
||||
# テストファイル名を決定
|
||||
TEST_FILE=""
|
||||
if [[ "$file" == *.tsx ]]; then
|
||||
TEST_FILE="${file%.tsx}.test.tsx"
|
||||
elif [[ "$file" == *.ts ]]; then
|
||||
TEST_FILE="${file%.ts}.test.ts"
|
||||
elif [[ "$file" == *.jsx ]]; then
|
||||
TEST_FILE="${file%.jsx}.test.jsx"
|
||||
elif [[ "$file" == *.js ]]; then
|
||||
TEST_FILE="${file%.js}.test.js"
|
||||
fi
|
||||
|
||||
# __tests__ ディレクトリパターンをチェック
|
||||
DIR=$(dirname "$file")
|
||||
BASENAME=$(basename "$file")
|
||||
if [ -d "$DIR/__tests__" ]; then
|
||||
TEST_FILE="$DIR/__tests__/$BASENAME"
|
||||
TEST_FILE="${TEST_FILE%.*}.test.${file##*.}"
|
||||
fi
|
||||
|
||||
echo " → テストファイル: $TEST_FILE"
|
||||
|
||||
# 既存のテストパターンを検索
|
||||
EXISTING_TEST_PATTERN=""
|
||||
if [ -f "$TEST_FILE" ]; then
|
||||
echo " ✓ 既存のテストファイルを更新"
|
||||
else
|
||||
# 同じプロジェクトの他のテストファイルからパターンを学習
|
||||
SAMPLE_TEST=$(find "$(dirname "$file")" -name "*.test.*" -o -name "*.spec.*" | head -1)
|
||||
if [ -n "$SAMPLE_TEST" ]; then
|
||||
echo " 📚 テストパターンを学習: $SAMPLE_TEST"
|
||||
fi
|
||||
echo " ✓ 新規テストファイルを生成"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
#### Python ファイル
|
||||
```bash
|
||||
# Python ファイルの処理
|
||||
echo "$ALL_CHANGED_FILES" | grep -E "\.py$" | while read -r file; do
|
||||
if [ -z "$file" ]; then continue; fi
|
||||
|
||||
echo "📄 処理中: $file"
|
||||
|
||||
# テストファイル名を決定
|
||||
TEST_FILE=""
|
||||
BASENAME=$(basename "$file" .py)
|
||||
DIR=$(dirname "$file")
|
||||
|
||||
# pytest規則に従う
|
||||
if [[ "$file" == test_* ]] || [[ "$file" == *_test.py ]]; then
|
||||
echo " ℹ️ スキップ: 既にテストファイルです"
|
||||
continue
|
||||
fi
|
||||
|
||||
# tests/ ディレクトリが存在するかチェック
|
||||
if [ -d "$DIR/tests" ]; then
|
||||
TEST_FILE="$DIR/tests/test_$BASENAME.py"
|
||||
elif [ -d "tests" ]; then
|
||||
# プロジェクトルートのtestsディレクトリ
|
||||
TEST_FILE="tests/test_$BASENAME.py"
|
||||
else
|
||||
TEST_FILE="${DIR}/test_${BASENAME}.py"
|
||||
fi
|
||||
|
||||
echo " → テストファイル: $TEST_FILE"
|
||||
|
||||
# 既存のテストパターンを検索
|
||||
if [ -f "$TEST_FILE" ]; then
|
||||
echo " ✓ 既存のテストファイルを更新"
|
||||
else
|
||||
# pytestパターンを検索
|
||||
SAMPLE_TEST=$(find . -name "test_*.py" -o -name "*_test.py" | head -1)
|
||||
if [ -n "$SAMPLE_TEST" ]; then
|
||||
echo " 📚 テストパターンを学習: $SAMPLE_TEST"
|
||||
fi
|
||||
echo " ✓ 新規テストファイルを生成"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
#### Go ファイル
|
||||
```bash
|
||||
# Go ファイルの処理
|
||||
echo "$ALL_CHANGED_FILES" | grep -E "\.go$" | grep -v "_test\.go$" | while read -r file; do
|
||||
if [ -z "$file" ]; then continue; fi
|
||||
|
||||
echo "📄 処理中: $file"
|
||||
|
||||
# テストファイル名を決定
|
||||
TEST_FILE="${file%.go}_test.go"
|
||||
|
||||
echo " → テストファイル: $TEST_FILE"
|
||||
|
||||
if [ -f "$TEST_FILE" ]; then
|
||||
echo " ✓ 既存のテストファイルを更新"
|
||||
else
|
||||
echo " ✓ 新規テストファイルを生成"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
### ステップ3: テスト生成の実行
|
||||
|
||||
実際のテスト生成は、各言語・フレームワークに応じて以下を実行:
|
||||
|
||||
1. **関数・クラスの抽出**: 変更されたファイルから公開関数・クラスを抽出
|
||||
2. **テストケースの生成**:
|
||||
- 正常系テスト
|
||||
- 異常系テスト
|
||||
- エッジケーステスト
|
||||
3. **既存テストとの統合**: 既存のテストがある場合は重複を避けて追加
|
||||
|
||||
```bash
|
||||
echo ""
|
||||
echo "🧪 テスト生成プロセス:"
|
||||
echo ""
|
||||
|
||||
# 実際にテストファイルを生成する関数を定義
|
||||
generate_js_test() {
|
||||
local source_file="$1"
|
||||
local test_file="$2"
|
||||
local basename=$(basename "$source_file" | sed 's/\.[^.]*$//')
|
||||
|
||||
# テストファイルの内容を生成
|
||||
cat > "$test_file" << EOF
|
||||
import { describe, it, expect } from '@jest/globals';
|
||||
import { $basename } from './$basename';
|
||||
|
||||
describe('$basename', () => {
|
||||
it('should be defined', () => {
|
||||
expect($basename).toBeDefined();
|
||||
});
|
||||
|
||||
// TODO: 実際のテストケースを実装してください
|
||||
// 以下は例です:
|
||||
// it('should return expected result', () => {
|
||||
// const result = $basename();
|
||||
// expect(result).toBe(expectedValue);
|
||||
// });
|
||||
});
|
||||
EOF
|
||||
}
|
||||
|
||||
generate_python_test() {
|
||||
local source_file="$1"
|
||||
local test_file="$2"
|
||||
local basename=$(basename "$source_file" .py)
|
||||
local module_path=$(echo "$source_file" | sed 's/\//_/g' | sed 's/\.py$//')
|
||||
|
||||
# テストディレクトリがない場合は作成
|
||||
mkdir -p "$(dirname "$test_file")"
|
||||
|
||||
cat > "$test_file" << EOF
|
||||
import pytest
|
||||
from $basename import *
|
||||
|
||||
|
||||
class Test$(echo $basename | sed 's/^./\U&/')():
|
||||
"""$basename モジュールのテストクラス"""
|
||||
|
||||
def test_module_import(self):
|
||||
"""モジュールがインポートできることをテスト"""
|
||||
# TODO: 実際のテストケースを実装してください
|
||||
assert True
|
||||
|
||||
# TODO: 以下のようなテストメソッドを追加してください:
|
||||
# def test_function_name(self):
|
||||
# """function_name のテスト"""
|
||||
# result = function_name()
|
||||
# assert result == expected_value
|
||||
EOF
|
||||
}
|
||||
|
||||
generate_go_test() {
|
||||
local source_file="$1"
|
||||
local test_file="$2"
|
||||
local package_name=$(head -1 "$source_file" | awk '{print $2}')
|
||||
|
||||
cat > "$test_file" << EOF
|
||||
package $package_name
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackage(t *testing.T) {
|
||||
// TODO: 実際のテストケースを実装してください
|
||||
// 以下は例です:
|
||||
// func TestFunctionName(t *testing.T) {
|
||||
// result := FunctionName()
|
||||
// expected := "expected_value"
|
||||
// if result != expected {
|
||||
// t.Errorf("FunctionName() = %v, want %v", result, expected)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 変更されたファイルに対してテストを生成
|
||||
echo "$ALL_CHANGED_FILES" | while read -r file; do
|
||||
if [ -z "$file" ] || [ ! -f "$file" ]; then continue; fi
|
||||
|
||||
# ファイルタイプを判定
|
||||
EXT="${file##*.}"
|
||||
|
||||
case "$EXT" in
|
||||
ts|tsx|js|jsx)
|
||||
# テストファイル名を決定
|
||||
TEST_FILE="${file%.*}.test.${EXT}"
|
||||
if [[ "$file" == *".tsx" ]] || [[ "$file" == *".jsx" ]]; then
|
||||
# React コンポーネントの場合は __tests__ ディレクトリも考慮
|
||||
DIR=$(dirname "$file")
|
||||
if [ -d "$DIR/__tests__" ]; then
|
||||
BASENAME=$(basename "$file")
|
||||
TEST_FILE="$DIR/__tests__/${BASENAME%.*}.test.${EXT}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$TEST_FILE" ]; then
|
||||
echo "🔧 JavaScript/TypeScriptテストを生成: $file → $TEST_FILE"
|
||||
generate_js_test "$file" "$TEST_FILE"
|
||||
else
|
||||
echo "⚠️ テストファイル既存: $TEST_FILE (スキップ)"
|
||||
fi
|
||||
;;
|
||||
py)
|
||||
if [[ "$file" != test_* ]] && [[ "$file" != *_test.py ]]; then
|
||||
BASENAME=$(basename "$file" .py)
|
||||
DIR=$(dirname "$file")
|
||||
|
||||
# テストファイル名を決定
|
||||
if [ -d "$DIR/tests" ]; then
|
||||
TEST_FILE="$DIR/tests/test_$BASENAME.py"
|
||||
elif [ -d "tests" ]; then
|
||||
TEST_FILE="tests/test_$BASENAME.py"
|
||||
else
|
||||
TEST_FILE="${DIR}/test_${BASENAME}.py"
|
||||
fi
|
||||
|
||||
if [ ! -f "$TEST_FILE" ]; then
|
||||
echo "🔧 Pythonテストを生成: $file → $TEST_FILE"
|
||||
generate_python_test "$file" "$TEST_FILE"
|
||||
else
|
||||
echo "⚠️ テストファイル既存: $TEST_FILE (スキップ)"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
go)
|
||||
if [[ "$file" != *_test.go ]]; then
|
||||
TEST_FILE="${file%.go}_test.go"
|
||||
|
||||
if [ ! -f "$TEST_FILE" ]; then
|
||||
echo "🔧 Goテストを生成: $file → $TEST_FILE"
|
||||
generate_go_test "$file" "$TEST_FILE"
|
||||
else
|
||||
echo "⚠️ テストファイル既存: $TEST_FILE (スキップ)"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "⚠️ サポートされていないファイルタイプ: $file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
```
|
||||
|
||||
### ステップ4: 生成結果の表示
|
||||
|
||||
```bash
|
||||
echo ""
|
||||
echo "📊 テスト生成結果:"
|
||||
echo ""
|
||||
|
||||
# 生成されたテストファイルを表示
|
||||
NEW_TEST_FILES=$(git status --porcelain | grep "^??" | grep -E "\.(test|spec)\." | awk '{print $2}')
|
||||
MODIFIED_TEST_FILES=$(git status --porcelain | grep "^ M" | grep -E "\.(test|spec)\." | awk '{print $2}')
|
||||
|
||||
if [ -n "$NEW_TEST_FILES" ]; then
|
||||
echo "✨ 新規作成されたテストファイル:"
|
||||
echo "$NEW_TEST_FILES" | while read -r file; do
|
||||
echo " - $file"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$MODIFIED_TEST_FILES" ]; then
|
||||
echo "📝 更新されたテストファイル:"
|
||||
echo "$MODIFIED_TEST_FILES" | while read -r file; do
|
||||
echo " - $file"
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ テスト生成が完了しました!"
|
||||
echo ""
|
||||
echo "🔄 次のステップ:"
|
||||
echo "1. 生成されたテストを確認: git diff"
|
||||
echo "2. テストを実行: npm test / pytest / go test など"
|
||||
echo "3. 必要に応じてテストを調整"
|
||||
echo "4. テストが成功したら: /commit でコミット"
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
|
||||
- 生成されたテストは必ず手動で確認してください
|
||||
- 既存のテストパターンがない場合は、一般的なパターンを使用します
|
||||
- プライベート関数のテストは生成されません
|
||||
- モックやスタブが必要な場合は手動で追加してください
|
||||
|
||||
## サポートされる言語とフレームワーク
|
||||
|
||||
### JavaScript/TypeScript
|
||||
- Jest
|
||||
- Mocha
|
||||
- Vitest
|
||||
- React Testing Library
|
||||
|
||||
### Python
|
||||
- pytest
|
||||
- unittest
|
||||
- nose2
|
||||
|
||||
### Go
|
||||
- 標準のtestingパッケージ
|
||||
- testify
|
||||
|
||||
## 高度な使用方法
|
||||
|
||||
### 特定ファイルのみ対象
|
||||
|
||||
特定のファイルに対してのみテストを生成したい場合は、事前に変更をステージングしてください:
|
||||
|
||||
```bash
|
||||
git add path/to/specific/file.ts
|
||||
/test-create
|
||||
```
|
||||
|
||||
これにより、ステージングされたファイルに対してのみテストが生成されます。
|
||||
|
||||
### インテリジェントなテスト生成
|
||||
|
||||
Claude Codeを使ってより高度なテストを生成することも可能です。実装の詳細に基づいたテストを生成したい場合は、以下のような拡張版を使用してください:
|
||||
|
||||
```bash
|
||||
# Claude Codeを使った高度なテスト生成
|
||||
generate_intelligent_test() {
|
||||
local source_file="$1"
|
||||
local test_file="$2"
|
||||
|
||||
echo "🤖 Claude Codeを使って高度なテストを生成中: $source_file"
|
||||
|
||||
# ファイルの内容を読み取って、Claude Codeにテスト生成を依頼
|
||||
cat > /tmp/test_generation_prompt.txt << EOF
|
||||
以下のファイルの内容に基づいて、包括的なテストコードを生成してください。
|
||||
|
||||
ファイル: $source_file
|
||||
|
||||
EOF
|
||||
cat "$source_file" >> /tmp/test_generation_prompt.txt
|
||||
cat >> /tmp/test_generation_prompt.txt << EOF
|
||||
|
||||
要件:
|
||||
1. すべての公開関数/メソッドをテストする
|
||||
2. 正常系、異常系、エッジケースを含む
|
||||
3. 適切なモックやスタブを使用する
|
||||
4. テストの可読性を重視する
|
||||
5. コメントは日本語で記述する
|
||||
|
||||
テストフレームワークは既存のプロジェクト設定に合わせて選択してください。
|
||||
EOF
|
||||
|
||||
# Note: 実際の実装では、Claude Code APIを呼び出して
|
||||
# テストコードを生成することができます
|
||||
echo "💡 手動でテストコードをレビューして完成させてください"
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user