fix(incident): read/write lifecycle via SDK 'state', not nonexistent 'status'#55
Merged
Merged
Conversation
…'status' The Datadog v2 SDK exposes the incident lifecycle as `state` on `IncidentResponseAttributes`; `status` is not a field. Reading `getattr(attrs, "status", "")` therefore always returned "" against the real API, making list/get/create/update show empty status. Likewise, `IncidentUpdateAttributes` has no `status` attribute — state changes must flow through `fields["state"]` as a dropdown (same pattern as severity), so `--status` was silently a no-op on the wire. Fixes both directions: reads come from `attrs.state`, writes route through `fields["state"]`. CLI-facing JSON key stays `"status"` to match the existing `--status` flag and avoid breaking output consumers. Tests now use `Mock(spec_set=...)` with `state` so the wrong attribute name can't slip past again, plus a regression test that asserts `update --status` lands in `fields["state"]` on the request body.
2 tasks
srgfrancisco
added a commit
that referenced
this pull request
May 12, 2026
) Three small CLAUDE.md tweaks driven by the PR #55 incident-state bug and a shift in the local worktree workflow: - Add a Gotcha for the datadog_api_client SDK: verify model field names against openapi_types before reading or writing. v2 incidents expose `state` (not `status`), and lifecycle changes flow through `fields["state"]` as a dropdown, not a top-level attribute. `getattr(obj, "wrong_name", "")` masks this silently. - Sharpen the Mock(spec_set=...) note in Testing Patterns to explain why it matters for SDK response mocks: bare Mock(field=...) accepts any attribute name, which is exactly how the incident bug shipped. - Drop the `git gtr` recommendations from Development Workflow and Gotchas. The local preference is now `claude --worktree`, falling back to plain `git worktree add` / `git worktree remove` when a session was started without it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Datadog v2 SDK exposes the incident lifecycle as
stateonIncidentResponseAttributes— there is nostatusattribute.getattr(attrs, "status", "")therefore always returned an empty string against the real API, soincident list,get,create, andupdateall displayed empty status for every incident.Likewise,
IncidentUpdateAttributeshas nostatus(orstate) attribute — state changes must flow throughfields["state"]as adropdown(same pattern already used forseverity). The previous code setattrs_kwargs["status"] = status, which was silently a no-op on the wire.Verified directly against the installed SDK:
Why this slipped past tests
The existing fixtures built
Mock(status=...).Mockaccepts any attribute name silently, so the wrong field name was never detected. This PR switches the fixture toMock(spec_set=[..., "state", ...])so any future reversion will fail loudly.Changes
ddogctl/commands/incident.py:getattr(attrs, "status", "")→getattr(attrs, "state", "")(5 sites)update_incident: route--statusintofields["state"] = {"type": "dropdown", "value": status}instead of an attribute kwargtests/commands/test_incident.py:Mock(spec_set=[...])withstate(notstatus) so the mock matches the real SDK shapetest_update_incident_status_sent_as_fields_stateregression test asserting--statuslands infields["state"]on the request body, and that nostatus/stateattribute is set onIncidentUpdateAttributestest_update_incident_json_reads_stateverifying JSON output'sstatuskey sources fromattrs.stateCLI-facing JSON output key stays
"status"to match the existing--statusflag.Context
This is the underlying bug that PR #48 (closed — hostile fork attempting a project-wide rebrand) was nominally pointing at. This PR fixes only that bug, scoped to two files.
Test plan
uv run pytest tests/commands/test_incident.py -v→ 17 passeduv run pytest tests/→ 690 passeduv run black --check ddogctl/ tests/→ cleanuv run ruff check ddogctl/ tests/→ cleanddogctl incident listshows non-empty status, andddogctl incident update <id> --status resolvedactually resolves the incident