Repository navigation
feat(cli): Complete --fields on org, project, release, dashboard, alert, and auth commands - #1783
Conversation
…commands Add output schemas to 20 org, project, release, and dashboard commands so --fields completes their JSON field paths and --help and the skill references list the fields. The schemas describe what --json prints, including fields the commands add (orgSlug, dsn, url, dry-run fields), and are documentation only: nothing validates output against them. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
BYK
left a comment
There was a problem hiding this comment.
Open question: release create's dry-run output has projects: string[], but a created release has an array of project objects. Should the schema describe both with a union, or should the dry-run output change shape?
Fix the dry-run output shape please.
Free-form or no meaningful JSON: api (raw passthrough), auth token, cli completion and mcp (bare strings), auth login/logout/refresh/switch (status messages).
Well we can infer fields for api endpoints we know about, right? Especially if the shapes are baked into @sentry/api as I requested. Same for others, we should be able to provide some field name suggestions to all command, maybe except cli completion. Ideal state is all commands have proper JSON outputs with known schemas so the --fields completion code is centralized and just uses whatever is defined for the command. For api we may need to be creative and allow a callback to change it based on the selected endpoint.
--fields does nothing today: alert issues/metrics create/edit/delete, dashboard widget delete and auth list have a jsonTransform that ignores the parsed fields, so --fields is silently dropped. Their transforms need fixing before a schema would be honest.
Well this sounds pretty bad. We should file an issue to make sure this never happens again, and fix the existing issue. Can you do that?
| } | ||
|
|
||
| /** JSON fields of {@link DashboardViewData}, for `--fields`. */ | ||
| const DashboardViewOutputSchema = object({ |
There was a problem hiding this comment.
I think all this should live in @sentry/api, right?
There was a problem hiding this comment.
Mostly, yes. A dashboard's own fields (id, title, dateCreated, environment, widgets[]…) are already in @sentry/api as vGetOrganizationDashboardResponse. But the generator doesn't emit OpenAPI descriptions, so the CLI writes its own copy with descriptions. period, fetchedAt, url and each widget's data are computed by the CLI and don't come from any endpoint, so they'd stay here.
Plan (also in the review reply):
- Upstream (getsentry/sentry-api-schema): emit
v.description()from the OpenAPI field descriptions. Todayvalibot.genhas noDescriptionActionat all. Then fix the descriptions in the OpenAPI spec in getsentry/sentry wherever they're missing. - Then this schema becomes
looseObject({ ...vGetOrganizationDashboardResponse.entries, ...cliComputedEntries }). The same goes for the org/project/release/deploy/team curations intypes/sentry.ts. The CLI keeps only the fields it adds. - Dashboard revisions have no response schema in the SDK yet, so that needs the endpoint documented in Sentry's OpenAPI spec first.
I haven't changed this here. It's a follow-up unless you want it in this PR.
Resolve the widget/add.ts import conflict by keeping both DashboardWidgetChangeOutputSchema (output schema) and DEFAULT_WIDGET_TYPE (dataset-field completers from #1782). Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
The dry-run preview listed projects as slug strings and a finalize flag,
while a created release has project objects and dateReleased. Emit
projects as { slug } objects and dateReleased instead, so one schema
(the release plus dryRun) describes both and --fields paths such as
projects.slug work in either mode.
Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
A jsonTransform replaces the default JSON path, including --fields filtering, so a transform that never read its fields argument made --fields a silent no-op (#1808). Fix the ones that did: - alert issues/metrics create and edit: drop the identity transform so the default path filters. - alert issues/metrics delete, alert issues view, auth list, dashboard widget delete, issue merge, issue resolve, project delete: filter what the transform returns with the new filterFieldsIfSet helper. Add output schemas for alert issues/metrics create, edit and delete (edit documents the @sentry/api workflow or detector update response it spreads), auth list, and dashboard widget delete, so --fields completes there too. Guard against new cases with the sentry-cli/json-transform-uses-fields lint rule: an inline or same-module jsonTransform, or any top-level jsonTransform* function, must read its second parameter. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
|
Thanks @BYK. Done in 47f50f0 and 31da9a5, and merged with
Proposed plan for the broader direction (not implemented here; this PR or follow-ups, your call):
Suggested split: step 1 upstream, then a CLI PR moving the existing curations onto SDK entries, then |
Resolve import conflicts with #1805 (shared toolkit-core Markdown builders) by keeping both the valibot schema imports and the new markdown helper imports. In release create's dry-run output, use inlineCode() from main on the now string-typed version. Co-Authored-By: Junior (Claude) <noreply@anthropic.com>
…schemas Take every API field of the alert create/edit/delete output schemas (id, name, the dry-run request body) from the @sentry/api/valibot schemas of the endpoint each command calls, instead of hand-writing them. Only the fields the CLI adds (org, project, the status label, dryRun, deleted) stay hand-written.
| | `name` | string | Alert rule name | | ||
| | `status` | string | Rule status (active, disabled) | | ||
| | `dryRun` | boolean | True when --dry-run made no change | | ||
| | `body` | object | Request body that would be sent (--dry-run) | |
There was a problem hiding this comment.
Metric create dry-run body schema does not match JSON output
--fields completion and skill docs type dry-run body as the nested detector request payload, but JSON prints the flat CLI body (query, aggregate, triggers, …). Nested paths like body.dataSources complete then project empty; real flat keys are not offered.
Evidence
MetricAlertCreateOutputSchematypesbodyasvCreateOrganizationProjectDetectorData.entries.bodywith description "Request body that would be sent (--dry-run)" (output-schemas.ts).alert metrics createdry-run yields the flat CLI body (name,query,aggregate,dataset,timeWindow,triggers,projects, …), notbuildDetectorBody()(create.ts; asserted increate.test.ts).- The transport only builds the nested detector payload inside
createMetricAlertRule→buildDetectorBody(alerts.ts). buildFieldsFlagcompletes withextractSchemaFieldPaths(schema), so nested detector paths underbodyare offered against the flat output.
Identified by Warden · code-review · 3VV-PEG
Fixes #1808. A command's `output.jsonTransform` replaces the default JSON path in `renderCommandOutput`, and that path is also where `--fields` filtering happens. Twelve transforms never read their `fields` argument, so `--fields` printed the full object without any warning. For example, `sentry project delete my-org/my-app --json --fields project` printed `{"deleted":true,"org":"my-org","project":"my-app"}`. - `alert issues|metrics create|edit` returned their input unchanged. I removed those transforms so the default path filters. - `alert issues|metrics delete`, `alert issues view`, `auth list`, `dashboard widget delete`, `issue merge`, `issue resolve` and `project delete` now pass their result through a new `filterFieldsIfSet` helper. To stop new cases, a new `sentry-cli/json-transform-uses-fields` lint rule fails when a `jsonTransform` never reads its second parameter. That covers inline transforms, same-module ones, and any top-level `jsonTransform*` function. On `main` it reports exactly these 12. The rule has `RuleTester` cases in `scripts/cli-lint-rules.test.mjs` and is documented in `packages/cli/AGENTS.md`. This is the #1808 part of #1783, pulled out without the new `--fields` completion schemas so it can land on its own. After this merges, #1783 will need its copy of these changes reconciled with `main`, keeping only its schema additions. <!-- junior-request-attribution:start --> via @BYK. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:local%3Aweb%3A57fd20ee8bdc8bf5fbf5d430 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A57fd20ee8bdc8bf5fbf5d430/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: BYK <126780+BYK@users.noreply.github.com>
Fixes #1824 using option 2 from the issue: write the schema first and derive the types from it. Fields the CLI adds to a command's JSON output were declared twice: once in `OutputConfig.schema`, which feeds `--fields` completion, `--help` and the skill references, and once in the TypeScript type the command yields. Nothing kept the two in sync. These fields are target context, `dryRun`/`deleted` flags, and computed values like `url`, `trace`, `period` and widget `data`. Now each command writes them once, as a valibot `object` of output fields. The schema spreads that object's `entries`, and the type comes from it, so the compiler catches drift: - `InferOutput<typeof Fields>`, when the output is all CLI fields. - `WithOutputFields<ApiType, typeof Fields>` (new, `src/types/output.ts`), when the fields sit on or override an `@sentry/api` object. It uses a key-remapping mapped type, not `Omit`, because `Omit` drops named keys from a `looseObject`'s index-signature output. API fields still come from the generated `@sentry/api/valibot` schemas, as in #1783. ### What moved - **alert issues/metrics create/edit/delete**: the output and create-body types come from `alert/output-schemas.ts`. Delete commands now yield their JSON shape directly (`{dryRun|deleted, org, [project], id, name}`), so their `jsonTransform`s are gone. - **release archive/restore/finalize/deploy/create/delete/list**: added `ReleaseUpdateOutputFields`, plus per-command fields for the `--dry-run` previews. Formatters take the derived type instead of `Record<string, unknown>` plus a cast. - **dashboard view/create/restore/widget add/edit/delete**: the widget data result union is now a valibot `variant`, and the TS types are inferred from it. Schema traversal and type display in `lib/formatters/output.ts` treat `variant` like `union`. Widget delete yields its JSON shape directly, and its transform is gone. - **Org-scoped lists** (`buildOrgListCommand`, `project list`): `orgListItemSchema` and `WithOrg<T>` add `orgSlug` to both schema and type. - **project view, org list, auth list, issue view, event view, feedback view, replay view**: enrichment fields (`org`, `event`, `trace`, `attachments`, `replayIds`, `activity`, `relatedIssues`, …) are declared once in `*OutputFields`. Full event payloads stay opaque in the docs with `opaque<SentryEvent>()`. - **auth list**: `AccountSummarySchema` moved to `src/types/account.ts`. `lib/db/accounts.ts` takes `AccountSummary` from it with a type-only import, because the `__complete` fast path loads that module and must not load valibot (`test/script/cli-startup.test.ts`). - **`packages/cli/AGENTS.md`**: new "Declaring Command Output" section on how a new command declares its output. ### Generated docs The only change is one new `orgSlug` row in each of the `team`, `repo`, `integration` and `monitor` skill references. Those lists already put `orgSlug` on every item in their JSON output; the schema just didn't document it. ### Not covered - `buildCommand` doesn't tie `OutputConfig<T>` to the type `func` yields, so the check depends on typing the formatter's parameter and the `CommandOutput<T>` yields. Wiring `T` through `buildCommand` would be a separate, wider change. - Doc schemas that only describe API data (`SentryFeedbackSchema`, `IssueEventSchema`, the replay list schema, `issue tags`) are unchanged. Per the issue, API field descriptions wait on upstream `@sentry/api` support. ### Checks - `pnpm run typecheck` and `pnpm run lint` (CLI package) pass after rebasing on `main`. Root `pnpm run lint` passed before the rebase. - `pnpm run test:unit`: 13,058 passed, 7 failed. Six failures are permission tests that also fail on the base commit in this sandbox (completions, upgrade, resilient DB, code scanner, init file changes). The seventh was the startup-import regression above, now fixed. - After the rebase I reran the alert, dashboard, release, auth, org, project, issue view, feedback, formatter and cli-startup tests (2,036 tests); all pass. Event and replay tests passed before the rebase. <!-- junior-request-attribution:start --> via @BYK. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:local%3Aweb%3A90128b345a91a7f5dc7c6a69 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/local%3Aweb%3A90128b345a91a7f5dc7c6a69/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: BYK <126780+BYK@users.noreply.github.com>
Follow-up to #1759.
--fieldsonly completes when a command'soutputconfig has a schema, so it still completed nothing on 115 commands. This adds output schemas to 29 of them, which leaves 86. It also fixes 12 commands whosejsonTransformsilently ignored--fields(#1808), and adds a lint rule so that can't come back.Schemas added:
list,viewlist,viewlist,view,create,archive,restore,finalize,set-commits,delete,deploys,deploylist,view,revisions,create,restore,widget add,widget edit,widget deletecreate,edit,deletelistEach schema describes what
--jsonactually prints:--fieldsfilters.orgSlug,targetProject,region/account, projectdsn, dashboardurl, and the--dry-runfields.detectedFrom,rendererPreferenceandgraphicsCap.The org, project, release and deploy schemas follow the
SentryTeamSchemapattern. Each one curates the user-facing fields of the@sentry/api/valibotresponse schema and adds descriptions.alert issues|metrics editspread the SDK's workflow and detector update responses (vUpdateOrganizationWorkflowResponse,vUpdateOrganizationDetectorResponse). All of them uselooseObject, so other API fields still pass through. The dashboard commands reuse the existingDashboardListItemSchema,DashboardDetailSchemaandDashboardRevisionSchema. Those three are runtime-validation schemas, and this PR doesn't change them.None of the new schemas validate anything at runtime.
OutputConfig.schemaonly feeds--fieldscompletion,--helpand the generated skill references. A test incomplete.test.tscovers top-level and nested completion onrelease view/list,org view,project viewanddashboard view.release create --dry-runnow has the same shape as a created release:projectsis a list of{ slug }objects instead of slug strings, anddateReleasedreplaces thefinalizeboolean. One schema (the release plusdryRun) covers both cases, so--fields projects.slugworks either way.--fieldswas silently ignored (#1808). AjsonTransformreplaces the default JSON path, and that includes--fieldsfiltering. These transforms never read theirfieldsargument:alert issues|metrics create|editreturned their input unchanged. I removed those transforms, so the default path does the filtering.alert issues|metrics delete,alert issues view,auth list,dashboard widget delete,issue merge,issue resolveandproject deletenow filter their result with a newfilterFieldsIfSethelper.Guard: the new
sentry-cli/json-transform-uses-fieldslint rule (lint-rules/cli-oxlint-plugin.js) fails when an inline or same-modulejsonTransform, or any top-leveljsonTransform*function, never reads its second parameter. It flagged exactly the 12 commands above, and it passes onmain's other transforms.packages/cli/AGENTS.mddocuments it.Still not completing (86):
api(the shape depends on the endpoint),auth token,cli completionandmcp(bare strings), and auth login/logout/refresh/switch (status messages).The review proposes moving these schemas into
@sentry/api, centralizing--fieldscompletion, and lettingapipick its schema from the endpoint. The plan for that is in the review reply. Whether it lands in this PR or in follow-ups is up to you.via @BYK.
--
View Session in Sentry