Skip to content

feat: Quality Gates をリポジトリ自動検出方式に刷新 - #498

Merged
keito4 merged 2 commits into
mainfrom
feat/quality-gates-auto-detect
Feb 21, 2026
Merged

feat: Quality Gates をリポジトリ自動検出方式に刷新#498
keito4 merged 2 commits into
mainfrom
feat/quality-gates-auto-detect

Conversation

@keito4

@keito4 keito4 commented Feb 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Quality Gates の pre_git_quality_gates.pypackage.jsonscripts 自動検出方式にリファクタリング
  • パッケージマネージャー(npm/pnpm/yarn/bun)をロックファイルから自動判定
  • config-base イメージに組み込まれるため、全 DevContainer/Codespaces 環境でデフォルト有効

Test plan

  • フォーマットチェック通過
  • Lint 通過
  • テスト全件通過(101 tests passed)
  • git commit 入力でチェック実行を確認
  • git push 入力でチェック実行を確認
  • 非 git コマンドはスルーすることを確認
  • package.json がないリポジトリではスキップを確認

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Quality checks are now auto-detected from your project's scripts and run in priority order when applicable
    • Package manager (npm/pnpm/yarn/bun) is auto-detected from lockfiles
  • Bug Fixes / Improvements

    • More robust detection of repository root and tool availability with clearer status messages and handling of missing tools
  • Documentation

    • Docs updated to reflect automatic quality gate execution before git operations and default enablement in DevContainer/Codespaces

package.json の scripts を自動解析して利用可能なチェックを検出する方式に変更。
npm/pnpm/yarn/bun のパッケージマネージャー自動判定にも対応し、
config-base イメージ経由で全 DevContainer/Codespaces 環境にデフォルト適用される。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Feb 21, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Refactors pre-git quality gates to dynamically detect and run checks from package.json scripts, adds package-manager and repo-root detection, updates hooks/config location, and revises documentation to describe the new auto-discovery behavior.

Changes

Cohort / File(s) Summary
Documentation
.claude/CLAUDE.md, .claude/hooks/README.md, README.md
Replaced static checks list with dynamic auto-detection from package.json scripts; updated wording to reference .claude/settings.json, package manager detection, DevContainer/Codespaces support, and a mapping table of detected checks to script names.
Quality Gates Script
.claude/hooks/pre_git_quality_gates.py
Replaced hard-coded checks with dynamic discovery and execution: adds detect_package_manager(), get_package_scripts(), has_node_modules(); determines repo_root via git rev-parse; detects package manager and node modules; assembles prioritized checks (format, lint, test, typecheck, shellcheck, optional scripts) and handles timeouts, missing commands, skips, and unified exit codes and messaging.
Hook config / metadata
.claude/.claude* (settings reference updates)
Changed hooks config source reference from .claude/settings.local.json to .claude/settings.json and documented auto-trigger behavior and config-base image defaults.

Sequence Diagram(s)

sequenceDiagram
  participant Git as Git (pre-commit/push)
  participant Hook as pre_git_quality_gates.py
  participant FS as Repo FS (package.json, scripts)
  participant PM as Package Manager / Tooling (npm/pnpm/yarn/bun, node_modules)
  Git->>Hook: Trigger hook
  Hook->>FS: resolve repo_root (git rev-parse)
  Hook->>PM: detect package manager & node_modules
  Hook->>FS: read package.json scripts
  alt checks found
    Hook->>PM: run detected checks (format, lint, test, typecheck, shellcheck, optional scripts)
    PM-->>Hook: stdout/stderr, exit codes
    Hook->>Git: return success or failure (0 or 2) with summarized output
  else no applicable checks
    Hook->>Git: exit 0 (no-op)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size/M

Poem

🐇 I sniffed the package.json tonight,
scripts lit up, tools in gentle light.
Bun or npm, yarn or pnpm's song,
checks hop in order, tidy and strong.
Quality gates hum — the repo's feeling right! 🎉

🚥 Pre-merge checks | ✅ 3
✅ 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 accurately describes the main change: refactoring Quality Gates to use automatic detection from the repository, which aligns with the primary objective of dynamic detection from package.json scripts.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/quality-gates-auto-detect

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.

@keito4

keito4 commented Feb 21, 2026

Copy link
Copy Markdown
Owner Author

🔍 AI Code Review (Local Hook)

Models: Codex (default) / Gemini (default)

