Skip to content

feat(api-docs): Build the API reference from @sentry/api/docs - #20679

Merged
BYK merged 24 commits into
masterfrom
feat/api-docs-from-sentry-api
Nov 13, 2026
Merged

BYK merged 24 commits into
masterfrom
feat/api-docs-from-sentry-api

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

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 ci(openapi-diff): Compare API schemas with the PR's merge-base 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
before after

Create a Custom Inbound Filter (experimental, with a body)

Before After
before after

List Your Organizations

Before After
before after

After merging

sentry-api-schema's "Cascade to sentry-docs" dispatch is no longer needed.

via @BYK.

--

View Session [Sentry]

Read the API reference data from the pinned @sentry/api package instead
of fetching openapi-derefed.json from a pinned sentry-api-schema commit.
OPENAPI_LOCAL_PATH still previews a local spec, through the package's
extractDocs().

Replace the API Schema SHA bump with a @sentry/api version bump that runs
hourly and on dispatch.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
@vercel

vercel Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
develop-docs Ready Ready Preview Nov 13, 2026 10:48pm UTC
sentry-docs Ready Ready Preview Nov 13, 2026 10:48pm UTC

Request Review

@github-actions github-actions Bot added the Priority: Needs Triage The PR description is missing valid priority information label Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Please update the IS YOUR CHANGE URGENT? section of the PR description:

  • Select exactly one option.
  • If you selected an urgent or other deadline, provide the date as YYYY-MM-DD.

This information helps the Docs team prioritize your review.

@cursor

cursor Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Getting ready to monitor this change · Rollout details

Status Service Environment
⏳ Getting ready to monitor this change

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread scripts/bump-sentry-api.sh Resolved
The workflow no longer depends on the script's executable bit.
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a4fb800. Configure here.

Comment thread scripts/bump-sentry-api.sh Resolved
A run that stops before the merge leaves the bump branch and maybe its PR
behind. Force-push the branch and reuse an open PR so the next run can
finish instead of failing.
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
Keep the deletion of src/build/open-api/types.ts and the @sentry/api/docs reader, and carry master's full-path display (#20787) over to it: API paths now get the docs data's apiBasePath prepended. apiLocation and its tests are dropped, because @sentry/api/docs already splits the base path out of the server URLs.
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
BYK added a commit to getsentry/sentry-api-schema that referenced this pull request Nov 13, 2026
Stacked on #149. Ported from getsentry/sentry#130538, per @BYK's request
there: get the docs aligned here first, then move `@sentry/api` into
getsentry/sentry.

This adds the data sentry-docs needs to build the API reference from the
`@sentry/api` version it pins, so it no longer has to read
`openapi-derefed.json` from 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:
- operation `path`s are relative, such as `/organizations/`, the same as
`@sentry/api/operations`;
- the base path ships as `API_BASE_PATH` (`/api/0`) and as `apiBasePath`
in `extractDocs()` output, so a page builds the full path as
`${API_BASE_PATH}${operation.path}`;
- per-operation `servers` are origins.

`extractDocs()` applies `splitApiBasePath` to 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 in `servers`.

**sentry-docs#20679 needs a follow-up for this:** its adapter has to
prepend `API_BASE_PATH` to 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 the `operations` generator.
It runs `lib/docs-catalog.mjs` `extractDocs(spec)` on the original
`openapi-derefed.json` and emits `src/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.js` plus `.d.ts`).
- **Shape** (`lib/docs-types.ts`):
  - `apiBasePath` / `API_BASE_PATH`.
- `tags`: name, description, `sidebarName` (`x-sidebar-name`) and
`displayDescription` (`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) with `in`, `required`, description, `experimental` and
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 and `example`/`examples`.
- **`extractDocs` is exported too**, so sentry-docs'
`OPENAPI_LOCAL_PATH` preview of an unreleased local spec goes through
the same projection as the published data.
- `lib/http-methods.mjs` holds 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-run` from clean builds of #149 and this
branch, using the spec in this repository:

| | tgz | unpacked | files |
|---|---|---|---|
| #149 | 3,385,825 B | 35,812,862 B | 80 |
| this PR | 3,828,867 B | 39,660,930 B | 86 |
| change | **+443 KB (+13%)** | **+3.85 MB (+11%)** | +6 |

Almost all of it is `dist/docs.js` (3,840,561 B). It's a separate entry
point, so `@sentry/api` and `@sentry/api/client` users like toolkit
don't load it unless they import `./docs`. They only pay for the
download.

## Tests

- `test/docs.test.ts`:
- A fixture test pins the exact output shape. Its spec declares `/api/0`
in `servers` and an operation server override under it, so the test also
covers the relative paths, `apiBasePath` and origin-only servers. It
also covers path-level parameter overrides, experimental flags, multiple
content types, responses without content, named examples and security.
- Drift tests compare the published `@sentry/api/docs` with
`openapi-derefed.json`:
- the export equals `extractDocs(spec)`, and `API_BASE_PATH` is
`/api/0`;
- tag and operation order matches the spec, with `API_BASE_PATH` plus
each relative path equal to the spec's path;
- for every operation, the text, parameters, request schema and example,
and response schemas and examples match the spec directly.
- `test/package.test.ts`: the packed-tarball smoke test imports
`@sentry/api/docs`.

`pnpm build`, `pnpm typecheck` and `pnpm test` pass 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/api` version with
`./docs`, then getsentry/sentry-docs#20679 with its `API_BASE_PATH`
follow-up. That PR's dependency bump is its last step.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>

<!-- 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-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
2.1.0 is the first release that exports @sentry/api/docs.
@sentry/api only declares an "import" condition for ./docs, so scripts/algolia.ts, which tsx loads through Node's CJS resolver, failed with ERR_PACKAGE_PATH_NOT_EXPORTED. Alias it to its dist file, as scripts/tsconfig.json already does for rehype-prism-diff.
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
sentry-junior Bot and others added 4 commits November 13, 2026 17:04
…sentry-api

# Conflicts:
#	src/build/resolveOpenAPI.ts
…sentry-api

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
The hourly bump pins each @sentry/api release right after it is
published. Exclude the package so those installs keep working once pnpm
applies a minimumReleaseAge default. The file only holds settings; this
repo stays a single package.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>

@BYK BYK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sentry-api-schema's "Cascade to sentry-docs" dispatch is no longer needed.

Let's do this after merging

@BYK
BYK merged commit fd041ae into master Nov 13, 2026
35 checks passed
@BYK
BYK deleted the feat/api-docs-from-sentry-api branch November 13, 2026 23:15
BYK pushed a commit to getsentry/sentry-api-schema that referenced this pull request Nov 13, 2026
Removes `.github/workflows/cascade-to-sentry-docs.yml`.

The cascade ran `gh workflow run "Bump API Schema SHA"` in sentry-docs
on every push to `main`. getsentry/sentry-docs#20679 renamed that
workflow to **Bump @sentry/api**, so dispatching it by the old name no
longer works. sentry-docs now builds its API reference from
`@sentry/api/docs` and bumps `@sentry/api` hourly on its own, so it
doesn't need a dispatch from this repo.

After this, nothing in this repo's workflows reads the
`SENTRY_API_SCHEMA_UPDATER_APP_CLIENT_ID` variable or the
`SENTRY_API_SCHEMA_UPDATER_PRIVATE_KEY` secret. A repo admin can remove
them unless something outside the workflows still needs them.

<!-- 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>
BYK pushed a commit to getsentry/sentry-api-schema that referenced this pull request Nov 14, 2026
Adds `.github/workflows/bump-sentry-docs.yml`. When a release is
published, it dispatches sentry-docs' **Bump @sentry/api** workflow, so
the docs pin the new version right away instead of waiting for the next
hourly run.

- It dispatches by file name (`bump-api-schema-sha.yml`, ref `master`).
The cascade removed in #154 dispatched by display name and broke when
getsentry/sentry-docs#20679 renamed the workflow.
- It mints a token from the existing `SENTRY_API_SCHEMA_UPDATER_*` app,
scoped to `getsentry/sentry-docs` with only `actions: write`, using the
same pinned `create-github-app-token` action as before. The job's
`GITHUB_TOKEN` has no permissions.
- `release: published` fires for these releases. getsentry/publish
creates them with the `sentry-release-bot` app token, not
`GITHUB_TOKEN`, and the same trigger already runs on sentry-python's
craft releases.
- `.craft.yml` runs the `npm` target before `github`, so the version is
already on npm when the release is published and the bump can install
it.
- The file has no repo-specific logic, so it can move to
getsentry/sentry with the package. There it needs a guard for `api@`
tags.

<!-- 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>
BYK added a commit to getsentry/sentry that referenced this pull request Nov 14, 2026
`openapi-diff` compared every backend PR with
getsentry/sentry-api-schema `main`, which is the latest master and not
where the PR branched off, so its diff also showed unrelated master
changes. Its `json-diff` step exits 1 on any difference, so the job
failed on every PR that changes the spec. That's why develop-docs calls
the failure expected, and also why the RPC breaking-change step after it
was **skipped on exactly those PRs**.

In the 100 runs I sampled, 69 hit the `api_docs` filter. 27 failed at
json-diff, and the RPC check was skipped in all 27. The other 42 ran the
RPC check and passed. #130472 moves `@sentry/api` into
`static/packages/api`, which gives master a second baseline source
besides sentry-api-schema: the `api@` release assets.

## What changes

- **Baselines come from the PR's merge-base.** `openapi.yml` now uploads
`tests/apidocs/openapi-derefed.json` and `rpc_method_schema.json` from
each master build as an `api-schemas` artifact, kept for 30 days.
`scripts/openapi-diff.sh baseline` gets the merge-base from the compare
API and walks back up to 30 master commits to the closest one with that
artifact. Every commit that can change the schemas uploads one.
Fallbacks, in order:
1. the newest `api@` GitHub release, picked by listing releases, since
`releases/latest` is sentry's calver release;
2. sentry-api-schema `main`, for as long as it still receives the spec.

The job summary says which baseline it used. Each source writes to a
scratch directory, so a source that fails halfway leaves nothing behind.
- **The public spec diff is a changelog.** The `changelog` job writes an
`oasdiff changelog --format markdown` to the job summary, capped below
GitHub's 1 MiB limit, and never fails. A missing baseline or an oasdiff
error becomes a note in the summary.
- **The RPC check runs in its own job.** The `rpc-breaking` job runs
`oasdiff breaking --fail-on WARN` on the RPC schema, so nothing upstream
can skip it. Control and cell silos deploy separately, and the new
required `api-client` check (#130472) doesn't cover RPC.
- **One build.** The `build` job still builds the spec and RPC schema
once, with `setup-sentry`. The two compare jobs only download its
artifact and run the oasdiff image, so CI cost stays about the same.
- **`make diff-api-docs`** runs the same script: the merge-base
baseline, then the changelog. It needs gh and docker. That replaces
`api-docs/openapi-diff.ts` and its `json-diff` dependency, so the
lockfile only loses the `json-diff` subtree.
- A new `make build-rpc-schema` writes
`.artifacts/rpc_method_schema.json`. It's the same target #130472 adds.
- A shellcheck pre-commit hook (`--shell=sh
--enable=check-extra-masked-returns`) covers the new script.

The develop-docs text that says this check is expected to fail is
updated in getsentry/sentry-docs#20679, which already rewrites that
section.

## Interaction with #130472

This PR is off master and doesn't depend on #130472, but the two touch
neighboring lines in `openapi.yml` and `Makefile`.
- **If #130472 lands first:** keep its `build-rpc-schema` target, and
point the `api-schemas` upload at `static/packages/api/spec/` or
`.artifacts/rpc_method_schema.json`. The baseline script finds both
files by name inside the artifact, so their paths don't matter.
- **If this one lands first:** #130472 resolves the same two spots.

## Verification

- shellcheck (`--shell=sh --enable=check-extra-masked-returns`) is
clean. actionlint reports nothing new; its only finding is the existing
`ubuntu-26.04-arm` label. knip is clean.
- **Baseline lookup, run for real under dash** with #130472's base and
head SHAs: no `api-schemas` artifact exists yet and there's no `api@`
release, so it fell back to sentry-api-schema `main` (15.8 MB spec plus
RPC schema) in 18 s.
- **Baseline lookup, run with a stubbed gh:**
  - the artifact is on the second commit back: it's used;
- the artifact is missing a file and an `api@` release exists: it uses
the release;
  - every source fails: it exits 1 and leaves no partial files behind;
  - gh fails: it exits 1.
- **Changelog and RPC check, run with the real oasdiff v1.33.0 binary:**
  - a real spec diff gives an 8.8 KB Markdown changelog;
  - identical specs give "No changes detected";
- a missing baseline or a bad JSON spec gives a note, and every one of
these exits 0;
- `rpc-breaking` on identical schemas exits 0, and on a schema with a
removed method it prints `::error` and exits 1.
- No UI change.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>

<!-- junior-request-attribution:start -->
via @BYK.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A69da19b385017e68b7f9eace56e9477f -->

--

[View Session in
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>

This branch was successfully deployed

2 active deployments
Preview – sentry-docs — a13781e0 Deployed Nov 13, 2026 by vercel[bot]
Preview – develop-docs — a13781e0 Deployed Nov 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: Needs Triage The PR description is missing valid priority information

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant