fix(gerrit): use action parameter for dispatch and clean up temp repos#2324
fix(gerrit): use action parameter for dispatch and clean up temp repos#2324
Conversation
The Gerrit server had two bugs:
1. The {action} path parameter was captured but ignored - the server
always dispatched based on item.msg content. Now the action parameter
determines the command, with item.msg only used for the "ask" action
to provide the question text. Also made item.msg optional (defaults
to empty string) since non-ask actions don't need it, and fixed
`return HTTPException` to `raise HTTPException`.
2. prepare_repo() created a temp directory via mkdtemp() that was never
cleaned up - remove_initial_comment() had shutil.rmtree commented
out. Added a cleanup() method to GerritProvider that removes the
temp repo, called from the server's finally block after each request.
Also added __del__ as a safety net, and wired remove_initial_comment()
to delegate to cleanup().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review Summary by QodoFix Gerrit action parameter dispatch and add temp repo cleanup
WalkthroughsDescription• Use action parameter to determine command dispatch instead of item.msg • Fix HTTPException to be raised instead of returned for proper error handling • Add cleanup() method to GerritProvider to remove temporary repositories • Call cleanup() in finally block after each request to prevent temp directory leaks Diagramflowchart LR
A["Gerrit Request<br/>with action param"] -->|"action determines<br/>command"| B["PRAgent<br/>handle_request"]
B -->|"try block"| C["Process Request"]
C -->|"finally block"| D["GerritProvider<br/>cleanup"]
D -->|"removes"| E["Temp Directory"]
F["HTTPException<br/>raise not return"] -->|"proper 400<br/>status code"| G["Error Response"]
File Changes1. pr_agent/git_providers/gerrit_provider.py
|
Code Review by Qodo
|
- cleanup(): catch (OSError, PermissionError) instead of broad Exception - gerrit_server finally block: catch (LookupError, RuntimeError) for starlette context access failures instead of bare Exception - Add isinstance guard for git_providers dict before iterating - Document that GerritProvider.__del__ acts as safety net when the provider is never stored in context (e.g. early failure)
|
Persistent review updated to latest commit 16e6a5e |
| def remove_initial_comment(self): | ||
| # remove repo, cloned in previous steps | ||
| # shutil.rmtree(self.repo_path) | ||
| pass | ||
| self.cleanup() |
There was a problem hiding this comment.
1. Repo deleted mid-execution 🐞 Bug ≡ Correctness
GerritProvider.remove_initial_comment() now calls cleanup(), which deletes the cloned temp repo even though PR-Agent tools call remove_initial_comment() before later steps that still need repo_path (e.g., publishing code suggestions). This can cause subsequent file operations in publish_code_suggestions() to fail because the repo directory has already been removed.
Agent Prompt
### Issue description
`GerritProvider.remove_initial_comment()` is part of the GitProvider interface and is called mid-flow by multiple tools to remove a temporary “preparing…” comment. In this PR it now deletes the cloned temp repo, which can break later steps in the same request that still need `repo_path` (e.g., `publish_code_suggestions`).
### Issue Context
For Gerrit, temp repo lifecycle should be cleaned up at the *end* of the request (your new `finally` block in `gerrit_server.py` is the right place). Deleting the repo inside `remove_initial_comment()` changes semantics and can invalidate the provider during the ongoing run.
### Fix Focus Areas
- pr_agent/git_providers/gerrit_provider.py[409-410]
### Suggested change
Make `remove_initial_comment()` a no-op again (or only handle comment deletion semantics), and keep repo cleanup exclusively in `GerritProvider.cleanup()` invoked from the server `finally` (plus optional safety-net `__del__`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
Closing to reopen from fork (lost push access to org branch). |
Summary
{action}path parameter inPOST /api/v1/gerrit/{action}was captured but never used for command dispatch. Instead,item.msgwas always passed as the command. Now the action enum value determines the command (/review,/describe, etc.), withitem.msgonly appended for theaskaction. Also mademsgoptional with a default empty string since non-ask actions don't require it.return HTTPException(...)silently returns a 200 with the exception object serialized as JSON. Changed toraise HTTPException(...)so the 400 status code is actually sent.prepare_repo()creates a temp directory viamkdtemp()butremove_initial_comment()hadshutil.rmtreecommented out. Added acleanup()method toGerritProviderthat safely removes the temp directory, called from the server'sfinallyblock after each request. A__del__method serves as a safety net.remove_initial_comment()now delegates tocleanup().Test plan
POST /api/v1/gerrit/reviewwith emptymsgdispatches/reviewcommand (not/)POST /api/v1/gerrit/askwithmsg: "what does this do?"dispatches/ask what does this do?POST /api/v1/gerrit/askwith emptymsgreturns 400/tmp/are cleaned up after request completeshandle_requestraises an exception🤖 Generated with Claude Code