Skip to content

chore: regen API types + 5 DevEx round-3 CLI fixes#28

Merged
caballeto merged 8 commits intomainfrom
chore/update-api-types-20260505205742
May 5, 2026
Merged

chore: regen API types + 5 DevEx round-3 CLI fixes#28
caballeto merged 8 commits intomainfrom
chore/update-api-types-20260505205742

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 5, 2026

Summary

Builds on the auto-regen of API types (the new MCP / API managedBy enum values) with five DevEx round-3 CLI fixes. Each fix is its own commit so review can be done incrementally.

Commits

  1. chore: update generated API types from latest spec (auto-regen) — refreshed api.generated.ts and the checked-in OpenAPI spec to add MCP / API to the managedBy enum.
  2. chore: complete API regen (zod schemas + spec-facts + skill refs) — propagated the enum into api-zod.generated.ts, spec-facts.generated.ts, and the openapi-drift skill reference so the generated artifacts line up with the spec.
  3. fix(monitors): default --regions to us-east for probe-driven types (P1.Bug9)devhelm monitors create --type HTTP … no longer errors with 400: At least one region is required for HTTP monitors. Probe-driven types (HTTP, TCP, DNS, ICMP, HTTP_HEADLESS, HTTP_BROWSER) get [us-east] as a fallback with a stderr notice. HEARTBEAT and MCP_SERVER are deliberately excluded.
  4. chore: regenerate field descriptions for MCP/API enum — follow-up regen of descriptions.generated.ts (also auto-derived from the spec).
  5. feat(monitors): add --assertion flag for inline assertions on create (P1.Bug2) — repeatable --assertion flag on monitors create accepts JSON or a shorthand DSL (status_code=200, response_time<5000, ssl_expiry>=14). Each assertion is POSTed after the monitor is created; failures roll back the monitor.
  6. feat(monitors): wire --alert-channels and add monitors set-channels (P1.Bug3)--alert-channels ch-1,ch-2 on monitors create and update, plus a standalone monitors set-channels <id> --channel-ids … subcommand. Empty string explicitly clears all channels on update / set-channels; failed attach on create rolls back the monitor.
  7. fix(deploy): scope --prune to local state file; add --prune-org-cli (P0.Bug1, multi-team safety)--prune now only deletes resources tracked in this config's .devhelm/state.json, so two teams sharing one workspace can no longer destroy each other's monitors. New --prune-org-cli preserves the legacy org-wide CLI scope; --prune-all is unchanged. Plan output groups destroys by scope ("Tracked by this config:" vs "Other CLI-managed resources:") when scopes differ.
  8. chore(cli): polish topic descriptions, fix a/an typos, clarify --webhook-url (P1.Bug7 + P1.Bug8) — explicit per-topic descriptions in package.json so monitors no longer reads "Create a new monitor"; aOrAn() helper in crud-commands.ts so we get "Delete an alert channel" / "Update an environment" instead of "a alert channel" / "a environment"; literal description for --webhook-url (used by webhook, slack, discord, teams).

Test plan

  • npm run lint clean
  • npm run typecheck clean
  • npm test978 passed
  • npm run build rebuilds manifest & skill refs cleanly
  • node bin/run.js --help shows polished topic descriptions
  • node bin/run.js monitors create --help shows --assertion, --alert-channels, and corrected article ("Create a new monitor")
  • node bin/run.js monitors set-channels --help is registered
  • node bin/run.js alert-channels delete --help reads "Delete an alert channel"
  • node bin/run.js deploy --help shows the new --prune-org-cli flag and updated --prune description
  • Followup release (intentionally not bumped here — batched after merge)

github-actions Bot and others added 8 commits May 5, 2026 20:57
The previous auto-regen commit refreshed `api.generated.ts` and the
checked-in OpenAPI spec, but did not propagate the new `MCP` / `API`
`managedBy` enum values into the downstream generated artifacts. This
runs `npm run zodgen` and `npm run skillgen` so all generated files line
up with the spec and the openapi-drift skill test passes.

Co-authored-by: Cursor <cursoragent@cursor.com>
`devhelm monitors create --type HTTP …` without `--regions` previously
hit the API and surfaced an unhelpful `400: At least one region is
required for HTTP monitors` (DevEx P1.Bug9). Most users hit this on
their first `monitors create` invocation, since region selection is a
plan-tier concern they shouldn't have to think about for a sanity check.

When `--type` is one of HTTP, TCP, DNS, ICMP, HTTP_HEADLESS, or
HTTP_BROWSER and `--regions` is omitted, default to `["us-east"]` and
print a one-line stderr notice so the choice isn't invisible. HEARTBEAT
(push-based) and MCP_SERVER (region semantics still in flux) are
intentionally excluded — both have legitimate "no regions" semantics.

Co-authored-by: Cursor <cursoragent@cursor.com>
Follow-up to the previous regen commits — descriptions.generated.ts is
produced by `node scripts/extract-descriptions.mjs` from the same
OpenAPI spec and was missed in the auto-regen run. The diff is purely
the updated `managedBy` description (DASHBOARD, CLI, TERRAFORM, MCP, or
API).

Co-authored-by: Cursor <cursoragent@cursor.com>
DevEx P1.Bug2: there was no way to create a monitor with assertions in
a single CLI call. Users had to `monitors create`, then call the
assertions API one assertion at a time — which the CLI didn't expose at
all, so most people gave up and used the dashboard.

This adds a repeatable `--assertion` flag to `monitors create` that
accepts either:

- JSON form (any of the ~40 assertion types in the spec):
    --assertion '{"severity":"fail","config":{"type":"status_code",
                  "expected":"200","operator":"equals"}}'
- Shorthand DSL for the three most common assertions:
    --assertion 'status_code=200'      → fail / status_code equals 200
    --assertion 'response_time<5000'   → warn / thresholdMs 5000
    --assertion 'ssl_expiry>=14'       → warn / minDaysRemaining 14

Each parsed assertion is POSTed to `/api/v1/monitors/{id}/assertions`
after the monitor is created. If any POST fails, the monitor is deleted
so users aren't left with a half-configured resource. Best-effort
rollback messaging mentions the orphaned id when DELETE itself fails.

Also adds `afterCreate` / `afterUpdate` hooks to `crud-commands.ts` so
post-create side effects can be wired without forking the CRUD factory
(used here for assertions; reused in the next commit for alert channels).

Co-authored-by: Cursor <cursoragent@cursor.com>
DevEx P1.Bug3: there was no way to attach an alert channel to a monitor
from the CLI. Users had to switch to the dashboard, which broke the
"deploy from CLI / test from dashboard" loop most teams use.

Two surfaces ship together so each common workflow has a one-liner:

- `monitors create --alert-channels ch-1,ch-2`
  Comma-separated channel IDs. After the create succeeds, the CLI calls
  `PUT /api/v1/monitors/{id}/alert-channels`. On failure the monitor is
  deleted (mirrors the assertion rollback added in the previous commit).

- `monitors update --alert-channels ch-1,ch-2`
  Same flag on update. An empty string explicitly clears all channels;
  omitting the flag preserves the current set (no PUT issued).

- `monitors set-channels <id> --channel-ids ch-1,ch-2`
  Standalone subcommand for the "I just want to attach channels to this
  existing monitor" workflow. Required flag, empty string clears.

The two `--alert-channels` flag descriptions differ deliberately: on
create it warns about rollback semantics, on update it documents the
clear-by-empty-string behaviour.

Co-authored-by: Cursor <cursoragent@cursor.com>
DevEx P0.Bug1 (multi-team safety): the previous `--prune` deleted any
CLI-managed resource org-wide that wasn't in the local devhelm.yml.
Two teams sharing one workspace ran into this immediately — running
`deploy --prune --yes` in their own config silently destroyed the
other team's monitors because both were tagged `managedBy: CLI`.

New scope semantics:

- `--prune` (NEW DEFAULT): only deletes resources tracked in this
  config's `.devhelm/state.json`. Other CLI-managed resources are left
  alone — they belong to a different config.
- `--prune-org-cli`: legacy `--prune` behaviour — also deletes
  CLI-managed resources elsewhere in the org. Required for cleanup
  after `state.json` was rotated, or when migrating between configs.
- `--prune-all`: unchanged. Deletes everything not in YAML, including
  dashboard- and Terraform-managed resources.

Plan output groups destroys by scope so multi-team users can tell at a
glance which deletes are theirs vs widened by `--prune-org-cli`:

    Tracked by this config:
      - monitor "mine"
    Other CLI-managed resources:
      - monitor "theirs"

When every delete shares one scope (the common case) the headers are
omitted and the plan looks identical to before.

Each `Change` of action `delete` now carries a `pruneScope` field
('state' | 'org-cli' | 'org-all') for downstream JSON consumers (CI,
dashboards, automation). Existing tests that exercised the legacy
broad behaviour were retargeted at `--prune-org-cli`; new tests cover
the state-scoped default and the grouped plan output.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ook-url

DevEx P1.Bug7 + P1.Bug8 (CLI polish):

1. Topic descriptions in `--help` previously inherited the first
   subcommand's description ("monitors → Create a new monitor",
   "alert-channels → Create a new alert channel"). Add explicit
   per-topic descriptions in `package.json`'s `oclif.topics` for every
   top-level topic and the nested subtopics under `auth`, `data`,
   `monitors`, and `status-pages`.

2. CRUD command descriptions hardcoded `Get a ${name}` / `Update a ${name}`
   / `Delete a ${name}`, which produced ungrammatical "a alert channel",
   "a API key", "a environment", "a incident". Add an `aOrAn(word)`
   helper to `crud-commands.ts` that picks the article based on the
   first letter and use it from get/update/delete factories. Tested
   directly so future resource names with vowel starts stay covered.

3. The `--webhook-url` flag on `alert-channels create` / `update`
   inherited the OpenAPI description "Slack incoming webhook URL", but
   the same flag works for webhook, slack, discord, and teams channels.
   Override it locally with "Webhook URL (used by webhook, slack,
   discord, teams channel types)" so users don't think it's slack-only.

Co-authored-by: Cursor <cursoragent@cursor.com>
@caballeto caballeto changed the title chore: update generated API types chore: regen API types + 5 DevEx round-3 CLI fixes May 5, 2026
@caballeto caballeto merged commit 7829ef1 into main May 5, 2026
3 checks passed
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