feat: implement four issue mutation commands (PR 4/5) #15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/issue-mutations"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
PR 4 of 5. Adds POST support to the HTTP client and ships the four mutating issue subcommands.
Client::post_ignore: POSTs a JSON body with Bearer auth, errors on non-2xx with status + body (same shape asget_json), drains the response so the connection can be reused. Apost_jsonvariant is intentionally not added: every mutation here only cares about success/failure, and the YouTrack response shapes we'd parse are thrown away by the Go CLI too.yt::query::build_apply_sprint_command: builds the/api/commandsquery (Board "<board>" "<sprint>") using Go-style quoting so embedded"and\escape correctly.yt::api::{apply_command, set_issues_sprint, add_comment, update_state, update_estimation}: each mirrors the Go body byte-for-byte (StateIssueCustomFieldandPeriodIssueCustomFieldshapes included).issue comment <id> <text...>: joins trailing args with spaces, posts to/api/issues/<id>/comments, printsComment added to <id>..issue set-state <id> <state...>: joins state words, POSTs theStateIssueCustomFieldbody.issue set-estimation <id> <minutes>: rejects0explicitly (Go silently sends0m; we surface the validation since the user hasn't asked us to clear estimations that way).issue sprint set <ids...>: portsDetermineSprintresolution.--sprintflag, thendefault_sprintconfig, then list the board's sprints and pick the current one viadetermine_current_sprint_now. Errors when none of the three turn up a sprint.Verification
cargo fmt --checkclean.cargo clippy --all-targets -- -D warningsclean.cargo test --all-targets: 112 tests pass (27 new on this branch).Test coverage on this PR: wiremock-asserted POST body shape for every helper (including the quoted-and-escaped command query), HTTP error propagation, missing-credentials guard on each command, every input-validation path (
set_issues_sprintrejects empty board / empty sprint / empty issue list;set-estimationrejects 0), and the full board + sprint resolution chain forsprint set(explicit flags skip lookup; falls back todefault_sprint; falls back to current sprint from board; errors when neither board nor current sprint is known).Test plan
youtrack-cli issue comment <ID> "hello"posts a real comment.youtrack-cli issue set-state <ID> "In Progress"flips the State custom field.youtrack-cli issue set-estimation <ID> 75writes 75m on the issue.youtrack-cli issue sprint set <ID1> <ID2> --board "X" --sprint "Sprint 26"moves both issues onto the named sprint.--sprint(with a configureddefault_sprint) writes the configured sprint.default_sprint: succeeds when the board has a current sprint; errors clearly otherwise.Sequence
This is PR 4 of 5. PR 5 picks up
work add,work check, andissue daily-sync.PR 4 of 5. Adds POST support to the YT client and ships the four mutating issue subcommands. `Client::post_ignore` rounds out the HTTP wrapper: it POSTs a JSON body with Bearer auth, surfaces non-2xx as `ClientError::Status` (same shape as the GET path), and consumes the response body without parsing it so the connection can be reused. The post-with-decode variant is intentionally not introduced yet: every mutation here cares only about success / failure, and the Go endpoints we mirror return shapes we'd promptly throw away. New `yt::query::build_apply_sprint_command` builds the `/api/commands` query (`Board "<board>" "<sprint>"`) using Go-style quoting so embedded quotes and backslashes escape correctly. New `yt::api` helpers compose the actual mutations: `apply_command` POSTs the command body to `/api/commands`; `set_issues_sprint` validates inputs (non-empty board, sprint, and at least one issue id) and delegates to `apply_command`; `add_comment` posts `{"text": ...}` to the comments endpoint; `update_state` posts a `StateIssueCustomField` shape; `update_estimation` posts a `PeriodIssueCustomField` with the `Xm` presentation. Each mirrors the Go body byte-for-byte. The four command modules are thin wrappers over those helpers. `issue comment <id> <text...>` joins trailing args with spaces and prints `Comment added to <id>.`. `issue set-state <id> <state...>` joins state words. `issue set-estimation <id> <minutes>` rejects 0 explicitly (Go silently sends `0m`, which the user has not chosen yet). `issue sprint set <ids...>` ports `DetermineSprint`'s 3-tier resolution: `--sprint` flag, then `default_sprint` config, then list the board's sprints and pick the current one via the existing `determine_current_sprint_now`. Errors when neither the flag nor config nor a current sprint can be found. Tests with wiremock assert the exact POST body for each helper (including the quoted-and-escaped variants of the sprint command), HTTP error propagation, missing-credentials guard, all input-validation paths, and the full board+sprint resolution chain for `sprint set`. 112 tests pass; clippy clean; fmt clean.