Skip to content

feat(cases)!: add timeline and restructure comments as a subgroup#510

Open
avidal wants to merge 1 commit into
DataDog:mainfrom
avidal:feat/cases-timeline
Open

feat(cases)!: add timeline and restructure comments as a subgroup#510
avidal wants to merge 1 commit into
DataDog:mainfrom
avidal:feat/cases-timeline

Conversation

@avidal
Copy link
Copy Markdown
Contributor

@avidal avidal commented May 15, 2026

Summary

Adds pup cases timeline <case-id> for the full case activity feed (comments, attribute updates, status transitions, etc.) and reorganizes the comment operations into a noun-subgroup that aligns with the existing projects precedent.

New surface:

pup cases comments list   <case-id>
pup cases comments get    <case-id> --comment-id <id>
pup cases comments create <case-id> --body "..."
pup cases comments update <case-id> --comment-id <id> --body "..."
pup cases comments delete <case-id> --comment-id <id>
pup cases timeline        <case-id>

Why

The previous flat pup cases comment / pup cases delete-comment (shipped in v0.62.0) was inconsistent with the rest of pup: every other domain uses noun-subgroups for nested resources (pup cases projects {list,get,...}, pup incidents attachments {list,...}, pup synthetics tests {list,...}). The flat shape also made it impossible to grow naturally — there was no clean home for list, get, or update. Folding everything under comments {action} gets a uniform surface and unlocks read/edit operations that previously couldn't be expressed.

timeline lives at the top level rather than under a subgroup because it has a single verb. If the API later grows additional timeline operations (e.g. posting custom cells), this can be refactored without breaking anything since timeline-cell ops aren't user-facing today.

Implementation notes

  • list and get derive from GET /api/v2/cases/{id}/timelines by filtering for cells where attributes.type == "COMMENT". The endpoint is not in the public OpenAPI spec at this revision, so the calls use client::raw_get rather than the typed datadog-api-client SDK. The TimelineResponse model exists in the SDK (comment_case returns it) but no get_timeline operation is generated.
  • update calls PUT /api/v2/cases/{id}/comment/{cell_id} — also undocumented; team confirmed it exists. PUT responds 200 with empty body on success, so the update path uses client::raw_request rather than raw_put (which expects parseable JSON). Function prints a success message in the style of comments delete.
  • create and delete continue to use the typed SDK (comment_case / delete_case_comment).

Breaking changes

  • pup cases comment pup cases comments create
  • pup cases delete-commentpup cases comments delete

These shipped in #504 / v0.62.0 (yesterday). Replacing rather than aliasing because the tool is alpha and uniformity with the rest of the CLI surface wins over preserving a one-day-old surface.

Test plan

  • cargo fmt --check clean
  • cargo clippy -- -D warnings clean
  • cargo test --bin pup -- --test-threads=1 — 1149 passed
  • 7 new unit tests in src/commands/cases.rs:
    • test_cases_timeline (happy path)
    • test_cases_comments_list_filters_to_comment_cells (mixed-cell timeline → only COMMENT cells returned, plus direct assertion on the filter helper)
    • test_cases_comments_get_found
    • test_cases_comments_get_not_found (missing id → error mentions "not found")
    • test_cases_comments_get_skips_non_comment_cell_with_same_id (defensive: non-COMMENT cell sharing an id is not returned)
    • test_cases_comments_create / test_cases_comments_update / test_cases_comments_delete
  • End-to-end run against DISTROLESS-3 and a scratch case (DISTROLESS-5, DISTROLESS-6 — both archived) covering timeline / comments {create, list, get, update, delete}
  • Agent docs updated: agents/case-management.md (removed obsolete "no list-comments endpoint" caveat, added timeline section, refreshed best practices) and agents/incident-response.md (two example commands updated to the new surface)

Pre-existing test flake

cargo test (default parallel execution) intermittently fails three tests unrelated to this PR:

  • commands::monitors::tests::test_monitors_list_empty
  • commands::monitors::tests::test_monitors_list_with_results
  • commands::tags::tests::test_tags_delete

All three are in files this PR does not touch. They race on PUP_MOCK_SERVER env-var cleanup — the existing lock_env() helper serializes the function bodies but cleanup_env() runs outside the guard scope, so a concurrent test can read a stale env var pointing at http://unused.local and fail DNS resolution. The three failing tests all pass in isolation and under --test-threads=1. Worth filing as a follow-up — fix is to make cleanup_env() part of the guard's Drop, or use a per-test mock-server env shadow rather than a process-wide one.


🤖 Generated with Claude Code

Adds `pup cases timeline <case-id>` for the full activity feed
(comments, attribute updates, status transitions) and reorganizes
comment ops into a noun-subgroup that aligns with the existing
`projects` precedent:

  pup cases comments list   <case-id>
  pup cases comments get    <case-id> --comment-id <id>
  pup cases comments create <case-id> --body "..."
  pup cases comments update <case-id> --comment-id <id> --body "..."
  pup cases comments delete <case-id> --comment-id <id>

`list` and `get` derive from `GET /api/v2/cases/{id}/timelines` by
filtering for `COMMENT` cells. `update` calls
`PUT /api/v2/cases/{id}/comment/{cell_id}` — both endpoints are
absent from the public OpenAPI spec at this revision, so they use
raw HTTP. PUT responds 200 with an empty body, so the update path
uses `raw_request` rather than `raw_put` (which expects JSON).

BREAKING: `pup cases comment` → `pup cases comments create`,
`pup cases delete-comment` → `pup cases comments delete`. Both
shipped in v0.62.0 (yesterday); replacing rather than aliasing
because the tool is alpha and consistency with the rest of the
CLI surface wins over preserving a one-day-old surface.

Test coverage adds 7 cases tests: timeline happy path, comments
list filtering on cell type, comments get found / not-found /
non-COMMENT cell with shared id, and comments create/update/delete.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@avidal avidal requested a review from a team as a code owner May 15, 2026 15:25
Comment thread src/commands/cases.rs
}

// ---------------------------------------------------------------------------
// Timeline (uses raw HTTP — the DD API client doesn't expose this endpoint
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add it to the spec internally?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that usually up to the team that owns the API? I'll flag it with them (they were the ones that told me it existed in the first place, as well as PUT on a comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants