feat: implement list, sprint list, sprint current (PR 2/5) #13
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/sprint-and-list"
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 2 of 5. Ports the three read-only listing commands and adds the shared infrastructure they need.
list(issue listing): renders the same 8-column table as the Go CLI (ID, Type, Status, Estimation, Spent Time, Sprint, Assignee, Title) viacomfy-table, with--jsonfor a pretty-printed array. Query construction matches Go:for:medefault,assignee: unassignedorfor: <name>variants, optionalType:andBoard <b>: {<sprint>}clauses.sprint list: prints the marker-list (* <name> [current]) for a board, paginating sprints 100 at a time via$top/$skip. Resolves the board name to its ID by listing all boards first, matching the Go behavior.sprint current: printsCurrent sprint for board '<x>': <name>(orNo sprints found ...). Resolution mirrors Go:is_currentflag, then a[start, finish]window check against the wall clock, then a fallback sort by trailing number desc and finish desc.--jsonis supported on all three (it was an unused flag in Go).New shared modules
yt::modelsgainsSprint,Issue,CustomField. Custom-field values are kept as rawserde_json::Valueso the many type-specific value shapes (presentation-strings, single user, array of users, etc.) decode lazily at read time.yt::querybuilds the YouTrack search query. Pure function with unit tests.yt::sprint_resolutionportsDetermineCurrentSprintas a pure function over(&[Sprint], now_ms)plus a_nowwrapper that reads the clock, so the fallback logic is testable without freezing time.yt::apicomposesClient::get_jsonintolist_boards,list_sprints(paginated), andfetch_issues(issue search plus per-issue sprint sub-fetch). Sub-fetch failures log via tracing and the issue continues without sprints, matching Go.yt::outputexposespresentation,extract_assignee_names, andcustom_field_presentationfor table rendering.Behavior change from the Go CLI (intentional)
A
--sprintfilter without a--board(orconfig set board <name>) now exits with an error instead of silently dropping the sprint clause. The silent fallback in Go masked configuration bugs.Verification
cargo fmt --checkclean.cargo clippy --all-targets -- -D warningsclean.cargo test --all-targets: 58 tests pass (40 new on this branch).--helpfor each new command shows annotated flags.Test plan
youtrack-cli listagainst a real instance. Confirm the table matches the Go CLI's columns andfor:meis the default scope.youtrack-cli list --assignee unassigned --type Bug --jsonproduces a parseable JSON array.youtrack-cli sprint list --board "My Board"lists every sprint with*on the active one.youtrack-cli sprint currentreports the expected name when the board has anis_currentsprint, and falls back to the latest-numbered sprint when none is flagged.youtrack-cli list --sprint "Sprint 26"without--board/configured board errors with a clear hint (previously the sprint filter was silently dropped).PR 2 of 5. Ports the three read-only listing commands from the Go CLI and adds the shared infrastructure they share. New `src/yt/` submodules: `models` gains `Sprint`, `Issue`, `CustomField` (custom-field values stored as raw `serde_json::Value` so we can lazily decode the many type-specific shapes); `query` builds the issue search string (`for:me` default, `assignee: unassigned` / `for: <name>` variants, optional `Type:` and `Board <b>: {<sprint>}` filters); `sprint_resolution` ports `DetermineCurrentSprint` (is_current flag, time-window check, trailing-number-then-finish fallback) as a pure function plus a `_now` wrapper that reads the clock; `api` composes `Client::get_json` calls into `list_boards`, `list_sprints` (resolves board name to ID, paginates 100 at a time via `$top`/`$skip`), and `fetch_issues` (issue search + per-issue sprint sub-fetch, sub-fetch failures logged via tracing and the issue continues without sprints, matching Go); `output` exposes `presentation`, `extract_assignee_names`, and `custom_field_presentation` for table rendering. One behavior change from the Go CLI worth flagging: a `--sprint` flag without a configured/passed `--board` now errors instead of silently dropping the sprint filter, since the silent fallback hid configuration bugs. `list` renders the same 8-column table the Go CLI did (ID, Type, Status, Estimation, Spent Time, Sprint, Assignee, Title) via comfy-table, with `--json` falling back to a pretty-printed array. `sprint list` prints the Go-style `* <name> [current]` marker list and `sprint current` prints `Current sprint for board '<x>': <name>` or `No sprints found`. All three commands gate on `cfg.url` + `cfg.token` and point users at `auth login` when missing. Tests use wiremock to drive end-to-end paths for each command plus the api helpers (board resolution, pagination, partial sprint sub-fetch failure), and pure-function tests cover query construction and sprint resolution edge cases (empty, is_current, time window, fallback sort, ties). 58 tests pass; clippy clean; format clean. `urlencoding = "2"` added so query/path components encode correctly. Duration helpers will land in PR 3 alongside `issue inspect`, which is their first consumer.