🤖 Codex Review

  1. Yarn PnP を使用するリポジトリで node_modules が存在しないため、常にコミット/プッシュがブロックされます。Yarn PnP は正当な構成なのに失敗扱いになる回帰です。影響: Git 操作が恒常的に阻害される。 .claude/hooks/pre_git_quality_gates.py:76-96

patch is incorrect。理由: Yarn PnP 構成で無条件に失敗する回帰があり、通常の開発フローを阻害します。信頼度 0.64


⚠️ 修正が必要です

上記のレビューで問題が指摘されています。修正してからマージしてください。


🤖 Generated by post_pr_ai_review.py hook

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.claude/hooks/README.md (1)

97-131: ⚠️ Potential issue | 🟡 Minor

Inconsistency: README instructs manual settings.local.json setup, but CLAUDE.md says hooks are already in settings.json

CLAUDE.md (line 137) states: "これらは .claude/settings.jsonhooks フィールドで設定されており" — meaning the hooks are already committed in settings.json and active by default (especially in the config-base image). But this README section still tells users to manually add the same config to settings.local.json as a required setup step, which is contradictory.

Consider one of:

  1. Removing or retitling this section to "カスタマイズ / オーバーライド方法" so it's clear the steps are optional.
  2. Adding a note at the top: "settings.json に既に設定済みです。追加カスタマイズが必要な場合のみ、以下の手順で settings.local.json に上書き設定できます。"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/README.md around lines 97 - 131, README inconsistency: update
the Hooksの設定方法 section to clarify that the `hooks` are already present in
`.claude/settings.json` (as stated in CLAUDE.md) and that adding entries to
`.claude/settings.local.json` is optional for customization/overrides; either
change the section title to "カスタマイズ / オーバーライド方法" or add a top note such as
"`settings.json` に既に設定済みです。追加カスタマイズが必要な場合のみ、以下の手順で `settings.local.json`
に上書き設定できます。" and keep the example JSON showing the `hooks` field for reference.
Ensure you reference the `hooks` field and the filenames `.claude/settings.json`
and `.claude/settings.local.json` in the edit.
🧹 Nitpick comments (1)
.claude/hooks/pre_git_quality_gates.py (1)

40-49: Consider checking returncode explicitly after git rev-parse

The missing-path case is handled by the if not repo_root guard at line 48, but an explicit returncode check would be clearer and avoids relying on stdout being empty when git fails.

🔧 Suggested clarification
     result = subprocess.run(
         ["git", "rev-parse", "--show-toplevel"],
         capture_output=True, text=True, timeout=10
     )
-    repo_root = result.stdout.strip()
+    if result.returncode != 0:
+        sys.exit(0)
+    repo_root = result.stdout.strip()
 except Exception:
     sys.exit(0)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/pre_git_quality_gates.py around lines 40 - 49, Check
result.returncode after calling subprocess.run in the block that invokes git
rev-parse: if result.returncode is non-zero, exit early (sys.exit(0)) instead of
relying on result.stdout being empty; update the logic around the result
variable and repo_root assignment in pre_git_quality_gates.py so you only set
repo_root from result.stdout when returncode == 0 and otherwise handle the
failure path explicitly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/hooks/pre_git_quality_gates.py:
- Around line 99-105: The comment above CHECK_CANDIDATES mentions a fallback to
"format" but the Format Check candidate's script_names currently only lists
["format:check"], causing repos with only a "format" script to skip checks;
either remove "format" from the comment if fallback is not intended, or add
"format" to the Format Check candidate's script_names (i.e., update the
CHECK_CANDIDATES entry for the Format Check to include both "format:check" and
"format") so that projects with only a "format" script are handled; modify the
CHECK_CANDIDATES array accordingly and keep the description/label ("Format
Check") unchanged.

---

Outside diff comments:
In @.claude/hooks/README.md:
- Around line 97-131: README inconsistency: update the Hooksの設定方法 section to
clarify that the `hooks` are already present in `.claude/settings.json` (as
stated in CLAUDE.md) and that adding entries to `.claude/settings.local.json` is
optional for customization/overrides; either change the section title to "カスタマイズ
/ オーバーライド方法" or add a top note such as "`settings.json`
に既に設定済みです。追加カスタマイズが必要な場合のみ、以下の手順で `settings.local.json` に上書き設定できます。" and keep
the example JSON showing the `hooks` field for reference. Ensure you reference
the `hooks` field and the filenames `.claude/settings.json` and
`.claude/settings.local.json` in the edit.

---

Nitpick comments:
In @.claude/hooks/pre_git_quality_gates.py:
- Around line 40-49: Check result.returncode after calling subprocess.run in the
block that invokes git rev-parse: if result.returncode is non-zero, exit early
(sys.exit(0)) instead of relying on result.stdout being empty; update the logic
around the result variable and repo_root assignment in pre_git_quality_gates.py
so you only set repo_root from result.stdout when returncode == 0 and otherwise
handle the failure path explicitly.

Comment on lines +99 to 105
# 優先度順: format:check > format > lint > test > typecheck > shellcheck
CHECK_CANDIDATES = [
{
"name": "Format Check",
"command": ["npm", "run", "format:check"],
"script_names": ["format:check"],
"label": "Format Check",
"description": "コードフォーマットの検証",
"install_hint": "npm install"
},

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 | 🟡 Minor

Comment-code discrepancy: format fallback is documented but not implemented

Line 99 comment lists format as a fallback priority (after format:check), but script_names for the Format Check candidate only contains ["format:check"]. Projects with only a format script will silently skip format checking.

If the omission is intentional — because format auto-modifies files and is unsuitable for a blocking gate — remove format from the comment. If it's meant to be a fallback, add it to script_names.

🐛 Option A — correct the comment (recommended if auto-fix scripts should be excluded)
-# 優先度順: format:check > format > lint > test > typecheck > shellcheck
+# 優先度順: format:check > lint > test > typecheck > shellcheck
🐛 Option B — implement the fallback (if read-only `format` scripts exist in your repos)
     {
-        "script_names": ["format:check"],
+        "script_names": ["format:check", "format"],
         "label": "Format Check",
         "description": "コードフォーマットの検証",
     },
📝 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
# 優先度順: format:check > format > lint > test > typecheck > shellcheck
CHECK_CANDIDATES = [
{
"name": "Format Check",
"command": ["npm", "run", "format:check"],
"script_names": ["format:check"],
"label": "Format Check",
"description": "コードフォーマットの検証",
"install_hint": "npm install"
},
# 優先度順: format:check > lint > test > typecheck > shellcheck
CHECK_CANDIDATES = [
{
"script_names": ["format:check"],
"label": "Format Check",
"description": "コードフォーマットの検証",
},
Suggested change
# 優先度順: format:check > format > lint > test > typecheck > shellcheck
CHECK_CANDIDATES = [
{
"name": "Format Check",
"command": ["npm", "run", "format:check"],
"script_names": ["format:check"],
"label": "Format Check",
"description": "コードフォーマットの検証",
"install_hint": "npm install"
},
# 優先度順: format:check > format > lint > test > typecheck > shellcheck
CHECK_CANDIDATES = [
{
"script_names": ["format:check", "format"],
"label": "Format Check",
"description": "コードフォーマットの検証",
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/hooks/pre_git_quality_gates.py around lines 99 - 105, The comment
above CHECK_CANDIDATES mentions a fallback to "format" but the Format Check
candidate's script_names currently only lists ["format:check"], causing repos
with only a "format" script to skip checks; either remove "format" from the
comment if fallback is not intended, or add "format" to the Format Check
candidate's script_names (i.e., update the CHECK_CANDIDATES entry for the Format
Check to include both "format:check" and "format") so that projects with only a
"format" script are handled; modify the CHECK_CANDIDATES array accordingly and
keep the description/label ("Format Check") unchanged.

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 236: The README's opening paragraph claims checks are detected by parsing
package.json scripts but two table rows are file paths
(script/security-credential-scan.sh, script/code-complexity-check.sh), causing
inconsistency; update the documentation to explicitly state that checks are
detected via two mechanisms—parsing package.json scripts and checking for the
existence of specific shell-script files—and either split the table into two
labeled sections ("package.json script detection" and "file-existence
detection") or add a clarifying note above the table listing the file-based
checks (including the two paths script/security-credential-scan.sh and
script/code-complexity-check.sh) so readers understand why those rows differ
from script names.

Comment thread README.md
4. ShellCheck (`npm run shellcheck`)
5. Security Credential Scan (`./script/security-credential-scan.sh`)
6. Code Complexity Check (`./script/code-complexity-check.sh`)
`package.json` の `scripts` を解析し、利用可能なチェックを自動検出して実行します。パッケージマネージャー(npm / pnpm / yarn / bun)もロックファイルから自動判定されます。

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 | 🟡 Minor

Documentation inconsistency: package.json script detection vs. file-existence detection

The opening paragraph states that checks are detected by parsing package.json scripts, but the last two table rows list shell-script file paths (script/security-credential-scan.sh, script/code-complexity-check.sh) — these are clearly file-existence checks, not package.json script names. Readers following the description will not understand why those two rows look different from the others.

✏️ Suggested clarification
-`package.json` の `scripts` を解析し、利用可能なチェックを自動検出して実行します。パッケージマネージャー(npm / pnpm / yarn / bun)もロックファイルから自動判定されます。
+`package.json` の `scripts` を解析し、利用可能なチェックを自動検出して実行します。一部のチェックはスクリプトファイルの存在確認によって検出されます。パッケージマネージャー(npm / pnpm / yarn / bun)もロックファイルから自動判定されます。

Or, split the table into two sections (package.json script detection / file-existence detection) to make the mechanism explicit.

Also applies to: 245-246

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 236, The README's opening paragraph claims checks are
detected by parsing package.json scripts but two table rows are file paths
(script/security-credential-scan.sh, script/code-complexity-check.sh), causing
inconsistency; update the documentation to explicitly state that checks are
detected via two mechanisms—parsing package.json scripts and checking for the
existence of specific shell-script files—and either split the table into two
labeled sections ("package.json script detection" and "file-existence
detection") or add a clarifying note above the table listing the file-based
checks (including the two paths script/security-credential-scan.sh and
script/code-complexity-check.sh) so readers understand why those rows differ
from script names.

@keito4
keito4 merged commit f293fb4 into main Feb 21, 2026
7 checks passed
@claude

claude Bot commented Feb 21, 2026

Copy link
Copy Markdown
Contributor

Claude Code レビュー

注意: このPRはすでにマージ済みです。フィードバックは今後の改善参考用として記録します。


全体評価

良い点:

  • git rev-parse --show-toplevel でリポジトリルートを確実に取得するアプローチは堅牢
  • package.json スクリプトの自動検出により、リポジトリ固有の設定が不要になった設計は優秀
  • subprocess.run をリスト引数で呼んでいるため、コマンドインジェクションのリスクなし
  • os.access(script_path, os.X_OK) で実行可能性を確認してから追加する点が適切
  • cwd=repo_root への変更で、サブディレクトリからの実行でも正しく動作するようになった

指摘事項

1. Bun環境での node_modules チェック(軽微)

if not has_node_modules(repo_root):
    ...
    sys.exit(2)

Bun は bun runnode_modules なしにスクリプトを実行できるケースがあります(特にBun workspacesや bun.lockb バイナリ形式のプロジェクト)。Bunが検出された場合は、node_modules がなくてもスキップ扱いにする(sys.exit(0))か、警告のみにする選択肢を検討する価値があります。

2. package.json 解析失敗時のサイレント終了

except Exception:
    return {}

JSONが不正な場合に空辞書を返すため、その後 if not scripts: sys.exit(0) でサイレントスキップします。解析エラーは sys.stderr に警告を出した方がデバッグしやすいです:

except json.JSONDecodeError as e:
    print(f"[Quality Gates] package.json のパースに失敗: {e}", file=sys.stderr)
    return {}
except Exception:
    return {}

3. tsc スクリプト名の誤検出リスク(軽微)

{"script_names": ["typecheck", "type-check", "tsc"], ...}

一部のプロジェクトでは "tsc": "tsc --noEmit" のような汎用スクリプト名を定義することがありますが、問題なく動作します。ただし tsc が定義されているリポジトリでは意図せず実行される可能性があります。優先度を typecheck > type-check > tsc にしている点は正しいアプローチです。

4. is_empty_output ロジックの削除について

旧コードにあった空出力チェックが削除されていますが、これは正しい判断です。ツール未インストール検出は exit code 127 と stderr の文字列マッチで十分です(実際のCI環境では空出力でも失敗とみなすべき)。

5. CHECK_CANDIDATES コメントとコードの不一致(coderabbitai 既指摘)

コメント「優先度順: format:check > format > lint ...」と実装の script_namesformat が含まれていない点は、コメントを修正するか formatscript_names に追加するかで対応してください。


テストカバレッジ

pre_git_quality_gates.py 自体の自動テストが確認できません。以下のようなテストケースが将来的にあると品質が高まります:

  • package.json がない場合のスキップ動作
  • 各パッケージマネージャーの検出ロジック
  • スクリプト検出と優先順位

総評

全体的に品質が高く、設計も適切です。特に「package.json を信頼の源にする」アプローチは、リポジトリ多様性への対応として理にかなっています。上記の指摘はすべて軽微で、マージ判断は妥当です。

🤖 Reviewed by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.81.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

released リリース済み

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant