Skip to content

feat: add maintenance_windows resource for scheduling planned downtime#25

Merged
caballeto merged 2 commits into
mainfrom
feat/maintenance-windows-resource
May 6, 2026
Merged

feat: add maintenance_windows resource for scheduling planned downtime#25
caballeto merged 2 commits into
mainfrom
feat/maintenance-windows-resource

Conversation

@caballeto
Copy link
Copy Markdown
Contributor

Summary

Adds an ergonomic client.maintenance_windows resource module so users can schedule, inspect, update, and cancel maintenance windows from automation scripts without dropping down to httpx.

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 into Devhelm, re-exports the DTOs, and locks in the URL contract with mocked-transport tests.

Resource surface

from datetime import datetime, timedelta, timezone
from devhelm import Devhelm

c = Devhelm(token="...")
start = datetime.now(timezone.utc) + timedelta(hours=1)

window = c.maintenance_windows.create({
    "startsAt": start.isoformat(),
    "endsAt":   (start + timedelta(hours=2)).isoformat(),
    "reason":   "Quarterly DB upgrade",
    "monitorId": "a8e3...",   # or omit for an org-wide window
})

# Browse / filter
upcoming = c.maintenance_windows.list(status="upcoming")
mine     = c.maintenance_windows.list(monitor_id="a8e3...")

# Cancel later
c.maintenance_windows.cancel(window.id)
Method HTTP Path
list(*, monitor_id=None, status=None) GET /api/v1/maintenance-windows
list_page(page, size, ...) GET /api/v1/maintenance-windows
get(id) GET /api/v1/maintenance-windows/{id}
create(body) POST /api/v1/maintenance-windows
update(id, body) PUT /api/v1/maintenance-windows/{id}
delete(id) / cancel(id) DELETE /api/v1/maintenance-windows/{id}

cancel is a thin semantic alias for delete — 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

  • The brief mentioned ScheduledMaintenance and MaintenanceComponentRef as 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 returns MaintenanceWindowDto, which is what the actual API endpoints return.
  • The brief proposed monitor_ids / component_ids and add_monitor_ids / remove_monitor_ids kwargs. The current API binds a window to a single monitor (or to the whole org via monitorId=null), so the resource exposes the same shape via RequestBody[CreateMaintenanceWindowRequest] — the existing convention used by Monitors, AlertChannels, etc.
  • Sync only — this SDK does not currently expose an AsyncDevhelm client.

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/ -x742 passed, including 10 new maintenance-window tests and the existing spec-parity tests (which now include MaintenanceWindows, Create/UpdateMaintenanceWindowRequest, and /api/v1/maintenance-windows).
  • Smoke against prod (skipped — no token in this environment).

Made with Cursor

caballeto and others added 2 commits May 6, 2026 12:22
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>
@caballeto caballeto merged commit f1846d7 into main May 6, 2026
4 checks passed
@caballeto caballeto deleted the feat/maintenance-windows-resource branch May 6, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant