feat: implement list, sprint list, sprint current (PR 2/5) #13

Merged
David merged 1 commit from feat/sprint-and-list into main 2026-05-14 00:00:14 +02:00
Owner

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) via comfy-table, with --json for a pretty-printed array. Query construction matches Go: for:me default, assignee: unassigned or for: <name> variants, optional Type: and Board <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: prints Current sprint for board '<x>': <name> (or No sprints found ...). Resolution mirrors Go: is_current flag, then a [start, finish] window check against the wall clock, then a fallback sort by trailing number desc and finish desc.
  • --json is supported on all three (it was an unused flag in Go).

New shared modules

  • yt::models gains Sprint, Issue, CustomField. Custom-field values are kept as raw serde_json::Value so the many type-specific value shapes (presentation-strings, single user, array of users, etc.) decode lazily at read time.
  • yt::query builds the YouTrack search query. Pure function with unit tests.
  • yt::sprint_resolution ports DetermineCurrentSprint as a pure function over (&[Sprint], now_ms) plus a _now wrapper that reads the clock, so the fallback logic is testable without freezing time.
  • yt::api composes Client::get_json into list_boards, list_sprints (paginated), and fetch_issues (issue search plus per-issue sprint sub-fetch). Sub-fetch failures log via tracing and the issue continues without sprints, matching Go.
  • yt::output exposes presentation, extract_assignee_names, and custom_field_presentation for table rendering.

Behavior change from the Go CLI (intentional)

A --sprint filter without a --board (or config 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 --check clean.
  • cargo clippy --all-targets -- -D warnings clean.
  • cargo test --all-targets: 58 tests pass (40 new on this branch).
  • --help for each new command shows annotated flags.

Test plan

  • After merge, run youtrack-cli list against a real instance. Confirm the table matches the Go CLI's columns and for:me is the default scope.
  • youtrack-cli list --assignee unassigned --type Bug --json produces a parseable JSON array.
  • youtrack-cli sprint list --board "My Board" lists every sprint with * on the active one.
  • youtrack-cli sprint current reports the expected name when the board has an is_current sprint, 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).
## 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) via `comfy-table`, with `--json` for a pretty-printed array. Query construction matches Go: `for:me` default, `assignee: unassigned` or `for: <name>` variants, optional `Type:` and `Board <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`: prints `Current sprint for board '<x>': <name>` (or `No sprints found ...`). Resolution mirrors Go: `is_current` flag, then a `[start, finish]` window check against the wall clock, then a fallback sort by trailing number desc and finish desc. - `--json` is supported on all three (it was an unused flag in Go). ## New shared modules - `yt::models` gains `Sprint`, `Issue`, `CustomField`. Custom-field values are kept as raw `serde_json::Value` so the many type-specific value shapes (presentation-strings, single user, array of users, etc.) decode lazily at read time. - `yt::query` builds the YouTrack search query. Pure function with unit tests. - `yt::sprint_resolution` ports `DetermineCurrentSprint` as a pure function over `(&[Sprint], now_ms)` plus a `_now` wrapper that reads the clock, so the fallback logic is testable without freezing time. - `yt::api` composes `Client::get_json` into `list_boards`, `list_sprints` (paginated), and `fetch_issues` (issue search plus per-issue sprint sub-fetch). Sub-fetch failures log via tracing and the issue continues without sprints, matching Go. - `yt::output` exposes `presentation`, `extract_assignee_names`, and `custom_field_presentation` for table rendering. ## Behavior change from the Go CLI (intentional) A `--sprint` filter without a `--board` (or `config 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 --check` clean. - `cargo clippy --all-targets -- -D warnings` clean. - `cargo test --all-targets`: 58 tests pass (40 new on this branch). - `--help` for each new command shows annotated flags. ## Test plan - [ ] After merge, run `youtrack-cli list` against a real instance. Confirm the table matches the Go CLI's columns and `for:me` is the default scope. - [ ] `youtrack-cli list --assignee unassigned --type Bug --json` produces a parseable JSON array. - [ ] `youtrack-cli sprint list --board "My Board"` lists every sprint with `*` on the active one. - [ ] `youtrack-cli sprint current` reports the expected name when the board has an `is_current` sprint, 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).
feat: implement list, sprint list, sprint current
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 9s
Create release / Create release from merged PR (pull_request) Has been skipped
26fa55502e
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.
David merged commit 73f45513cb into main 2026-05-14 00:00:14 +02:00
David deleted branch feat/sprint-and-list 2026-05-14 00:00:14 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/youtrack-cli!13
No description provided.