Skip to content

feat: add git quality gates hooks for Claude Code - #268

Merged
keito4 merged 1 commit into
mainfrom
feat/git-quality-gates-hooks
Jan 2, 2026
Merged

feat: add git quality gates hooks for Claude Code#268
keito4 merged 1 commit into
mainfrom
feat/git-quality-gates-hooks

Conversation

@keito4

@keito4 keito4 commented Jan 2, 2026

Copy link
Copy Markdown
Owner

Summary

Claude による git commit/push の前に自動的に品質チェックを実行する仕組みを追加しました。

主な変更点

  • .claude/hooks/pre_git_quality_gates.py: Git操作前のQuality Gates実行スクリプト

    • Format Check (npm run format:check)
    • Lint (npm run lint)
    • Test (npm run test)
    • ShellCheck (npm run shellcheck)
    • Security Credential Scan (./script/security-credential-scan.sh --strict)
    • Code Complexity Check (./script/code-complexity-check.sh --strict)
  • .claude/hooks/README.md: Hooksの使用方法、トラブルシューティング、カスタムHooks作成方法を記載

  • .claude/CLAUDE.md: Quality Gatesのセクションを追加

動作

PreToolUse フックとして設定され、Bash ツールで git commit または git push を実行しようとした際に自動的にトリガーされます。すべてのチェックに合格した場合のみ、Git操作が許可されます。

設定方法

.claude/settings.local.json に以下の hooks 設定を追加することで有効化されます:

{
  "hooks": {
    "PreToolUse": [
      {
        "comment": "Block git --no-verify and HUSKY=0",
        "matcher": "tool_name == 'Bash'",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/block_git_no_verify.py"
          }
        ]
      },
      {
        "comment": "Run Quality Gates before git commit/push",
        "matcher": "tool_name == 'Bash'",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/pre_git_quality_gates.py"
          }
        ]
      }
    ]
  }
}

Test plan

  • Hookスクリプトの構文チェック(python3 -m py_compile)
  • block_git_no_verify.py の動作確認
    • --no-verify フラグをブロック
    • HUSKY=0 環境変数をブロック
  • pre_git_quality_gates.py の動作確認
    • Git以外のコマンドは正しくスルー
    • 必要なnpmスクリプトとシェルスクリプトの存在確認
  • 実際のコミット時にQuality Gatesが実行されることを確認
  • すべてのチェックに合格してコミットが成功することを確認

関連Issue

このPRは、開発品質を保証するための基盤強化の一環です。

その他

  • .claude/settings.local.json.gitignore に含まれているため、各開発者が個別に設定する必要があります
  • 詳細な使用方法は .claude/hooks/README.md を参照してください

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Added comprehensive documentation for quality gate configuration, troubleshooting, and hook setup instructions.
  • New Features

    • Introduced automated quality gate checks enforced before git commit and push operations, including format validation, linting, unit testing, shell script validation, security credential scanning, and code complexity analysis.

✏️ Tip: You can customize this high-level summary in your review settings.

Claude による git commit/push 前に品質チェックを自動実行する
仕組みを追加。

## 追加内容

### 新規ファイル
- `.claude/hooks/pre_git_quality_gates.py`:
  Git操作前のQuality Gates実行スクリプト
  - Format Check (npm run format:check)
  - Lint (npm run lint)
  - Test (npm run test)
  - ShellCheck (npm run shellcheck)
  - Security Credential Scan (--strict)
  - Code Complexity Check (--strict)

- `.claude/hooks/README.md`:
  Hooksの使用方法とトラブルシューティングガイド

### 更新ファイル
- `.claude/CLAUDE.md`: Quality Gates セクションを追加

## 動作

PreToolUse フックとして設定され、git commit または
git push 実行時に自動的にトリガー。すべてのチェック
に合格した場合のみ、Git操作が許可される。

## 設定

`.claude/settings.local.json` の hooks 設定で有効化:
- block_git_no_verify.py:
  --no-verify と HUSKY=0 をブロック
- pre_git_quality_gates.py: Quality Gates を実行

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jan 2, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Introduces a quality gates system that enforces pre-commit checks (Format Check, Lint, Test, ShellCheck, Security Credential Scan, Code Complexity Check) via git hooks. Adds documentation describing the hooks architecture and a Python script that intercepts git commit/push commands to run sequential validation checks with 5-minute timeouts before allowing operations to proceed.

Changes

Cohort / File(s) Summary
Documentation
.claude/CLAUDE.md, .claude/hooks/README.md
Adds "Quality Gates(品質ゲート)" section to CLAUDE.md with overview of pre-commit checks. Creates new README.md documenting hook system, available hooks (block_git_no_verify.py, pre_git_quality_gates.py), configuration via settings.local.json, setup instructions, and troubleshooting guidance.
Quality Gates Hook Implementation
.claude/hooks/pre_git_quality_gates.py
Introduces Python script that intercepts git commit/push commands and sequentially executes six quality checks with 5-minute timeouts each: Format Check, Lint, Test, ShellCheck, Security Credential Scan, and Code Complexity Check. Collects failures and exits with code 2 on any failure, code 0 on all-pass. Uses Japanese status messaging and graceful error handling.

Sequence Diagram

sequenceDiagram
    participant User as User/Claude
    participant Git as Git CLI
    participant Hook as Quality Gates Hook
    participant Checks as Quality Checks
    
    User->>Git: git commit / git push
    Git->>Hook: Trigger pre-git-quality-gates.py
    activate Hook
    
    Note over Hook: Detect git command
    rect rgb(240, 248, 255)
        Note over Hook,Checks: Sequential Quality Checks (5min timeout each)
        Hook->>Checks: npm run format:check
        Checks-->>Hook: ✓ or ✗
        Hook->>Checks: npm run lint
        Checks-->>Hook: ✓ or ✗
        Hook->>Checks: npm run test
        Checks-->>Hook: ✓ or ✗
        Hook->>Checks: npm run shellcheck
        Checks-->>Hook: ✓ or ✗
        Hook->>Checks: ./script/security-credential-scan.sh --strict
        Checks-->>Hook: ✓ or ✗
        Hook->>Checks: ./script/code-complexity-check.sh --strict
        Checks-->>Hook: ✓ or ✗
    end
    
    alt All Checks Pass
        Hook->>User: Exit code 0 + success message
    else Any Check Fails
        Hook->>User: Exit code 2 + failure details
        User->>Git: ✗ Blocked
    end
    deactivate Hook
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

released

Poem

🐰 A rabbit hops through git commands with care,
Quality gates stand guard everywhere!
Six checks in a row, each one in its place,
Before commits fly, they pass the race! ✨
Pre-commit hooks now keep the code so clean,
The finest quality gates you've ever seen!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding git quality gates hooks for Claude Code, which aligns with the primary objective of automating quality checks before git operations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Jan 2, 2026

Copy link
Copy Markdown
Contributor

PR Review: Git Quality Gates Hooks for Claude Code

このPRは Claude Code による Git 操作前に自動的に品質チェックを実行する仕組みを追加するもので、開発品質の向上に貢献する良い取り組みです。


✅ 良い点

1. アーキテクチャ設計

  • 適切な責任分離: block_git_no_verify.py と pre_git_quality_gates.py で関心事を分離
  • 明確なドキュメント: README.md が充実
  • 柔軟な設定: .claude/settings.local.json で個別にカスタマイズ可能

2. エラーハンドリング

  • FileNotFoundError を適切にキャッチしてスキップ処理(pre_git_quality_gates.py:112-114)
  • タイムアウト処理の実装(300秒)(pre_git_quality_gates.py:105-110)
  • 詳細なエラー情報の出力

3. ユーザビリティ

  • 絵文字を使った視覚的なフィードバック
  • 失敗時に具体的な修正方法を提示

⚠️ 改善提案

1. セキュリティ: コマンド検出の強化(優先度: 高)

pre_git_quality_gates.py:31-38 で Git コマンドを検出していますが、bash -c "git commit" のようなケースが考慮されていません。

推奨: matcher を活用したフィルタリングの強化

2. パフォーマンス: 全テストの実行コスト(優先度: 中)

毎回全テストを実行しますが、大規模プロジェクトで時間がかかる可能性があります。

推奨案:

  • 変更されたファイルのみをテスト
  • 独立したチェックを並列化
  • キャッシュ戦略

3. テストカバレッジ: 自動テストの不足(優先度: 高)

CLAUDE.md で 70%+ カバレッジを要求していますが、このPRにはフックスクリプト自体のテストがありません。

推奨: test/hooks/ ディレクトリに単体テストを追加

4. コード品質: マジックナンバーの定数化(優先度: 低)

pre_git_quality_gates.py:91 のタイムアウト値(300秒)を定数化


📊 パフォーマンス考慮事項

現在の実行時間見積もり: 合計 70-100秒/コミット

