feat: add maintenance_windows resource for scheduling planned downtime#25
Merged
Conversation
Adds a `client.maintenance_windows` resource module so users can schedule,
inspect, update, and cancel maintenance windows from automation scripts
without dropping down to httpx.
Surface (mirrors `/api/v1/maintenance-windows`):
* `list(*, monitor_id=None, status=None) -> list[MaintenanceWindowDto]`
auto-paginates and projects ergonomic snake_case kwargs onto the
documented camelCase / `filter` query params.
* `list_page(page, size, ...)` for manual page control.
* `get(id)` / `create(body)` / `update(id, body)`.
* `delete(id)` plus `cancel(id)` as a semantic alias — both call the
same `DELETE /api/v1/maintenance-windows/{id}` endpoint, but
`cancel` reads better in scheduling automation.
Re-exports the public DTOs (`MaintenanceWindowDto`,
`CreateMaintenanceWindowRequest`, `UpdateMaintenanceWindowRequest`) from
both `devhelm.types` and the package root so users can write
`from devhelm import MaintenanceWindowDto` directly.
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds `tests/test_maintenance_windows.py` mirroring the
`TestMonitorsListFilters` pattern: an `httpx.MockTransport` captures
outgoing requests so we can lock in the URL, verb, query string, and
JSON body the SDK sends to the API.
Coverage:
* `list` / `list_page` thread `monitor_id` / `status` onto `monitorId`
/ `filter` query params and omit them when unset.
* `get` hits the correct templated URL and unwraps the `data`
envelope into a typed `MaintenanceWindowDto`.
* `create` posts a validated body with camelCase keys and rejects
bodies missing required fields *before* any HTTP IO.
* `update` PUTs to the templated URL with a camelCase body.
* `delete` and `cancel` both issue `DELETE` to the same URL, locking
in the documented alias semantics.
Also wires the new resource into the existing parity tests — adds it to
`test_client.TestClientResources`, the spec-parity request-DTO list,
the resource body-method matrix, and the SDK path-prefix list — so a
future spec rename or surface drift is caught automatically.
Co-authored-by: Cursor <cursoragent@cursor.com>
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
Adds an ergonomic
client.maintenance_windowsresource module so users can schedule, inspect, update, and cancel maintenance windows from automation scripts without dropping down tohttpx.The endpoints (
/api/v1/maintenance-windows) and the underlying Pydantic models (MaintenanceWindowDto,CreateMaintenanceWindowRequest,UpdateMaintenanceWindowRequest) already shipped via the vendored OpenAPI spec — this PR just adds the typed resource layer, wires it intoDevhelm, re-exports the DTOs, and locks in the URL contract with mocked-transport tests.Resource surface
list(*, monitor_id=None, status=None)GET/api/v1/maintenance-windowslist_page(page, size, ...)GET/api/v1/maintenance-windowsget(id)GET/api/v1/maintenance-windows/{id}create(body)POST/api/v1/maintenance-windowsupdate(id, body)PUT/api/v1/maintenance-windows/{id}delete(id)/cancel(id)DELETE/api/v1/maintenance-windows/{id}cancelis a thin semantic alias fordelete— both call the same endpoint, but the verb reads better in code that schedules and later tears down planned downtime.Notes / deviations from the original brief
ScheduledMaintenanceandMaintenanceComponentRefas the intended return types. Those do exist in_generated.py, but they describe the vendor-scheduled maintenance records served by the status-page pipeline (status.example.com providers), not the user-managed maintenance windows behind/api/v1/maintenance-windows. The resource therefore returnsMaintenanceWindowDto, which is what the actual API endpoints return.monitor_ids/component_idsandadd_monitor_ids/remove_monitor_idskwargs. The current API binds a window to a single monitor (or to the whole org viamonitorId=null), so the resource exposes the same shape viaRequestBody[CreateMaintenanceWindowRequest]— the existing convention used byMonitors,AlertChannels, etc.AsyncDevhelmclient.Test plan
uv run ruff check src/ tests/uv run ruff format --check src/ tests/uv run mypy src/(strict — no new errors)uv run pytest tests/ -x— 742 passed, including 10 new maintenance-window tests and the existing spec-parity tests (which now includeMaintenanceWindows,Create/UpdateMaintenanceWindowRequest, and/api/v1/maintenance-windows).Made with Cursor