mirror of
https://github.com/coder/coder.git
synced 2026-10-31 19:36:41 +08:00
8203b2ebafc89f97cc4723fe482dde1567522cf5
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0a7bb80a1e |
feat: make CLI/API doc generators emit front-matter metadata (Phase 2) (#27246)
## Summary
Phase 2 of the H1 → front-matter migration (`DOCS-483`; parent
`DOCS-477`). Makes the two reference-doc generators emit per-page
metadata as YAML front matter instead of a leading `# H1`, so generated
pages are self-describing and `make gen` stops reverting migrated pages
(Phase 3).
Phase 1 (`DOCS-482`) made the coder.com renderers prefer a front-matter
`title` (manifest fallback).
> [!NOTE]
> Rebased onto `main` and fully regenerated, and updated across two
rounds of Coder Agents Review — see **Review follow-ups** below.
## Changes
- **`scripts/clidocgen/command.tpl` + `gen.go` + `main.go`** — front
matter now carries `title` (from `fullName`) and `description` (from the
command's `Short`), and the leading `# H1` is dropped. The CLI index
page's front matter is taken from the manifest `Command Line` route
(title/description/icon_path).
- **`scripts/apidocgen/postprocess/main.go`** — reads the manifest and,
at write time, injects front matter carrying each section's `title` plus
any curated `description`, `state`, and `icon_path`. The API index
page's front matter is taken from the manifest `REST API` route.
- **`scripts/docgenenv`** (new shared code) — one `YAMLScalar`
front-matter escaper, one `Route`/`Manifest` schema +
`LoadManifest`/`FindRoute`, and one `FrontMatter(Route)` emitter, all
imported by both generators (no duplicated helpers, types, or emitters).
- Regenerated all **166 CLI + 31 API** reference pages.
### Metadata → front matter, and what stays in the manifest
Every *per-page* manifest field is mirrored into the page's front
matter: `title`, `description`, `state`, `icon_path`. The **structural**
fields stay in `manifest.json`:
- `children` — the nav tree (explicitly out of scope).
- `path` — the manifest's pointer to the file; a page carrying its own
path is redundant/error-prone, so it's treated like `children`.
The fields are **duplicated** into front matter and **`manifest.json` is
left unchanged**, so this is a **no-op for rendering today** (coder.com
strips front matter for `llms`, and Algolia + the renderer read only
`title`). Removing the fields from the manifest is the natural
follow-up, gated on the renderer reading them from front matter first.
### Why the API side changes the postprocessor, not the `.dot` templates
The issue text suggested editing
`scripts/apidocgen/markdown-template/*`. I deliberately did **not**,
because the postprocessor derives each page's **filename, section title,
and manifest route** from the leading `# {name}` line
(`extractSectionName`). Emitting front matter from the template would
break that extraction. Instead the widdershins templates still emit `#
{name}`, the postprocessor reads it (and now verifies it), and then
swaps the heading for a front-matter block as each section is written.
## Review follow-ups (Coder Agents Review)
### Round 1 — addressed in `e53d5e03` (all threads resolved)
- **CRF-1 / CRF-4** — de-duplicated the escaper and the
`route`/`manifest` schema + traversal into `scripts/docgenenv` (shared
by both generators).
- **CRF-2** — `YAMLScalar` now quotes YAML-reserved scalars
(`true/false/null/…`, numbers); no current value is affected.
- **CRF-3** — added unit tests: a `YAMLScalar` round-trip, `FindRoute`,
and `prependFrontMatter`.
- **CRF-5** — the CLI and API **index** pages now mirror their manifest
route's title/description/icon_path instead of a hardcoded
`coder`/`API`, fixing a rendered-heading regression (`REST API`/`Command
Line` were being overwritten).
- **CRF-6** — dropped the dead `#login` anchor in
`docs/support/support-bundle.md` (the migrated `login.md` no longer
mints that heading anchor).
- **CRF-7 / CRF-8 / CRF-11** — renamed to `prependFrontMatter`, switched
to `bytes.Cut`, and it now strips the first line only when it is the `#
{name}` heading (`extractSectionName` errors otherwise).
- **CRF-9** — removed the orphan `docs/reference/api/chat.md` (not in
the manifest, not linked; the real page is `chats.md`).
- **CRF-10** — the metadata read and the manifest rewrite now share one
`FindRoute` traversal.
- **CRF-13** — moot under squash-merge; this branch is a single
scopeless commit.
- **CRF-15** — the pre-existing `sort.Slice`/`slices.IsSorted`
comparator is left as-is per the review (out of scope; safe today
because section names are unique).
### Round 2 — addressed in `ee796e7107` (all threads resolved)
- **CRF-16** (P1) — removed three em-dashes from new doc comments (the
only `make lint` failure on the prior head); the emdash gate is green.
- **CRF-17 / CRF-18** — unified front-matter emission into one shared
`docgenenv.FrontMatter(Route)`, used by the API postprocessor directly
and by `command.tpl` via a `frontMatter` template func. This retires the
hand-written template YAML and the
`indexTitle`/`indexDescription`/`indexIconPath` closures, so a new
front-matter field is wired in one place, and it gives the CLI index the
`state` arm it previously lacked. Verified byte-identical: a full CLI +
API regen produces zero page changes.
- **CRF-19** — CLI child sort switched to `slices.SortFunc` +
`cmp.Compare` (typed comparator).
- **CRF-20** — reworded the `prependFrontMatter` comment:
`extractSectionName`'s fail-fast is the load-bearing guard; the prefix
check is a defensive backstop.
- **CRF-21** — added `icon_path`/`state` coverage in `docgenenv`'s
`TestFrontMatter/AllFields` (the branch the index page relies on,
previously at 0%).
- **CRF-22** — `YAMLScalar` no longer emits a trailing-space value as a
bare scalar (YAML strips it on read, so it would not round-trip); added
test coverage.
- **CRF-24** — the shared emitter removed the duplicated `cliIndexRoute`
doc comment; the rationale now lives in one place.
- **CRF-23** (Phase 3, out of scope here) — noted: the API generator
wipes and regenerates `reference/api/` from the manifest, so removing
curated metadata from the manifest in Phase 3 needs another source first
(a generator that preserves existing front matter, or metadata carried
alongside the swagger annotations).
- **Process (Mafu-san)** — the verification set below now leads with
`make lint`, the mandatory CI gate that the earlier list omitted.
## Cross-repo dependency
**Resolved — this PR no longer has a hard merge-ordering gate** (CRF-14
was right; the earlier "must merge after #968" note was stale).
The coder.com surfaces that would otherwise leak raw front matter from
`coder/coder` `main` are already front-matter-aware on merged PRs:
- **coder.com#964** (`DOCS-554`, llms-full.txt corpus + Algolia) —
**merged**.
- **coder.com#974** (`DOCS-574`, the `.md` proxy twin + `llms.txt` index
titles) — **merged**.
coder.com#968 (`DOCS-577`) was re-scoped to only the renderer
route-metadata generalization; it's a no-op on today's corpus and its
own description confirms the "deploy before the generators" constraint
no longer applies (that was driven by the llms corpus, now in #964).
Worth a final confirmation that #964/#974 are **deployed** before merge,
but there's no branch/PR ordering blocker left.
## Verification & evidence
AI was the primary author of this PR (see disclosure below); per the [AI
Contribution
Guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
here is manual verification.
- `make lint` (golangci-lint + the emdash gate) passes; `go build` / `go
vet` / `go test` are clean for the generators + `scripts/docgenenv`;
`pnpm check-docs` passes.
- `swagger.json`, `docs.go`, and `manifest.json` are **unchanged** —
metadata is duplicated into front matter; command/section names and
routes did not move.
- The diff is purely additive front matter
(`title`/`description`/`state`/`icon_path`) + the leading H1 removal; no
body reflow. A full CLI + API regen produces **zero** page changes
beyond the two index pages.
<details>
<summary>Terminal evidence</summary>
CLI `description` from the command's `Short` (`YAMLScalar` quotes when
needed, e.g. a `Short` with a colon):
```md
---
title: server
description: Start a Coder server
---
```
API pages inherit curated manifest metadata (only Agents/Chats have any
today):
```md
---
title: Chats
description: "REST endpoints for Coder Agents Chats API (programmatic agent sessions)."
state:
- early access
---
```
Diff scope + "no body changes" proof (uses an explicit `base..HEAD`
range, so it actually tests the claim):
```
$ git diff --shortstat origin/main
210 files changed, 1447 insertions(+), 344 deletions(-)
# = 166 CLI + 31 API reference pages + generators + scripts/docgenenv
# swagger.json / docs.go / manifest.json: NOT modified
# Every removed line under docs/reference is a leading "# H1"; nothing else:
$ git diff origin/main..HEAD -- docs/reference/ | grep '^-' | grep -v '^---' | grep -v '^-# '
(empty)
$ pnpm check-docs
Summary: 0 error(s)
```
</details>
Linear: DOCS-483
> This PR was created with AI assistance (Coder Agents).
|
||
|
|
c84aa564ba |
docs: normalize code-fence languages for Shiki compatibility (#27161)
Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.* |
||
|
|
fad69df710 | fix: correct SCIM Swagger try it out URLs (#24779) | ||
|
|
86ca61d6ca |
perf: cap count queries and emit native UUID comparisons for audit/connection logs (#23835)
Audit and connection log pages were timing out due to expensive COUNT(*) queries over large tables. This commit adds opt-in count capping: requests can return a `count_cap` field signaling that the count was truncated at a threshold, avoiding full table scans that caused page timeouts. Text-cast UUID comparisons in regosql-generated authorization queries also contributed to the slowdown by preventing index usage for connection and audit log queries. These now emit native UUID operators. Frontend changes handle the capped state in usePaginatedQuery and PaginationWidget, optionally displaying a capped count in the pagination UI (e.g. "Showing 2,076 to 2,100 of 2,000+ logs") Related to: https://linear.app/codercom/issue/PLAT-31/connectionaudit-log-performance-issue |
||
|
|
3fb7c6264f |
feat: display the AI add-on column in the UI on the Users and Organization Members tables (#23291)
## Summary Adds an entitlement-gated **AI add-on** column to both the **Users** table and the **Organization Members** table. When `ai_governance_user_limit` is entitled, each row shows whether the user is consuming an AI seat. ## Background The AI governance add-on tracks which users are consuming AI seats. Admins need visibility into per-user seat consumption directly from the user management tables. This change surfaces that information through both the site-wide Users table and the per-organization Members table, gated behind the `ai_governance_user_limit` entitlement so the column only appears when the feature is licensed. ## Implementation ### Backend - **New SQL query** `GetUserAISeatStates` (`coderd/database/queries/aiseatstate.sql`) — returns user IDs consuming an AI seat, derived from: - Users with entries in `aibridge_interceptions` (AI Bridge usage) - Users who own workspaces with `has_ai_task = true` builds (AI Tasks usage) - **SDK types** — added `has_ai_seat: boolean` to `codersdk.User` and `codersdk.OrganizationMemberWithUserData` - **Handler wiring** — both the Users list endpoint (`coderd/users.go`) and all Members endpoints (`coderd/members.go`) query AI seat state per page of user IDs and populate the response field - **dbauthz** — per-user `ActionRead` checks on `ResourceUserObject` ### Frontend - **Shared `AISeatCell` component** (`site/src/modules/users/AISeatCell.tsx`) — green `CircleCheck` for consuming, gray `X` for non-consuming - **`TableColumnHelpTooltip`** — extended with `ai_addon` variant with tooltip: *"Users with access to AI features like AI Bridge, Boundary, or Tasks who are actively consuming a seat."* - **Column visibility** gated behind `useFeatureVisibility().ai_governance_user_limit` ## Validation - Backend: dbauthz full method suite (`TestMethodTestSuite`) passes including new `GetUserAISeatStates` test - Backend: `TestGetUsers`, `TestUsersFilter`, CLI golden file tests pass - Frontend: 7/7 tests pass across `UsersPage.test.tsx` and `OrganizationMembersPage.test.tsx` (column visibility gating both directions) - `go build ./coderd/...` compiles clean - `pnpm --dir site run lint:types` passes - `make gen` clean ## Risks - **Pagination performance**: The AI seat query is scoped to the current page's user IDs (not a full table scan), keeping it efficient for paginated views. - **Semantic scope**: The workspace-side AI seat derivation uses "any build with `has_ai_task = true`" rather than "latest build only". If the product intent is latest-build-only, this can be tightened in a follow-up. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-6` • Thinking: `xhigh` • Cost: `$27.25`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=27.25 --> |
||
|
|
49e5547c22 | feat: add support for creating service accounts (#23140) | ||
|
|
114ba4593b | chore: fix swagger type of AuditLog AdditionalFields (#17286) | ||
|
|
94f5d52fdc |
chore: adopt markdownlint and markdown-table-formatter for *.md (#15831)
Co-authored-by: Edward Angert <EdwardAngert@users.noreply.github.com> |
||
|
|
95a7c0c4f0 | chore: use tabs for prettier and biome (#14283) | ||
|
|
48f29a1995 | docs: move api and cli docs routes to reference/ (#14241) |