Skip to content

Docs: generate reference from code + CI drift guard#70

Merged
iarunsaragadam merged 5 commits into
mainfrom
docs/codegen-and-drift-guard
Jun 29, 2026
Merged

Docs: generate reference from code + CI drift guard#70
iarunsaragadam merged 5 commits into
mainfrom
docs/codegen-and-drift-guard

Conversation

@iarunsaragadam

Copy link
Copy Markdown
Contributor

Eliminates the docs-drift class by making code the single source of truth, plus a cheap CI guard. Built in 4 sequenced parts:

  1. Generate reference from code. A go/ast generator parses internal/config/config.go's env*("GATEWAY_…", default) registry → docs-site/src/data/generated/config.json (name/type/default/required/constraint), and internal/service/auditlog.go + internal/connect/metrics.goaudit-events.json. configuration.astro and observability.astro now RENDER those tables, so they can't be wrong about names/defaults. Wired via //go:generate + make docs-gen; generation is idempotent.
  2. CI docs-drift guard (internal/docscheck): scans docs-site/src + docs/ and fails if any referenced GATEWAY_* var, RPC name, audit event, metric, or .go path doesn't exist in source — plus a freshness test that fails if the committed generated JSON is stale. (Proven non-vacuous: a bogus GATEWAY_* ref fails it.)
  3. Executable quickstart (tests/integration): boots the real service with the documented config, asserts /healthz + a Check + auth-rejection — the documented setup is run, not just read.
  4. Thin narrative: hand-maintained reference tables removed in favor of the generated ones; conceptual prose kept.

Real drift it already caught & fixed: quickstart.astro + docker.astro claimed GATEWAY_POSTGRES_AUTO_MIGRATE defaults to true — it defaults to false (since #64). Corrected both.

go generate idempotent · go test -race ./... ✓ (real Postgres) · lint 0 · Astro pnpm build ✓ (24 pages, generated tables verified in HTML).

Add go/ast generators that parse internal/config/config.go and
internal/service/auditlog.go + internal/connect/metrics.go and emit
stable, sorted JSON (config.json, audit-events.json) under
docs-site/src/data/generated. The configuration table and the
observability metrics/audit-event tables now render from that JSON
instead of hand-maintained markup, so the pages cannot drift from the
code. Wire generation via //go:generate directives and a make docs-gen
target. Document the previously-undocumented config fields.
Add internal/docscheck with two tests. TestDocsReferencesExist scans
every prose file under docs-site/src and docs/ and fails if it names a
GATEWAY_ env var, an RPC, an authz_ metric, an audit-event string, or a
repo .go path that does not exist in source — RPC tokens are gated on the
service's verb prefixes and cross-checked against exported Go symbols to
avoid false positives. TestGeneratedDocsAreFresh regenerates the
reference JSON into a temp dir (via DOCS_GEN_OUT) and fails if the
committed files are stale. Wire a docs-drift CI job and a make docs-drift
target.
Add tests/integration/docs_examples_test.go (integration build tag) that
boots the real service via workspaceserver.New with the exact config the
quickstart documents (the dev service token + default project, memory
driver), asserts /healthz and /readyz return 200, and runs a
representative Check with the documented credential — including the
negative case that a wrong credential is rejected, proving service auth
is on as the docs claim. It also cross-checks the documented env against
the generated config registry, so a snippet naming an unsupported knob
fails.
The configuration and observability reference tables now render from the
generated JSON, so the hand-maintained per-section tables are removed and
only narrative prose remains. Correct the quickstart and docker pages,
which claimed GATEWAY_POSTGRES_AUTO_MIGRATE defaults to true (it defaults
to false — migrations are an explicit operator step), and align the
quickstart's compose comment with the bundled docker-compose.yml.

Also satisfy gosec/nilerr in the docscheck tests.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 365b82bb8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

validateMsgs := collectValidateConstraints(file, consts)

var knobs []knob
for field, call := range loadAssign {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include credentials env var in generated config

Because the config registry is populated only by iterating loadAssign (env-helper calls inside the Config literal), env vars read outside that literal are dropped. Load still reads GATEWAY_SERVICE_CREDENTIALS via os.Getenv after the literal, so the generated config.json and Configuration page omit the named credential/project-pin knob and its token-length constraint; operators using mapped service credentials won't see how to configure it, and the freshness test regenerates the same incomplete list rather than catching the omission.

Useful? React with 👍 / 👎.

The config/audit doc generators (internal/config/gen, internal/service/gen) are
package main tooling run via go generate and validated by the docs-gen freshness
test, not by line coverage — but they sat under internal/ and tripped the
per-package coverage gate at 0%. Add a real exclude: list to coverage-gate.sh
(matching prefixes, dropped from the gate entirely like cmd/) and list the two
generator packages.
@iarunsaragadam
iarunsaragadam merged commit 932f366 into main Jun 29, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant