Skip to content

ref(cli): Define the org/project target syntax as a PEG grammar - #1638

Merged
BYK merged 11 commits into
mainfrom
byk/cli-target-grammar
Oct 23, 2026
Merged

BYK merged 11 commits into
mainfrom
byk/cli-target-grammar

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Closes #1637. Stacked on #1626 (it replaces TARGET_FORMS from that PR), so the base is byk/cli-docs-drift-guards.

The <org>/<project> target syntax is now one peggy grammar, packages/cli/grammar/org-project-target.pegjs. Both the parser and the docs table come from it.

  • Parser. parseOrgProjectArg keeps its signature. It still keeps the first non-blank line, auto-detects on empty input, and reads Sentry URLs itself. Everything else goes through the generated parser. Slug and @ checks run through options hooks (validateResourceId, rejectAtSelector), so error messages stay the same. parseSlashOrgProject, parseExplicitProjectList, and their helpers are deleted. The backtracking pitfall from the spike is documented in the grammar, and the existing @latest test guards it: token rules only capture text, and validation runs in the winning alternative.
  • Docs. Each target alternative has // @form <syntax> — <meaning> lines above it, and generate-docs-sections.ts builds the table from them. Generation fails if an alternative has no @form or @invalid line. The check uses peggy's grammar AST, so a new form can't ship undocumented. The table now also lists the forms TARGET_FORMS was missing: Sentry URLs, /<name>, <org>/<Project Name>, and <Project Name>. Omitted targets and URLs never reach the grammar, so they are annotated in the grammar header.
  • Generator. packages/toolkit-core/script/generate-parsers.ts moved to scripts/generate-parsers.mjs (pnpm run generate:parsers). One list of grammar specs covers both packages, and check:generated and the pre-commit hook use it. The CLI output goes to packages/cli/src/generated/org-project-target-grammar.{js,d.ts} and is committed (.gitignore exception). It is about 24 KB unminified. peggy moves from a toolkit-core devDependency to the root and the CLI. The lockfile only changes the importer entries.

Migration check, not committed: I compared the new parser with a copy of the old one on 139,954 inputs. They were every string up to 4 characters over a b / , space @ - _ ? # \n 1 % . A \t, the 53 literals in arg-parsing.test.ts, and some extra edge cases, each with multi on and off. There were 0 differences in results, error classes, messages, or fields. While doing this I found and fixed one real bug, which needed end-anchored token rules. Without them, PEG prefix matching turned A # into a SyntaxError.

Not in this PR: parseIssueArg (step 4 of the issue), and removing normalizeSlug / normalized. parseIssueArg and trace-target.ts still use the latter. originalSlug is still needed: it is how resolution tells a display name from a slug.

via BYK.

--

View Junior Session in Sentry

sentry-junior Bot and others added 6 commits October 23, 2026 12:31
Lists that copied code (destructive commands, detected agents, target
syntax, skill file layout) are now generated from the code. New checks
fail CI when a `sentry ...` example names a missing command or flag,
passes a bare org slug as a project-first target, or when an installer
option is missing from its help text or the install guide. `pnpm run cli`
and `generate:docs` now create missing build-time files, and
check:stale-refs flags `pnpm run cli -- <args>`, which pnpm forwards as a
literal `--`.

Co-Authored-By: Claude Opus <noreply@anthropic.com>
Co-Authored-By: BYK <burak.kaya@sentry.io>
Address review feedback on the docs drift guards:

- Type agent tables by `KnownAgent` (keys of AGENT_DISPLAY_NAMES), so a
  detectable agent without a display name is a compile error. Drop the
  map-structure test.
- Key TARGET_FORMS by parse result type so TypeScript enforces that every
  type is documented, and have the generator parse each example and fail
  on a mismatch. Drop target-syntax.test.ts.
- Check only structured `docs.examples`, not examples hand-written into
  `fullDescription`.
- Scan the install scripts in check:env-coverage so installer variables
  must be in ENV_VAR_REGISTRY (and therefore configuration.md). Add the
  missing SENTRY_NO_MODIFY_PATH. check:installer-docs now covers only
  installer help text and flags.
- Replace the pnpm-specific `pnpm run cli --` lint with a dev-only preload
  that drops a leading `--`, so the dev scripts work with any package
  manager.
- Add check:destructive: derive SDK DELETE operations from @sentry/api,
  follow calls, imports, and barrel re-exports through src/, and fail when
  a command that sends a DELETE is not marked destructive.

Co-Authored-By: BYK <burak.kaya@sentry.io>
Follow-up to #1594: `buildCommand` now calls `markDestructive` when
`destructive: true`, instead of `buildDeleteCommand` doing it, so the
`destructive` flag is the single source for the Safety Rules list and the
auto-detect guard. `issue merge` and `trial start` get the guard if they
move to lazy target positionals.

check:doc-examples now recognizes target positionals by their
`org/project` completion kind, which covers the new lazy target parsers
as well as `parseOrgProjectTarget`.
Resolve conflicts with #1633, which moved the remaining hand-written
examples into `docs.examples`: take main's version of the dashboard
commands and the alert/dashboard fragments, then regenerate the skill
references.

check:doc-examples now covers the migrated examples and flagged:
- `dashboard revisions` and `dashboard restore` examples that pass a bare
  `my-org` (a project lookup); changed to `my-org/`
- examples that start with `sudo` or `NAME=value`, which the check
  misread as the command name; it now skips those prefixes

Co-Authored-By: BYK <burak.kaya@sentry.io>
Replace the hand-written `<org>/<project>` parser with a peggy grammar
(packages/cli/grammar/org-project-target.pegjs). parseOrgProjectArg keeps
its signature and still handles blank input and Sentry URLs; character
validation goes through options hooks so error messages are unchanged.

The target syntax tables are now generated from `@form` annotations in the
grammar, and generation fails when a `target` alternative is unannotated.
This replaces TARGET_FORMS and documents the forms it missed: Sentry URLs,
`/<name>`, and display names with and without an org.

The parser generator moves to scripts/generate-parsers.mjs so toolkit-core
and the CLI share it, check:generated, and the pre-commit hook.

Closes #1637

Co-Authored-By: BYK <burak.kaya@sentry.io>
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
sentry-local Ready Ready Preview Oct 23, 2026 10:31pm UTC

Request Review

#1633 added the `no-regex-markdown-parsing` lint rule. Replace the fenced
block regex with the shared `markdownCodeBlocks` / `blankCodeBlocks`
helpers in script/markdown.ts, which use the same lexer as the docs
renderer.
The Windows job checks out the grammar with CRLF line endings, so the
annotation regexes never matched and docs generation failed.
Base automatically changed from byk/cli-docs-drift-guards to main October 23, 2026 21:47
# Conflicts:
#	apps/cli-docs/src/fragments/commands/index.md
#	packages/cli/CONTRIBUTING.md
#	packages/cli/script/generate-docs-sections.ts

Co-Authored-By: BYK <burak.kaya@sentry.io>
Comment thread packages/cli/src/generated/org-project-target-grammar.js Outdated
Comment thread scripts/generate-parsers.mjs Outdated
Stop committing the CLI target parser; src/generated/ is gitignored and
lint/format-ignored again. generate:grammar builds it from generate:docs
and ensure-generated, so build, typecheck, test, and cli runs get it.

Parser types move out of string templates in generate-parsers.mjs into
hand-written grammar/<name>.d.ts files. The generator copies them and
rebases relative module specifiers it finds with the TypeScript parser.
toolkit-core's parser stays committed and checked by check:generated.
@BYK
BYK merged commit 9aefecd into main Oct 23, 2026
42 checks passed
@BYK
BYK deleted the byk/cli-target-grammar branch October 23, 2026 23:00

This branch was successfully deployed

1 active deployment
Preview — 7adec8ca Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ref(cli): Define the org/project target syntax as a PEG grammar

1 participant