feat(github): fix security/quality findings and ship PRs with auto-detected coding agents - #4597
Conversation
…tected coding agents Add the fix_github_security_alert action tool: resolve a Dependabot, code-scanning, or Code Quality finding, fix it in the local checkout (built-in ruff fixers first), and optionally commit/push a fresh opensre/github-security-fix-* branch and open a PR. Make the coding-agent seam multi-backend and zero-config: CODING_AGENT now defaults to auto, which picks the first ready backend among Pi, Claude Code (claude -p acceptEdits), and Codex (codex exec workspace-write). Shared machinery moves to leaf modules (integrations/llm_cli/agent_exec.py, integrations/git/worktree_capture.py) and the Pi client is refactored onto them; tests migrated in the same change. When no agent is ready the tool now returns one actionable line instead of a vague coding-agent-fallback message. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile code reviewThis repo uses Greptile for automated review. Before merge, aim for Confidence Score: 5/5 with zero unresolved review threads — see CONTRIBUTING.md. Run a review — add a PR comment with: Give it ~5-10 minutes (sometimes longer) for results, then fix feedback and re-trigger until you reach Confidence Score: 5/5. Optional: automate with the greploop skill. |
Greptile SummaryThis PR adds GitHub security and quality finding remediation with optional pull-request shipping.
Confidence Score: 4/5The PR should not be merged until timeout cleanup reliably terminates coding-agent descendants on every supported platform. The stale-line import deletion has been corrected, but the timeout path still falls back to terminating only the immediate CLI process when POSIX process-group APIs are unavailable, so spawned tests, linters, or other descendants can continue consuming resources or editing the checkout after a timeout is reported. Files Needing Attention: integrations/llm_cli/agent_exec.py
|
| Filename | Overview |
|---|---|
| integrations/github/tools/security_fix/local_fix.py | Adds Ruff-backed deterministic fixes and now avoids applying original finding coordinates after Ruff has rewritten the file. |
| integrations/llm_cli/agent_exec.py | Centralizes guarded CLI execution and adds POSIX process-group timeout cleanup, while non-POSIX fallback cleanup remains limited to the direct child. |
| integrations/github/tools/security_fix/runner.py | Coordinates alert resolution, baseline capture, remediation, and optional PR shipping. |
| integrations/github/tools/security_fix/ship.py | Implements branch creation, scoped commits, pushing, and pull-request creation for completed fixes. |
| integrations/coding_agent/runner.py | Adds automatic readiness-based selection among Pi, Claude Code, and Codex backends. |
| integrations/github/pull_requests.py | Extracts reusable GitHub pull-request creation and stable error mapping from the Sentry-specific implementation. |
Sequence Diagram
sequenceDiagram
participant User
participant Tool as GitHub security-fix tool
participant GitHub
participant Fixer as Built-in fixer / coding agent
participant Git as Local Git checkout
User->>Tool: Fix finding, optionally open PR
Tool->>GitHub: Resolve alert details
Tool->>Git: Validate repository and capture baseline
Tool->>Fixer: Apply remediation
Fixer->>Git: Edit and verify files
Tool->>Git: Capture changed paths
alt PR requested and approved
Tool->>Git: Create branch and commit fix paths
Tool->>GitHub: Push branch and open PR
GitHub-->>Tool: PR URL
end
Tool-->>User: Result or actionable error
Reviews (2): Last reviewed commit: "Merge branch 'main' into feat/security_i..." | Re-trigger Greptile
Drop stale fix_sentry_issue.pr ignore_imports (module removed) and allow ship → pull_requests. Skip the F401 line-delete fallback after Ruff rewrites the file, and terminate coding-agent process groups on timeout.
The findings API returns only an authenticated api.github.com url
(html_url is null). Synthesize github.com/security/quality/findings/{n}
so tasks, PR bodies, and tool responses never link to a 401 API endpoint.
## Summary **Root cause:** `test_run_pi_coding_task_timeout` drives the timeout path in `poll_agent_process`, which calls `_signal_process_group` (integrations/llm_cli/agent_exec.py:121). That function reads `proc.pid`, but the test's `_FakePopen` stand-in never defined a `pid` attribute → `AttributeError`. **Change (1 file):** - `tests/integrations/test_pi.py` — added `self.pid: int | None = None` to `_FakePopen.__init__`. With `pid=None`, `_signal_process_group` skips the `os.killpg` branch and uses its documented `terminate()`/`kill()` fallback, which the fake implements. This also guarantees tests never signal a real process group. No production code was touched — the `pid is not None` guard in `agent_exec.py` already handles this case correctly; the fake was just incomplete. **Verification:** - `uv run python -m pytest tests/integrations/test_pi.py -q` → 11 passed, 1 skipped (opt-in live test) - `ruff check` + `ruff format --check` on the edited file → clean Per instructions, I did not commit or push; the fix is in the working tree alongside your other uncommitted changes. Generated by OpenSRE from #4597.
|
@greptile review |
Add fix_github_pr_ci to inspect failing Actions checks, run an auto-detected coding agent, and push fixes to the existing PR branch. Skip cancelled sibling checks, sanitize markdown headings out of commit subjects, and make process-group cleanup tolerate test doubles without pid.
Resolve action_driver conflict by keeping main's turn helpers while preserving preferred tool response_text over chatty model closings. Drop stale FLEET_CDK exports and update the harness test to ActionTurnRunner.
Ensure local commits and CI formula/readme bump commits include the OpenSRE Agent trailer so agent-authored changes stay attributable.
The git helpers import these trailers; keep the constants module in the repo so the branch stays importable after the co-author stamp landed.
Compress github_cli skill guidance under the registry char budget, classify fix_github_pr_ci for Sentry telemetry coverage, and refresh the action-system prompt characterization snapshot.
|
🤖 CI passed. Linter didn't scream. Reviewer typed LGTM. @VaibhavUpreti, every machine in this pipeline just slow-clapped. 🖥️✨ 👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome. |

Fixes #
Describe the changes you have made in this PR -
This PR adds the GitHub security/quality fix + PR capability to the interactive shell, and makes the fixer actually work on machines without the Pi CLI by turning the coding-agent seam into a multi-backend, auto-detected one.
Feature (fix + ship a PR from a GitHub finding):
fix_github_security_alertaction tool (integrations/github/tools/security_fix/): resolves a Dependabot / code-scanning / Code Quality finding (exact alert, URL, or highest-severity auto-selection), fixes it in the local checkout, and withopen_pr=truecommits only the changed files to a freshopensre/github-security-fix-*branch, pushes, and opens a PR. Secret-scanning alerts are refused (rotation first).integrations/github/pull_requests.py(also adopted byfix_sentry_issue, whose localpr.pyis removed).github_security_fix) + docs page (docs/github-security-fix.mdx), wired intodocs.json.response_textfor user-facing output, so the reply is the tool's one-line result instead of model-invented "options" lists.Coding-agent seam: auto-detected multi-backend (the "shitty response" fix):
Previously
CODING_AGENTdefaulted topiand Pi was the only backend, so any finding without a built-in fixer dead-ended in "the built-in fixer couldn't produce a patch… configure a coding agent" — even on machines with Claude Code or Codex installed.integrations/coding_agent/now has three backends: Pi, Claude Code (claude -p --permission-mode acceptEdits --allowedTools …), and Codex (codex exec -s workspace-write).CODING_AGENTdefaults toauto: the runner picks the first installed-and-authenticated backend (pi → claude-code → codex). A concrete name (or aliasclaude) pins one.integrations/llm_cli/agent_exec.py— injection-guarded task prompt, deadline-polled subprocess with pipe draining, outcome classification (provider limit markers).integrations/git/worktree_capture.py— tolerant changed-files + diff capture (tracked edits + untracked files).integrations/pi/client.pyand the security-fix local fixer are refactored onto these (no behavior change; tests migrated in the same change).Demo/Screenshot for feature changes and bug fixes -
Auto-detection on a machine without Pi (previously this configuration dead-ended):
Test run:
Code Understanding and AI Usage
Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?
If you used AI assistance:
Explain your implementation approach:
core/llm— rejected as a large new surface duplicating what installed coding CLIs already do well; (b) keeping Pi-only and just improving the error — rejected because it still can't fix anything on most machines.run_coding_task/verify_coding_agent) and register additional backends behind it, exactly as its module docstring anticipated. Auto-detection makes it zero-config; the seam's callers are unchanged.agent_exec.py(generic "hands"-role subprocess machinery — moved from the Pi client so all backends share the prompt-injection guard, deadline polling, and limit-marker classification),worktree_capture.py(what-changed capture),claude_code_backend.py/codex_backend.py(vendor argv/env + verify via the existing llm_cli adapters'detect()),runner.py(autoresolution order pi → claude-code → codex), and thesecurity_fixtool package (alert context → fix → confirm → branch/commit/push/PR).Checklist before requesting a review
🤖 Generated with Claude Code