feat(github): add GHAS forensics tools — rulesets, code & secret scanning (#186)#188
Conversation
…ning (#186) Adds 7 read-only tools so 'mergeable: true, merge_state: blocked' PRs whose blocker lives in a repository ruleset or a code-scanning requirement can be root-caused from MCP git alone (classic branch protection doesn't expose these). Rulesets: github_list_rulesets, github_get_ruleset, github_get_branch_rules. Code scanning: github_list_code_scanning_alerts, github_list_code_scanning_analyses, github_get_code_scanning_default_setup. Secret scanning: github_list_secret_scanning_alerts. Closes #186 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Claude finished @MementoRC's task —— View job PR Review: feat(github): add GHAS forensics tools
Overall this is a clean, well-structured addition. The implementation follows the existing patterns in the codebase consistently. Below are observations ranging from functional issues to style improvements. Bugs / Functional Issues1. def _build_params(**kwargs: Any) -> dict[str, str]:
return {k: str(v) for k, v in kwargs.items() if v is not None}The condition 2. Missing Every other module ( __all__ = [
"github_list_rulesets",
"github_get_ruleset",
"github_get_branch_rules",
"github_list_code_scanning_alerts",
"github_list_code_scanning_analyses",
"github_get_code_scanning_default_setup",
"github_list_secret_scanning_alerts",
]3. No pagination support (scanning.py)
Code Quality / Style4. Inconsistent logging style with the rest of the codebase (scanning.py)
logger.debug(f"🔍 Getting vulnerability alerts status for {repo_owner}/{repo_name}")
5. Pydantic models lack input validation for enum-like string fields (models.py:1026-1029)
from typing import Literal
state: Literal["open", "closed", "dismissed", "fixed"] | None = None
severity: Literal["critical", "high", "medium", "low", "warning", "note", "error"] | None = None6. Redundant
Test Coverage7. No error-path tests for non-200/non-404 responses (test file) All 18 tests cover 200 (success) and 404 (not found). There are no tests for, e.g., 403 (insufficient scope), 422 (invalid params), 500 (server error), or the 8. call_kwargs = mock_client.get.call_args
params = call_kwargs[1]["params"]
Summary
The core logic is correct, the 404 handling mirrors existing patterns faithfully, and the diagnosis workflow described in the PR description is well thought out. Addressing pagination and |
…ation - Add per_page/page to the four GHAS list tools (rulesets, code-scanning alerts/analyses, secret-scanning alerts) — endpoints paginate (30 default, 100 max); previously only the first page was returned. - Add __all__ to scanning.py so wildcard re-export hides logger/_build_params. - Drop empty-string query params in _build_params (keep False/0). - Literal-constrain code-scanning state/severity and secret-scanning state for schema-documented validation. - Add 403 / exception error-path tests; use call_args.kwargs in assertions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the thorough review — addressed in c03c369: Functional
Quality
Tests
Intentionally not changed (you flagged these as fine):
|
|
Claude finished @MementoRC's task —— View job PR Review: feat(github): add GHAS forensics tools (follow-up on c03c369)
All 7 items from the previous review have been addressed. Here's the verification: Fixes Verified ✓
Remaining Observations (minor, not blocking)1. Inconsistent 403 test coverage
2. The docstring says 3. The GitHub code scanning API uses 4. No test for The 200 and 404 cases are covered but not the exception path. Minor given the straightforward implementation. SummaryThe implementation is clean, correct, and follows all existing patterns. All substantive issues from the first review have been properly resolved. The remaining observations are minor and non-blocking. This PR is ready to merge. |
Adds 403 tests for github_get_ruleset, github_get_branch_rules, github_list_code_scanning_analyses, github_get_code_scanning_default_setup, and an exception-path test for default_setup, so every GHAS tool has uniform error-path coverage (PR #188 follow-up). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Closed out the remaining minor observations in b349cc2 (test-only):
|
|
Claude finished @MementoRC's task —— View job PR Review: feat(github): add GHAS forensics tools (round 3 — b349cc2)
All three rounds of review are now complete. The implementation is in excellent shape. Here's a final verification pass against the full set of files. All Previous Issues Resolved ✓
Final Code Quality Assessment
Test file — 30+ tests across 7 tools covering: 200 success, 404 not-found, 403 forbidden, exception paths, filter param forwarding, None param omission, and pagination forwarding. Test isolation via One Observation (non-blocking)
SummaryThe implementation is complete, correct, and thoroughly tested. The diagnosis workflow described in the PR ( |
Closes #186.
Summary
Adds 7 read-only GitHub tools so a
mergeable: true, merge_state: blockedPR — all checks green,required_approving_review_count: 0— can be root-caused from MCP git alone. The blocker for that class (e.g. Claire-s-Monster/ci-framework#207, a Dependabot bump where CodeQL passes in 2s but the PR sits blocked) is invariably a repository ruleset or a code-scanning requirement, neither of which classicgithub_get_branch_protectionexposes.New tools
Rulesets
github_list_rulesets(repo_owner, repo_name)—GET /repos/{o}/{r}/rulesetsgithub_get_ruleset(repo_owner, repo_name, ruleset_id)—GET /repos/{o}/{r}/rulesets/{id}(full config: required_status_checks, code_scanning, bypass actors)github_get_branch_rules(repo_owner, repo_name, branch)—GET /repos/{o}/{r}/rules/branches/{branch}(which classic+ruleset rules apply to a branch)Code scanning
github_list_code_scanning_alerts(..., state, severity, tool_name, ref)—GET /repos/{o}/{r}/code-scanning/alertsgithub_list_code_scanning_analyses(..., ref, tool_name)—GET /repos/{o}/{r}/code-scanning/analyses(ref supportsrefs/pull/{n}/head)github_get_code_scanning_default_setup(repo_owner, repo_name)—GET /repos/{o}/{r}/code-scanning/default-setupSecret scanning
github_list_secret_scanning_alerts(repo_owner, repo_name, state)—GET /repos/{o}/{r}/secret-scanning/alertsImplementation
github/scanning.py(kept out ofsecurity.py, which was at 516 lines — adding here would have breached the 500-line organism limit). Wired viaapi.py's wildcard re-export.github_client_context()auth pattern; 404 returns a structured❌ … not foundstring mirroringgithub_get_required_signatures. Optional filters are sent as query params, omitted whenNone.github/models.py; 7ToolDefinitions inlean/registry_github.py.tests/unit/github/test_github_ghas_forensics.py: 18 tests (success + 404 per tool, plus query-param forwarding / None-omission for the filtered list tools).Diagnosis path this unlocks (the #207 case)
github_get_branch_rules(development)→ ruleset id →github_get_ruleset(id)→ checkcode_scanningrequirement →github_list_code_scanning_analyses(ref=refs/pull/207/head)→ confirm empty/insufficient results.Test plan
pixi run -e quality test-unit— passes (exit 0)pixi run -e quality lint(ruff F,E9) — cleansecurity_events: readscope on the token (the existing PAT that powersgithub_get_security_analysisalready has it). Requires an MCP server restart to expose the new tools.🤖 Generated with Claude Code