大規模プロジェクトでは負担になる可能性があるため、変更差分ベースのチェックや並列実行を推奨します。


総評

素晴らしい取り組みです。以下を優先的に対応することを推奨します:

  1. 最優先: テストカバレッジの追加(TDD原則に従う)
  2. 高優先: コマンド検出ロジックのセキュリティ強化
  3. 中優先: パフォーマンス最適化

レビュアー: Claude Sonnet 4.5

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.claude/hooks/pre_git_quality_gates.py (1)

103-121: Refactor exception handling and remove unnecessary f-strings.

Two improvements needed:

  1. Lines 103, 110, 114: Remove unnecessary f prefix from strings without placeholders
  2. Line 116: Catching bare Exception can mask programming errors. Consider logging the full traceback or being more specific about expected exceptions.
🔎 Proposed improvements
         else:
-            print(f"  ✅ 成功", file=sys.stderr)
+            print("  ✅ 成功", file=sys.stderr)
 
     except subprocess.TimeoutExpired:
         failed_checks.append({
             "name": check["name"],
             "error": "タイムアウト (5分)"
         })
-        print(f"  ❌ タイムアウト", file=sys.stderr)
+        print("  ❌ タイムアウト", file=sys.stderr)
 
     except FileNotFoundError:
         # スクリプトが存在しない場合は失敗として記録
         failed_checks.append({
             "name": check["name"],
             "error": "コマンドが見つかりません"
         })
-        print(f"  ❌ 失敗 (コマンドが見つかりません)", file=sys.stderr)
+        print("  ❌ 失敗 (コマンドが見つかりません)", file=sys.stderr)
 
     except Exception as e:
+        # 予期しないエラーの場合はトレースバックも記録
+        import traceback
         failed_checks.append({
             "name": check["name"],
-            "error": str(e)
+            "error": f"{str(e)}\n{traceback.format_exc()}"
         })
         print(f"  ❌ エラー: {e}", file=sys.stderr)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3c954f and 29f1754.

📒 Files selected for processing (3)
  • .claude/CLAUDE.md
  • .claude/hooks/README.md
  • .claude/hooks/pre_git_quality_gates.py
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: keito4/config PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T08:39:14.049Z
Learning: Follow development quality standards defined in `CLAUDE.md` when using Claude Code for development assistance
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Apply automated linting, formatting, security analysis, and license checking as static quality gates
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Applies to .github/workflows/claude.yml : Trigger automatic AI assistance on claude mentions in issues, PRs, and comments using .github/workflows/claude.yml
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Applies to .github/workflows/ci.yml : Validate code quality in CI pipeline (.github/workflows/ci.yml) with linting, formatting, testing, and building
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Ensure Definition of Done criteria are met when completing tasks (quality gates passed, documentation updated, monitoring stable, release notes complete)
📚 Learning: 2025-12-09T08:39:14.049Z
Learnt from: CR
Repo: keito4/config PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T08:39:14.049Z
Learning: Follow development quality standards defined in `CLAUDE.md` when using Claude Code for development assistance

Applied to files:

  • .claude/CLAUDE.md
  • .claude/hooks/pre_git_quality_gates.py
📚 Learning: 2025-12-01T03:45:17.253Z
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Apply automated linting, formatting, security analysis, and license checking as static quality gates

Applied to files:

  • .claude/CLAUDE.md
  • .claude/hooks/pre_git_quality_gates.py
📚 Learning: 2025-12-01T03:45:17.253Z
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Applies to .github/workflows/claude.yml : Trigger automatic AI assistance on claude mentions in issues, PRs, and comments using .github/workflows/claude.yml

Applied to files:

  • .claude/CLAUDE.md
📚 Learning: 2025-12-01T03:45:17.253Z
Learnt from: CR
Repo: keito4/config PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T03:45:17.253Z
Learning: Applies to .github/workflows/ci.yml : Validate code quality in CI pipeline (.github/workflows/ci.yml) with linting, formatting, testing, and building

Applied to files:

  • .claude/CLAUDE.md
🪛 Ruff (0.14.10)
.claude/hooks/pre_git_quality_gates.py

5-5: Docstring contains ambiguous (FULLWIDTH COLON). Did you mean : (COLON)?

(RUF002)


27-27: Comment contains ambiguous (FULLWIDTH LEFT PARENTHESIS). Did you mean ( (LEFT PARENTHESIS)?

(RUF003)


27-27: Comment contains ambiguous (FULLWIDTH RIGHT PARENTHESIS). Did you mean ) (RIGHT PARENTHESIS)?

(RUF003)


32-32: Possible hardcoded password assigned to: "token"

(S105)


35-35: Possible hardcoded password assigned to: "next_token"

(S105)


37-37: Possible hardcoded password assigned to: "next_token"

(S105)


86-86: subprocess call: check for execution of untrusted input

(S603)


103-103: f-string without any placeholders

Remove extraneous f prefix

(F541)


110-110: f-string without any placeholders

Remove extraneous f prefix

(F541)


114-114: f-string without any placeholders

Remove extraneous f prefix

(F541)


116-116: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: claude-review
🔇 Additional comments (11)
.claude/hooks/pre_git_quality_gates.py (6)

1-18: LGTM!

The shebang, imports, and documentation are appropriate for this quality gates hook script.


19-25: LGTM!

Input parsing correctly uses shlex.split() for safe command tokenization and implements appropriate early exit.


27-42: LGTM!

The git command detection logic correctly identifies git commit and git push operations. The static analysis warnings about "token" variables are false positives—these are command tokens, not credentials.


44-78: LGTM!

The quality checks are well-structured and align with the documented gates in CLAUDE.md. The subprocess security warning from static analysis is a false positive—all commands are hardcoded and not derived from user input.


126-146: LGTM!

Failure reporting is comprehensive and actionable, with appropriate exit code (2) to block the git operation when quality gates fail.


148-149: LGTM!

Success case correctly exits with code 0 to allow the git operation to proceed.

.claude/CLAUDE.md (1)

94-117: LGTM! Excellent documentation aligned with quality standards.

The Quality Gates section clearly documents the pre-commit checks and hooks architecture. This aligns well with the retrieved learnings about applying automated quality gates for development. The references to detailed documentation are appropriate.

Based on learnings, this documentation properly follows the development quality standards defined in CLAUDE.md.

.claude/hooks/README.md (4)

1-84: LGTM! Comprehensive hook documentation.

The hook descriptions, triggers, and configuration examples are clear, accurate, and well-structured. The JSON configuration snippets are syntactically correct.


86-131: LGTM! Clear setup instructions.

The configuration steps are well-documented and complete, including the necessary permissions setup and restart requirement.


132-158: LGTM! Practical troubleshooting guidance.

The troubleshooting section addresses common issues with actionable solutions, including the helpful timeout adjustment example.


159-184: No action needed. The custom hooks template is well-structured and correct, and the Anthropic documentation URL is valid and accessible (returns HTTP 301 redirect status).

Comment on lines +112 to +114
except FileNotFoundError:
# スクリプトが存在しない場合はスキップ
print(f" ⚠️ スキップ (コマンドが見つかりません)", file=sys.stderr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Missing scripts should fail the gate, not skip silently.

When a required quality check script (e.g., security-credential-scan.sh) is missing, it's silently skipped without adding to failed_checks. This allows git operations to proceed even when critical security checks cannot run, defeating the purpose of quality gates.

🔎 Proposed fix to fail on missing scripts
     except FileNotFoundError:
-        # スクリプトが存在しない場合はスキップ
-        print(f"  ⚠️  スキップ (コマンドが見つかりません)", file=sys.stderr)
+        # スクリプトが存在しない場合は失敗として記録
+        failed_checks.append({
+            "name": check["name"],
+            "error": "コマンドが見つかりません"
+        })
+        print(f"  ❌ 失敗 (コマンドが見つかりません)", file=sys.stderr)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except FileNotFoundError:
# スクリプトが存在しない場合はスキップ
print(f" ⚠️ スキップ (コマンドが見つかりません)", file=sys.stderr)
except FileNotFoundError:
# スクリプトが存在しない場合は失敗として記録
failed_checks.append({
"name": check["name"],
"error": "コマンドが見つかりません"
})
print(f" ❌ 失敗 (コマンドが見つかりません)", file=sys.stderr)
🧰 Tools
🪛 Ruff (0.14.10)

114-114: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
In .claude/hooks/pre_git_quality_gates.py around lines 112-114, the
FileNotFoundError handler currently only prints a skip message; change it to
treat missing scripts as failures by appending a descriptive failure entry to
failed_checks (e.g., failed_checks.append((script_name, "script not found")))
and printing an error to stderr, and ensure the script sets a non-zero exit (or
lets the outer logic detect failed_checks) so the quality gate fails rather than
skipping; keep the message informative (include script name/path) and do not
swallow the exception silently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant