Repository navigation
feat(api): Export API reference data as @sentry/api/docs - #150
Merged
Merged
Conversation
sentry-junior
Bot
requested review from
BYK,
MathurAditya724 and
betegon
as code owners
November 13, 2026 14:26
BYK
requested changes
Nov 13, 2026
Add a docs generator next to the operations catalog. It projects the dereferenced spec onto what an API reference page shows: tags, full parameters, the request body's first content type, responses with schemas and examples, security and servers. It ships as the ./docs export with types, plus extractDocs() to build the same data from an unreleased spec. As in the client and the operation catalog since 2.0.0, paths are relative to the API base path, which the export carries as API_BASE_PATH, and server overrides keep only their origin. Tests pin the shape with a fixture and check the published export against the spec it was built from, so the two can't drift. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
BYK
force-pushed
the
feat/api-docs-export
branch
from
November 13, 2026 14:32
811d00e to
db4e4c1
Compare
BYK
reviewed
Nov 13, 2026
…e strings generate-docs now builds docs.ts from ts.factory nodes and writes it through a new writeSource helper that prints with the TypeScript printer. A local oxlint plugin adds sentry-api/no-typescript-source-strings, which reports .ts files written from strings, templates, concatenation or .join(), and string patches through replaceOnce, in build.mjs, scripts/ and lib/. CI runs it as pnpm lint. The generators that predate the rule are listed in .oxlintrc.json until they move to the printer.
API_BASE_PATH comes from the spec's server URL, so naming its current value would go stale if the server changes it.
BYK
approved these changes
Nov 13, 2026
BYK
added a commit
that referenced
this pull request
Nov 13, 2026
Main has been red since the spec sync from getsentry/sentry#131065 landed (36d0d11). That sync made spec paths relative to the server URL's `/api/0`. Two tests still look up or compare full `/api/0` paths, so Build fails and no `@sentry/api` release goes out until this lands. - `test/descriptions.test.ts` (from #142): `spec.paths["/api/0/organizations/{organization_id_or_slug}/dashboards/"]` → `spec.paths["/organizations/{organization_id_or_slug}/dashboards/"]` - `test/docs.test.ts` (from #150, written against the old spec), comparing the export's paths with the spec's: `` `${operation.method} ${API_BASE_PATH}${operation.path}` `` → `` `${operation.method} ${operation.path}` `` No other test reads `spec.paths` by a full `/api/0` key. The remaining `/api/0` strings in tests are request URLs, which are still correct. Checks: `pnpm build`, `pnpm typecheck`, `pnpm test` (681 passed) and `check-script-modes.sh` pass. <!-- junior-request-attribution:start --> via @BYK. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A640c5343d03e547097aa9b8a711daaf5 --> -- [View Session](https://junior-prod.sentry.dev/conversations/agent%3A640c5343d03e547097aa9b8a711daaf5) [[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A640c5343d03e547097aa9b8a711daaf5/?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>
2 tasks done
BYK
added a commit
to getsentry/sentry-docs
that referenced
this pull request
Nov 13, 2026
The API reference now comes from the `@sentry/api` version this repo pins (`2.3.0`), through its `./docs` export (getsentry/sentry-api-schema#150). It no longer fetches `openapi-derefed.json` from a pinned getsentry/sentry-api-schema commit. The rendered pages don't change. ## Changes - **`src/build/resolveOpenAPI.ts`** reads `{tags, operations}` from `@sentry/api/docs` and maps them to the `APICategory`/`API` shapes the pages already use. - `OPENAPI_LOCAL_PATH` still works in development. It runs a local `make build-api-docs` spec through the package's `extractDocs()`, so previews take the same path as production. - `src/build/open-api/types.ts` is gone; the package types replace it. - Optional query parameters now carry `required: false` instead of no key. The pages check `!!param.required`, so they render the same. - **`scripts/tsconfig.json`** maps `@sentry/api/docs` to `dist/docs.js` for the Algolia script. `tsx` resolves through Node's CJS resolver, and the export only has an `import` condition. - **Bump workflow:** `bump-api-schema-sha.yml` is now **Bump @sentry/api**. It keeps its file name, so existing dispatches still reach it. - It runs hourly and on `workflow_dispatch`, with a concurrency group so the two can't push the same branch. - `scripts/bump-sentry-api.sh` (POSIX `sh`) reads the latest version from npm, pins it exactly in `package.json` and the lockfile, then opens and merges the PR with the same app token as before. A pre-commit hook runs shellcheck on it. - Dependabot here only does security updates, so it doesn't fit. - **`pnpm-workspace.yaml`** only holds settings (no `packages` list). It puts `@sentry/api` in `minimumReleaseAgeExclude`, so the hourly bump can still pin a release minutes after it ships once pnpm applies a release-age default. It does nothing on the current `pnpm@10.30.0`: the lockfile, dependency tree, `package.json` pnpm settings and root `pnpm add` behave as before. - **`develop-docs/backend/api/public.mdx`:** the build process section describes the new flow, and the `openapi-diff` text matches getsentry/sentry#130541: a changelog that never fails, plus a separate RPC breaking-change job. Hold that part until that PR merges. ## Screenshots These `next dev` screenshots are 1400px wide. Before is the current reader on the same spec through `OPENAPI_LOCAL_PATH`; after is this PR reading `@sentry/api/docs`. The images are pixel-identical except for the Next.js dev badge, so two pairs have the same URL. **Create a New Team** | Before | After | |---|---| |  |  | **Create a Custom Inbound Filter** (experimental, with a body) | Before | After | |---|---| |  |  | **List Your Organizations** | Before | After | |---|---| |  |  | ## After merging sentry-api-schema's "Cascade to sentry-docs" dispatch is no longer needed. <!-- junior-request-attribution:start --> via @BYK. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A69da19b385017e68b7f9eace56e9477f --> -- [View Session](https://junior-prod.sentry.dev/conversations/agent%3A69da19b385017e68b7f9eace56e9477f) [[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A69da19b385017e68b7f9eace56e9477f/?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>
sentry-junior Bot
added a commit
to getsentry/sentry
that referenced
this pull request
Nov 14, 2026
Brings static/packages/api level with getsentry/sentry-api-schema main (2.3.1): - @sentry/api/docs exports the API reference data (getsentry/sentry-api-schema#150), with the no-typescript-source-strings lint rule, which the api client CI job now runs. - listPage keeps per_page stable across offset cursors (getsentry/sentry-api-schema#149). - ApiPermissionError carries the scopes from a 403 insufficient_scope challenge (getsentry/sentry-api-schema#146). - Union fields and annotated single-member allOf fields keep their own descriptions. The version moves to 2.3.1, so craft's first api@ release bumps from sentry-api-schema's latest npm version. The release check no longer cuts a patch for API ownership stats alone: the asset stays on each release for ad-hoc use, but nothing reads it on a schedule. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
BYK
added a commit
to getsentry/sentry
that referenced
this pull request
Nov 14, 2026
…0472) Moves `@sentry/api`, the generated TypeScript client for Sentry's public API, from getsentry/sentry-api-schema to `static/packages/api`. It builds from `tests/apidocs/openapi-derefed.json`, the spec this repository generates. The npm name stays `@sentry/api`, so getsentry/toolkit, sentry-docs and other consumers don't change. This PR replaces the pre-merge check from #130450, which was closed. This PR doesn't publish anything. Releases from here stay off until a person cuts the first `api@` tag (see the cutover section). ## Package - The sources match getsentry/sentry-api-schema `main` at 2.3.1, including the `@sentry/api/docs` API reference export (getsentry/sentry-api-schema#150), the `listPage` `per_page` fix (getsentry/sentry-api-schema#149) and `insufficient_scope` handling on `ApiPermissionError` (getsentry/sentry-api-schema#146). - One deliberate difference from sentry-api-schema `main`: the generated `buildUrl` trims trailing slashes from the base URL before appending `/api/0` (`withApiBasePath` in `lib/api-client/api-base-url.ts`), so `https://sentry.io/` no longer requests `https://sentry.io//api/0`. Published 2.x versions keep that bug; the fix ships with the first `api@` release from here. - `package.json` is at 2.3.1, the latest npm version. Craft bumps from it while there is no `api@` tag, so the first release from here lands after sentry-api-schema's. - Differences from sentry-api-schema, all because of where the package now lives: - TypeScript 6 through the repo's `@typescript/typescript6` alias, and zod 4.6.7, the version `static/app`, gsApp, gsAdmin and scraps already pin. The other dev tools are pinned to exact versions, and oxlint matches the repo's 1.90.0. - The build reads the spec files through `lib/spec-files.mjs` and collects them under `spec/`. - `source-analysis` uses a path-parameter pattern that can't backtrack on runs of `{`, for a CodeQL alert the move raised. - The scripts are `test:vitest` and `lint:js`, not `test` and `lint`. The repo's `test-ci` and `test-all` pass Jest flags to every workspace's `test` script, and the repo's `lint:js` runs each workspace's `lint:js`. ## Spec files on GitHub releases Each `api@x.y.z` GitHub release gets the files that version was built from as assets. The pack job adds them to the release artifact; craft's github target attaches every file in it, and its npm target publishes only the tarball: - `openapi-derefed.json`, the dereferenced OpenAPI spec. - `rpc_method_schema.json`, for the openapi-diff/RPC check. It comes from a new `make build-rpc-schema` target. - `api_ownership_stats_dont_modify.json`, which `make build-api-docs` still generates. No known consumer reads it; it is kept for ad-hoc and future use. For example: `https://github.com/getsentry/sentry/releases/download/api@x.y.z/openapi-derefed.json`. The npm package doesn't include them. ## CI: `api client` is a required check The new `api-client` job in `backend.yml` builds, typechecks, lints and tests the client against the PR's own spec. It is part of `backend-required-check`. A spec change that broke the client once stalled releases for 2 days with nothing catching it before merge; this check catches that class of change. - It reuses the spec from the `api-docs` job (shared as a workflow artifact), so the spec isn't built twice. - Both jobs run only when the new `api_client` filter matches: the existing `api_docs` paths plus `static/packages/api/**`. On other PRs both jobs are skipped, and `backend-required-check` counts skipped jobs as passing. ## Releases - **Pack:** `package-pack.yml` sets up the Python env for `api`, then builds the spec, the RPC schema and the package before `pnpm pack`. - **Release on change:** a `release-api-package` job in `openapi.yml` runs after the master spec build whenever the spec or the package might have changed. It runs `.github/workflows/scripts/api-package-release-preflight.sh`, then `craft prepare` with `getsentry/publish`. The preflight skips the release when: - there is no `api@` tag yet, so the job stays inert until the first release is cut by hand; - an `api/release/*` branch is still pending. When that release merges back, its own run releases whatever landed in the meantime; - HEAD predates the newest `api@` tag; - the spec, the RPC schema and the package are unchanged since the last release. It compares the files against the last release's assets. - **Version bump:** a spec change is a minor release, as in sentry-api-schema. A package change uses craft's automatic bump. An RPC-schema-only change is a patch. An ownership-stats-only change doesn't release; the file refreshes with the next release. - **Concurrency:** releases share a concurrency group with `cancel-in-progress: false`, so a burst of merges produces one release. - There is no cron. Manual releases go through the Release workflow, which gets a `static/packages/api` option. - **sentry-docs:** `bump-sentry-docs.yml` runs on each published `api@` release. `.craft.yml` lists the npm target before github for `static/packages/*`, so the version is already on npm when the release is published (the same order applies to icons, scraps and search-syntax, and nothing in them needs the tag before the npm publish). It dispatches sentry-docs' `bump-api-schema-sha.yml` by file name with the existing `SENTRY_API_SCHEMA_UPDATER` app. sentry-docs' bump reads the version from npm, so it works the same after the move. - The mirror push to getsentry/sentry-api-schema still runs, on the same `api_client` filter, and the release doesn't wait for it. ## Cutover (in this order) 1. Merge #130541 and getsentry/eng-pipes#1116, which retires the `apis` command. #130541 falls back to sentry-api-schema `main` until an `api@` release exists. 2. Merge this PR. 3. In getsentry/publish `auto-approve-repos.txt`, replace the `getsentry/sentry-api-schema` line with this repo's `static/packages/api` entry. 4. Disable sentry-api-schema's Release workflow and its sentry-docs dispatch workflow (getsentry/sentry-api-schema#155), so only one repo publishes. 5. Cut the first `api@` release by hand: run the Release workflow with workspace `static/packages/api`. Check that the version it picks is above sentry-api-schema's last npm release. From then on, `openapi.yml` releases on change. 6. Remove the openapi-diff fallback, the mirror push in `openapi.yml`, and the sentry-api-schema links in the getsentry/toolkit docs, getsentry/skills `document-api-endpoint` and devinfra-mcp `docs/sentry/ci.md`. 7. Archive getsentry/sentry-api-schema. Its copies of the `SENTRY_API_SCHEMA_UPDATER_*` credentials can go with it. `static/packages/api/` is owned by @getsentry/owners-api and @getsentry/ocpo in CODEOWNERS. This PR touches `static/` as well as backend CI files. The package is a standalone npm package and isn't part of either deploy, so splitting it wouldn't change what gets deployed. No UI change. <!-- junior-request-attribution:start --> via @BYK. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A69da19b385017e68b7f9eace56e9477f --> -- [View Session](https://junior-prod.sentry.dev/conversations/agent%3A69da19b385017e68b7f9eace56e9477f) [[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A69da19b385017e68b7f9eace56e9477f/?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> Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.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.
Stacked on #149. Ported from getsentry/sentry#130538, per @BYK's request there: get the docs aligned here first, then move
@sentry/apiinto getsentry/sentry.This adds the data sentry-docs needs to build the API reference from the
@sentry/apiversion it pins, so it no longer has to readopenapi-derefed.jsonfrom a pinned commit of this repository. The sentry-docs adapter is getsentry/sentry-docs#20679.Changes from the sentry version
2.0.0 (#148) made every path relative to the API base path and trimmed server URLs to their origin. The export now follows the same contract:
paths are relative, such as/organizations/, the same as@sentry/api/operations;API_BASE_PATH(/api/0) and asapiBasePathinextractDocs()output, so a page builds the full path as${API_BASE_PATH}${operation.path};serversare origins.extractDocs()appliessplitApiBasePathto a copy of the spec it gets, so the published data and a preview of a local spec have the same shape. It accepts both the current spec and one that declares the base path inservers.sentry-docs#20679 needs a follow-up for this: its adapter has to prepend
API_BASE_PATHto paths, like sentry-docs#20787 does for 2.0.0. I'll push that once this shape is settled.What it adds
scripts/generate-docs.mjs, next to theoperationsgenerator. It runslib/docs-catalog.mjsextractDocs(spec)on the originalopenapi-derefed.jsonand emitssrc/docs.ts. That file holds the data as a JSON string literal, so tsc doesn't infer a type for 3.7 MB of data. It ships as@sentry/api/docs(dist/docs.jsplus.d.ts).lib/docs-types.ts):apiBasePath/API_BASE_PATH.tags: name, description,sidebarName(x-sidebar-name) anddisplayDescription(x-display-description).operations, in spec order:operationId, method and relative path, with summary and description copied as written. Also tags,deprecated,experimental(x-sentry-experimental), server origins, security requirements, and parameters (path-level merged with operation overrides) within,required, description,experimentaland schema. The request body comes from its first content type (content type,required, schema, example), and every response has its status, description, content type, schema andexample/examples.extractDocsis exported too, so sentry-docs'OPENAPI_LOCAL_PATHpreview of an unreleased local spec goes through the same projection as the published data.lib/http-methods.mjsholds the HTTP method set that both catalogs use.The export's shape is now a semver contract
sentry-docs, and anything else that imports
@sentry/api/docs, depends on these field names and types. Removing or renaming a field, or changing its type, is a major release. Adding fields is a minor release. The README says so.Size
Measured with
npm pack --dry-runfrom clean builds of #149 and this branch, using the spec in this repository:Almost all of it is
dist/docs.js(3,840,561 B). It's a separate entry point, so@sentry/apiand@sentry/api/clientusers like toolkit don't load it unless they import./docs. They only pay for the download.Tests
test/docs.test.ts:/api/0inserversand an operation server override under it, so the test also covers the relative paths,apiBasePathand origin-only servers. It also covers path-level parameter overrides, experimental flags, multiple content types, responses without content, named examples and security.@sentry/api/docswithopenapi-derefed.json:extractDocs(spec), andAPI_BASE_PATHis/api/0;API_BASE_PATHplus each relative path equal to the spec's path;test/package.test.ts: the packed-tarball smoke test imports@sentry/api/docs.pnpm build,pnpm typecheckandpnpm testpass locally (54 files, 679 tests).No UI change here. The sentry-docs PR carries the API reference screenshots.
Merge order
#149, this PR, the normal release of an
@sentry/apiversion with./docs, then getsentry/sentry-docs#20679 with itsAPI_BASE_PATHfollow-up. That PR's dependency bump is its last step.Co-Authored-By: BYK 126780+BYK@users.noreply.github.com
--
View Session [Sentry]