feat: add bl pr commands (list/count/show/create/update/comment/attachment)#104
feat: add bl pr commands (list/count/show/create/update/comment/attachment)#104
Conversation
📝 WalkthroughWalkthroughAdds full pull-request support: new API models and BacklogClient methods, 12+ CLI subcommands for PR lifecycle, comments, and attachments, wiring into main CLI and docs; includes unit tests for API and command handlers. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI
participant BacklogClient
participant BacklogAPI
participant Filesystem
CLI->>BacklogClient: download_pull_request_attachment(project, repo, number, attachment_id)
BacklogClient->>BacklogAPI: GET /.../pullRequests/{number}/attachments/{attachmentId}
BacklogAPI-->>BacklogClient: 200 OK (bytes + Content-Disposition filename)
BacklogClient-->>CLI: (bytes, filename)
CLI->>Filesystem: write file (path, bytes)
Filesystem-->>CLI: success
CLI-->>User: "Saved attachment to <path> (<n> bytes)"
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
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. Comment |
There was a problem hiding this comment.
Pull request overview
Adds bl pr functionality to the CLI by introducing pull request API models/endpoints, wiring new clap subcommands, and documenting the new commands.
Changes:
- Added Backlog API v2 pull request structs + client/trait methods (PRs, comments, attachments).
- Implemented
bl prCLI commands (list/count/show/create/update + comment/attachment subcommands) with unit tests. - Updated command documentation and the command coverage/status tables (EN/JA).
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| website/i18n/ja/docusaurus-plugin-content-docs/current/commands.md | Adds Japanese docs for bl pr ... commands and marks them implemented in the coverage table. |
| website/docs/commands.md | Adds English docs for bl pr ... commands and marks them implemented in the coverage table. |
| src/main.rs | Adds clap subcommand wiring for bl pr and nested comment/attachment commands. |
| src/cmd/pr/mod.rs | Introduces cmd::pr module exports. |
| src/cmd/pr/list.rs | Implements bl pr list output + tests. |
| src/cmd/pr/count.rs | Implements bl pr count output + tests. |
| src/cmd/pr/show.rs | Implements bl pr show output + tests. |
| src/cmd/pr/create.rs | Implements bl pr create + tests. |
| src/cmd/pr/update.rs | Implements bl pr update (+ validation via try_new) + tests. |
| src/cmd/pr/comment/mod.rs | Introduces cmd::pr::comment module exports. |
| src/cmd/pr/comment/list.rs | Implements bl pr comment list + tests. |
| src/cmd/pr/comment/count.rs | Implements bl pr comment count + tests. |
| src/cmd/pr/comment/add.rs | Implements bl pr comment add + tests. |
| src/cmd/pr/comment/update.rs | Implements bl pr comment update + tests. |
| src/cmd/pr/attachment/mod.rs | Introduces cmd::pr::attachment module exports. |
| src/cmd/pr/attachment/list.rs | Implements bl pr attachment list + tests. |
| src/cmd/pr/attachment/get.rs | Implements bl pr attachment get (download + save) + tests. |
| src/cmd/pr/attachment/delete.rs | Implements bl pr attachment delete + tests. |
| src/cmd/mod.rs | Registers the new pr command module. |
| src/api/pull_request.rs | Adds PR/comment/attachment API structs + BacklogClient endpoints (+ partial httpmock tests). |
| src/api/mod.rs | Exposes pull_request module and extends BacklogApi trait + BacklogClient impl. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/cmd/pr/comment/count.rs (1)
57-69: Have the mock assert the forwarded PR coordinates.These tests still pass if
count_withswapsproject_id_or_key,repo_id_or_name, ornumber, becauseMockApi::count_pull_request_commentsignores all three inputs. Asserting them here would make the cmd-layer test actually validate the new wiring.🧪 Tighten the mock expectations
impl crate::api::BacklogApi for MockApi { fn count_pull_request_comments( &self, - _project_id_or_key: &str, - _repo_id_or_name: &str, - _number: u64, + project_id_or_key: &str, + repo_id_or_name: &str, + number: u64, ) -> anyhow::Result<PullRequestCommentCount> { + assert_eq!(project_id_or_key, "TEST"); + assert_eq!(repo_id_or_name, "main"); + assert_eq!(number, 1); self.count.clone().ok_or_else(|| anyhow!("no count")) } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/cmd/pr/comment/count.rs` around lines 57 - 69, The MockApi currently ignores the incoming PR coordinates so tests won't catch swapped parameters; modify the MockApi struct to store the expected values (e.g., expected_project: String, expected_repo: String, expected_number: u64) and in its implementation of count_pull_request_comments assert that the incoming _project_id_or_key, _repo_id_or_name, and _number match those expected fields (use assert_eq! or return an anyhow! mismatch error) before returning self.count.clone().ok_or_else(|| anyhow!("no count")); this will ensure count_with actually validates the forwarded PR coordinates.src/cmd/pr/comment/update.rs (1)
1-118: Consider keepingpr/commentas a single sub-resource module.This repo’s sub-resource command modules usually keep sibling operations together, so splitting PR comment commands into per-subcommand files makes
pr/commentdiverge from the local layout and harder to scan alongside similar modules.Based on learnings, "In the
23prime/backlog-clirepository, sub-resource command files undersrc/cmd/<resource>/(e.g.,status.rs,admin.rs,user.rs,category.rs) consolidate all subcommands (add, update, delete, reorder, etc.) and their*_withvariants into a single file rather than splitting each subcommand into its own file."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/cmd/pr/comment/update.rs` around lines 1 - 118, Move the split PR comment command back into a single pr/comment sub-resource module by consolidating the sibling subcommand files into one file that exports the related functions (e.g., update, update_with, PrCommentUpdateArgs and its impl) and tests; ensure you keep the public API surface the same and preserve helper imports (BacklogApi, BacklogClient) and test utilities (sample_pr_comment) while removing duplicate imports/defs from the other per-subcommand files so all add/update/delete variants live together in the pr/comment module.src/api/pull_request.rs (1)
175-310: Addhttpmockcoverage for the write/download PR endpoints.The test module only exercises the GET variants right now, so
create_pull_request,update_pull_request,add_pull_request_comment,update_pull_request_comment,download_pull_request_attachment, anddelete_pull_request_attachmentstill have no automated check of their exact path and request shape. The higher-level command tests only assert returned values, so a typo here could slip through unnoticed.As per coding guidelines, "For
api/layer tests, usehttpmockto spin up a local HTTP server and constructBacklogClient::new_with(base_url, api_key)instead of callingBacklogClient::from_config()."Also applies to: 314-478
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/pull_request.rs` around lines 175 - 310, Tests currently only cover GET endpoints; add httpmock-based tests that exercise and assert the request path, method, body/form and headers for the write/download PR endpoints (create_pull_request, update_pull_request, add_pull_request_comment, update_pull_request_comment, download_pull_request_attachment, delete_pull_request_attachment and the same for items in the 314-478 range). Use httpmock to spin up a server and construct BacklogClient::new_with(base_url, api_key) (not from_config), register mocks that validate exact URL path, HTTP verb, query/form payload shape and return representative JSON or binary responses, then call the corresponding methods (create_pull_request, update_pull_request, add_pull_request_comment, update_pull_request_comment, download_pull_request_attachment, delete_pull_request_attachment) and assert both the mock was hit and the returned values deserialize as expected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@website/docs/commands.md`:
- Around line 1969-1985: Update the docs to list the missing --json flag
variants for the PR commands wired in src/main.rs: add `--json` to the usages
for `bl pr create`, `bl pr update`, and the PR comment commands (`bl pr comment
count`, `bl pr comment add`, `bl pr comment update`) so the examples reflect the
json: bool wiring; also mirror the same additions in the Japanese translations
under website/i18n/ja/ to keep user-visible command docs consistent across
locales.
In `@website/i18n/ja/docusaurus-plugin-content-docs/current/commands.md`:
- Around line 1946-2043: Update the Japanese PR CLI docs so examples and usage
show the --json output flag where the CLI supports it: add --json variants for
the commands named bl pr list, bl pr count, bl pr create, bl pr update, bl pr
comment list, bl pr comment count, bl pr comment add, bl pr comment update, and
bl pr attachment list/delete to match the behavior implemented in src/main.rs;
also ensure the attachment get example still shows --output usage only and
mirror the same changes in the website/docs/ (English) docs to keep both locales
in sync.
---
Nitpick comments:
In `@src/api/pull_request.rs`:
- Around line 175-310: Tests currently only cover GET endpoints; add
httpmock-based tests that exercise and assert the request path, method,
body/form and headers for the write/download PR endpoints (create_pull_request,
update_pull_request, add_pull_request_comment, update_pull_request_comment,
download_pull_request_attachment, delete_pull_request_attachment and the same
for items in the 314-478 range). Use httpmock to spin up a server and construct
BacklogClient::new_with(base_url, api_key) (not from_config), register mocks
that validate exact URL path, HTTP verb, query/form payload shape and return
representative JSON or binary responses, then call the corresponding methods
(create_pull_request, update_pull_request, add_pull_request_comment,
update_pull_request_comment, download_pull_request_attachment,
delete_pull_request_attachment) and assert both the mock was hit and the
returned values deserialize as expected.
In `@src/cmd/pr/comment/count.rs`:
- Around line 57-69: The MockApi currently ignores the incoming PR coordinates
so tests won't catch swapped parameters; modify the MockApi struct to store the
expected values (e.g., expected_project: String, expected_repo: String,
expected_number: u64) and in its implementation of count_pull_request_comments
assert that the incoming _project_id_or_key, _repo_id_or_name, and _number match
those expected fields (use assert_eq! or return an anyhow! mismatch error)
before returning self.count.clone().ok_or_else(|| anyhow!("no count")); this
will ensure count_with actually validates the forwarded PR coordinates.
In `@src/cmd/pr/comment/update.rs`:
- Around line 1-118: Move the split PR comment command back into a single
pr/comment sub-resource module by consolidating the sibling subcommand files
into one file that exports the related functions (e.g., update, update_with,
PrCommentUpdateArgs and its impl) and tests; ensure you keep the public API
surface the same and preserve helper imports (BacklogApi, BacklogClient) and
test utilities (sample_pr_comment) while removing duplicate imports/defs from
the other per-subcommand files so all add/update/delete variants live together
in the pr/comment module.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: aaadc4d0-e446-475e-bd88-2cd1e8fd975c
📒 Files selected for processing (21)
src/api/mod.rssrc/api/pull_request.rssrc/cmd/mod.rssrc/cmd/pr/attachment/delete.rssrc/cmd/pr/attachment/get.rssrc/cmd/pr/attachment/list.rssrc/cmd/pr/attachment/mod.rssrc/cmd/pr/comment/add.rssrc/cmd/pr/comment/count.rssrc/cmd/pr/comment/list.rssrc/cmd/pr/comment/mod.rssrc/cmd/pr/comment/update.rssrc/cmd/pr/count.rssrc/cmd/pr/create.rssrc/cmd/pr/list.rssrc/cmd/pr/mod.rssrc/cmd/pr/show.rssrc/cmd/pr/update.rssrc/main.rswebsite/docs/commands.mdwebsite/i18n/ja/docusaurus-plugin-content-docs/current/commands.md
…ests for mutating endpoints Addresses review comments: add --json usage examples to pr comment update, attachment list, and attachment delete commands; add httpmock tests for create/update/delete pull request, comment, and attachment API methods.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/api/pull_request.rs (1)
541-546: Harden download test by asserting API key query parameter.This test currently doesn’t verify
apiKey, unlike the rest of this module. Adding it improves regression detection for download auth/query wiring.Proposed test assertion update
server.mock(|when, then| { when.method(GET) - .path("/projects/TEST/git/repositories/main/pullRequests/1/attachments/1"); + .path("/projects/TEST/git/repositories/main/pullRequests/1/attachments/1") + .query_param("apiKey", TEST_KEY); then.status(200) .header( "Content-Disposition", "attachment; filename=\"screenshot.png\"", )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/pull_request.rs` around lines 541 - 546, The test download_pull_request_attachment_returns_bytes should assert the apiKey query parameter on the mock like the other tests do; in the server.mock when clause for the path "/projects/TEST/git/repositories/main/pullRequests/1/attachments/1" add a query_param assertion (e.g., .query_param("apiKey", "TEST_API_KEY") or the test constant used elsewhere) so the mock requires the apiKey query parameter for the request to match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/api/pull_request.rs`:
- Around line 541-546: The test download_pull_request_attachment_returns_bytes
should assert the apiKey query parameter on the mock like the other tests do; in
the server.mock when clause for the path
"/projects/TEST/git/repositories/main/pullRequests/1/attachments/1" add a
query_param assertion (e.g., .query_param("apiKey", "TEST_API_KEY") or the test
constant used elsewhere) so the mock requires the apiKey query parameter for the
request to match.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 809b26f1-2c25-4bc6-87aa-f4f52b118107
📒 Files selected for processing (3)
src/api/pull_request.rswebsite/docs/commands.mdwebsite/i18n/ja/docusaurus-plugin-content-docs/current/commands.md
🚧 Files skipped from review as they are similar to previous changes (1)
- website/i18n/ja/docusaurus-plugin-content-docs/current/commands.md
Checklist
mainwebsite/docs/,website/i18n/ja/,README.md)Summary
bl pr list <project> <repo>— list pull requestsbl pr count <project> <repo>— count pull requestsbl pr show <project> <repo> <number>— show pull request detailsbl pr create <project> <repo> --summary --base --branch— create pull requestbl pr update <project> <repo> <number>— update pull requestbl pr comment list/count/add/update— manage PR commentsbl pr attachment list/get/delete— manage PR attachmentsReason for change
Implements #54.
Changes
src/api/pull_request.rs—PullRequest,PullRequestComment,PullRequestAttachmentstructs + allBacklogClientmethodssrc/api/mod.rs— trait declarations + implsrc/cmd/pr/— all command logic with testssrc/cmd/mod.rs— addedprmodulesrc/main.rs— clap wiring for allbl prsubcommandswebsite/docs/commands.md,website/i18n/ja/.../commands.md— docs and coverage table updatedNotes
POST/PATCH/DELETE commands (
create,update,comment add,comment update,attachment delete) are implemented but not tested against the real API (no PR environment available).Closes #54