docs: publish documentation as a GitHub Pages site and run a full quality pass#146
Conversation
…ks for strict build Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix grid card rendering: restore 4-space body indentation required by Python-Markdown and protect it from prettier with a prettier-ignore marker, so card descriptions render inside the card box. - Persistent left navigation on every page: drop navigation.tabs (and navigation.sections) so the home page and all pages show the full nav tree. - Remove hand-written Table of Contents sections from component, primitives, custom-resource, and guidelines pages; Material renders the page TOC in the right sidebar, so the in-body TOC was redundant. - Fix a stale in-page anchor link in component.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite Primitives Overview as the canonical hub for cross-cutting concepts (mutation system, boolean/version gating, editors, container selectors, server-side apply, workload-kind-agnostic mutations, lifecycle interface to status-value mapping), with category decision-tree and plan-and-apply Mermaid diagrams. Rewrite Component: rebuild the condition-priority table from source (all reasons including the failing reasons and FeatureGateError), correct the Auxiliary() guidance and reconciliation phase count, add reconciliation-lifecycle and status-model diagrams, document Previewable and MutationInspector, and move generic best practices to the Guidelines page. Rewrite Custom Resources: fix the example resource to implement Preview() (concepts.Previewable) and delegate MutationInspector, correct operational status string values, document the Static builder WithGuard option and the identity format contract, add an Integration builder example, and add a step index. Lean pages link shared concepts to the hub. Add Go API external link to the nav. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Landing page: add a value proposition, key-features summary, and a minimal code taste, with the card grid as secondary navigation and a suggested reading path. Getting Started: a hands-on first-component tutorial grounded in a real example, covering the owner CRD contract, building ConfigMap and Deployment primitives, a boolean-gated mutation, composing the component, wiring a thin reconciler (with the Kubebuilder fetch-and-delegate entry point and FlushStatus status-write semantics), and a golden test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Standardize all 22 primitive pages on one template (capabilities, building, mutations, internal ordering, editors, kind-specific sections, lifecycle sections, full example, guidance). Shared cross-cutting concepts now live once in the Primitives Overview and each page links to them rather than repeating. Notable fixes verified against source: - Use runtime string status values consistently (e.g. OperationPending), fixing service, pv, pvc, hpa, pdb which previously used wrong or Go-identifier forms. - Add workload-kind-agnostic mutation pointers only where LiftMutation exists (deployment, statefulset, daemonset). - Demonstrate WithDataExtractor on static primitives that claimed the capability but never showed it. - Add the garbage-collection ownership warning and a full example to clusterrolebinding; remove the duplicated server-side apply section from cronjob; expand the previously thin pod and replicaset pages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Guidelines: restructure into a practical guideline set grounded in real production usage patterns (desired-state baselines, pure mutations, the defaults/compat/overrides layering, fail-loud version floors, user-override escape hatch, named mutations, continue-on-error across components), with neutral examples. Testing: lead with golden.WithScheme (effectively mandatory for typed objects), add a which-tool-when guide, document the Previewer/ComponentPreviewer contracts, and show the explicit go test ./path -update form. Compatibility: add the Go minimum, clarify what Tested status means for production, add a deprecation note and a workflow status badge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the domain-flavored version-gating scenario (8.x versions, ClusterEnv Pre89/Unified89 with gossip/raft discovery) with a neutral one: versions 1.0.0/1.5.0/2.0.0 and PeerDiscovery/PreV2 and PeerDiscovery/V2 mutations gated at the 2.0.0 boundary. Regenerate the goldens and manifest, and update the testing guide to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace em dashes with colons, parentheses, or sentence breaks as the context requires, per the project writing style. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lead with the navigation (Start here) above the prose, and rewrite the value proposition to frame the framework's full purpose (composing operators from reusable, testable layers) rather than a single status-handling pain point. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use the new NewBooleanGate(enabled) constructor in the Primitives Overview
boolean-gating section, the getting-started tutorial, and the mutations-and-gating
example (tracing, debug-logging, and metrics-config mutations) in place of the
verbose NewVersionGate("", nil).When(enabled) form. Drop the now-unused version
parameter from MetricsConfigMutation. Version-gated examples are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The boolean-gating note pointed at version gating but showed no example in context. Add a version-gated gate snippet, note that the VersionConstraint is consumer-supplied, link the backward-compat mutation in the mutations-and-gating example, and target the Version-Gated Mutations section directly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the example test suite to model the mutation/resource/component layers: - Mutation level: factor minimal baselines into a shared helpers_test.go; the per-mutation tests keep their explicit field assertions. - Resource level: drive the real NewDeploymentResource/NewConfigMapResource factory from the owner spec (instead of re-spelling the build inline), assert exactly which mutations fire via concepts.MutationInspector.FiringSet, and golden the rendered YAML. - Component level: extract BuildComponent (shared by the controller and the test) and golden the whole component with AssertComponentYAML. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…spection Build the resource through NewDeploymentResource (as the reconciler does) instead of re-spelling the build inline, assert which mutations fire via concepts.MutationInspector.FiringSet, then golden the output. Point to the Testing page for the full mutation/resource/component strategy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s on goldengen Replace the manual MutationInspector.FiringSet introspection in the resource tests with goldengen.Resource: declarative fixtures across versions assert which mutations fire (Requires/Forbids) and AssertComplete proves every registered mutation is covered. The component test moves to goldengen.Component the same way. Mutation-level unit tests are unchanged. Per-case golden files are replaced by regime-based goldengen output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build resources through their real factory functions instead of re-spelling the build inline, and assert the firing set via concepts.MutationInspector where a resource registers mutations (component-prerequisites, custom-resource). Extract BuildComponent helpers shared by the controller and a new component-level test that goldens each example's distinctive component behavior (prerequisite ordering, extraction feeding a guard, grace suppression). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lead with the mutation/resource/component layering: unit-test a mutation against a baseline, assert which mutations fire via concepts.MutationInspector, and pin output with golden. Frame goldengen as the declarative coverage tool that works at both resource (goldengen.Resource) and component (goldengen.Component) granularity, with AssertComplete proving every registered mutation is tested. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the manual MutationInspector/FiringSet introspection from the tutorial step; a single golden assertion is the right altitude for getting started. The firing-set introspection and goldengen coverage are covered on the Testing page, which the step already links to. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build the single-resource golden example through a factory instead of an inline builder, define owner in every complete test snippet so they compile as written, and fix the -update note whose content sat on the same line as the !!! note directive (so it rendered as plain text). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the standalone 'asserting which mutations fire' section that taught the manual MutationInspector type-assert and FiringSet call; goldengen.Resource is the supported way to assert firing and it adds completeness. Keep a short note in the goldengen section explaining the MutationInspector primitive it is built on. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The goldengen intro named FiringSet before it was introduced (the section that explained it was removed). Drop the parenthetical; the MutationInspector note later in the section is now where the primitive is first presented.
AssertComplete is an accounting check (every registered mutation must be in a Requires or Exclude); it never evaluates firing. The firing is verified by the Requires assertions during Run. Spell out the division of labor, which is easy to misread. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mplete A compact table makes the division clear: Requires/Forbids assert firing during the sweep, AssertComplete asserts coverage on registration, and nothing fails merely because a mutation fired without a matching Requires. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Put the opening paren on the call line, one argument per line, and the closing paren on its own line with a trailing comma.
…ed deep copy The YAML-loaded fixture spec is unmarshaled once at load time and reused for every version in the sweep, so the build callback must deep-copy it before setting the version, exactly like the Go Config.Build. newSpec is called once per fixture at load time, not per build invocation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously the LoadMatrix snippet referenced buildUnit by name only, hiding the deep copy and version-setting the prose describes. Show the full function so the shared-spec handling is visible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the wiring explicit: LoadMatrix stores buildUnit as Config.Build and loads fixtures from the file; goldengen.New + gen.Run then call buildUnit per version and fixture. The YAML supplies the data, buildUnit supplies the build logic. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Driven by fresh-reader tests for a newcomer and an experienced author:
- Add an import block to the canonical golden example so it compiles, and name
the test-helper package path; clarify that owner/resources/scheme are the
reader's own packages and the package-level scheme.
- Explain why the factory result is type-asserted to golden.Previewer, and that
a built component satisfies ComponentPreviewer directly (no assertion).
- Add a goldengen.Component Build example (component-level coverage), and explain
that a component's registered/firing set is the deduplicated union of its
resources' mutations.
- Show how to chain AssertComplete across multiple generators in one package.
- Cross-link buildComponent to Getting Started for building a component.
- Reword the LoadMatrix wiring ('runs like one declared in Go') and fix a wrong
'defined below' reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The guideline showed a hand-written one-golden-per-version loop, which the testing guide now supersedes with goldengen.Resource (firing regimes, gating assertions, AssertComplete coverage). Reframe around goldengen, keep the baseline-safety principle and the review-the-diff insight, and drop the manual loop. Retitle to 'Pin Rendered Output Across Supported Versions'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iagram Replace the hand-drawn ASCII tree with a Mermaid flowchart (consistent with the page's other diagrams and the README), and center Mermaid diagrams site-wide via extra.css. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ner-reference caveat Confirm that moving a resource from WithResource to IncludeWhen(false) drops it from the component without deleting it, and warn that the controller owner reference set while it was managed is not stripped, so Kubernetes still garbage-collects it when the owner is deleted unless you remove the reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A semicolon in the Note text terminated the Mermaid statement (Mermaid treats ; as a separator), so the whole sequenceDiagram failed to parse. Replace it with a comma.
Add OrphanWhen(cond) to the resource-options table, and replace the IncludeWhen 'remove the owner reference yourself' warning with a note recommending OrphanWhen for releasing a resource so it outlives its owner. Include OrphanWhen in the ReadOnly exclusivity list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cut the quick start, beyond-the-basics, primitives/lifecycle tables, and custom-resource section (all now covered on the docs site). Keep the pitch, the architecture diagram, one short taste, install, and a documentation section linking to the published site and pkg.go.dev. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull requests still build the site in strict mode to catch broken links and nav. The site now deploys to GitHub Pages only when a release is published (so it tracks the latest released version) or on manual workflow_dispatch, rather than on every merge to the default branch.
There was a problem hiding this comment.
Pull request overview
This PR publishes the project documentation as a Material for MkDocs site on GitHub Pages and performs a broad documentation quality pass, while also updating examples/tests to align with the documented gating + golden-generation patterns.
Changes:
- Adds MkDocs site configuration + tooling (
mkdocs.yml,requirements-docs.txt,make docs-serve/docs-build) and a GitHub Pages workflow for strict builds + deploys. - Refactors multiple examples to use
goldengenversion-matrix generation andfeature.NewBooleanGate, and adds component-level golden tests that share the same component assembly as controllers. - Rewrites/standardizes many primitive reference pages and core docs (index, compatibility, multiple primitives), including Mermaid diagrams and cross-linking to shared concepts.
Reviewed changes
Copilot reviewed 80 out of 89 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| requirements-docs.txt | Pins MkDocs Material dependency for building docs. |
| mkdocs.yml | Material for MkDocs site config: theme, extensions, nav structure. |
| Makefile | Adds local docs serve/build targets. |
| .github/workflows/docs.yml | Builds docs in --strict mode on PRs; deploys to Pages on main. |
| .gitignore | Ignores MkDocs output directory (site/). |
| .tool-versions | Adds Python toolchain entry for docs workflows/local dev. |
| docs/index.md | New/updated docs landing page for the site. |
| docs/compatibility.md | Expands compatibility policy and links to workflow/badge. |
| docs/stylesheets/extra.css | Material theme CSS tweaks + Mermaid centering. |
| docs/primitives/statefulset.md | StatefulSet primitive page rewritten/standardized. |
| docs/primitives/serviceaccount.md | ServiceAccount primitive page rewritten/standardized. |
| docs/primitives/service.md | Service primitive page rewritten/standardized. |
| docs/primitives/secret.md | Secret primitive page rewritten/standardized. |
| docs/primitives/rolebinding.md | RoleBinding primitive page rewritten/standardized. |
| docs/primitives/role.md | Role primitive page rewritten/standardized. |
| docs/primitives/replicaset.md | ReplicaSet primitive page rewritten/standardized. |
| docs/primitives/pvc.md | PVC primitive page rewritten/standardized. |
| docs/primitives/pv.md | PV primitive page rewritten/standardized. |
| docs/primitives/pod.md | Pod primitive page rewritten/standardized. |
| docs/primitives/pdb.md | PDB primitive page rewritten/standardized. |
| docs/primitives/networkpolicy.md | NetworkPolicy primitive page rewritten/standardized. |
| docs/primitives/job.md | Job primitive page rewritten/standardized. |
| docs/primitives/ingress.md | Ingress primitive page rewritten/standardized. |
| docs/primitives/configmap.md | ConfigMap primitive page rewritten/standardized. |
| docs/primitives/clusterrolebinding.md | ClusterRoleBinding primitive page rewritten/standardized. |
| docs/primitives/clusterrole.md | ClusterRole primitive page rewritten/standardized. |
| examples/version-matrix/version_matrix_test.go | Updates version universe + expectations for the version-matrix example. |
| examples/version-matrix/resources/statefulset.go | Renames/updates version-gated mutations to the new peer-discovery story. |
| examples/version-matrix/README.md | Updates narrative/docs to match revised mutations and version set. |
| examples/version-matrix/testdata/version_matrix/manifest.yaml | Updates goldengen manifest regimes for new versions/mutations. |
| examples/version-matrix/testdata/version_matrix/default/1.0.0.yaml | Updates golden output for the pre-v2 regime. |
| examples/version-matrix/testdata/version_matrix/default/2.0.0.yaml | Updates golden output for the v2 regime. |
| examples/mutations-and-gating/features/debug_logging.go | Switches boolean gating to feature.NewBooleanGate. |
| examples/mutations-and-gating/features/tracing_sidecar.go | Switches boolean gating to feature.NewBooleanGate. |
| examples/mutations-and-gating/features/metrics_config.go | Removes version parameter; gates via feature.NewBooleanGate. |
| examples/mutations-and-gating/features/helpers_test.go | Adds shared mutation-test baselines + no-op -update flag. |
| examples/mutations-and-gating/features/debug_logging_test.go | Uses shared baseline helper for mutation-level testing. |
| examples/mutations-and-gating/features/tracing_sidecar_test.go | Uses shared baseline helper for mutation-level testing. |
| examples/mutations-and-gating/features/metrics_config_test.go | Uses shared baseline helper and updated mutation signature. |
| examples/mutations-and-gating/features/legacy_container_test.go | Uses shared baseline helper for mutation-level testing. |
| examples/mutations-and-gating/resources/configmap.go | Updates mutation signature usage. |
| examples/mutations-and-gating/resources/deployment_test.go | Reworks resource tests to goldengen version-matrix + completeness accounting. |
| examples/mutations-and-gating/resources/configmap_test.go | Adds goldengen version-matrix generation for ConfigMap and gating assertions. |
| examples/mutations-and-gating/resources/testdata/deployment/manifest.yaml | Adds goldengen manifest for Deployment resource regimes. |
| examples/mutations-and-gating/resources/testdata/deployment/default/1.9.0.yaml | Adds Deployment golden for v1 regime. |
| examples/mutations-and-gating/resources/testdata/deployment/default/2.0.0.yaml | Adds Deployment golden for v2 regime. |
| examples/mutations-and-gating/resources/testdata/deployment/debug/1.9.0.yaml | Adds debug fixture golden for v1 regime. |
| examples/mutations-and-gating/resources/testdata/deployment/debug/2.0.0.yaml | Adds debug fixture golden for v2 regime. |
| examples/mutations-and-gating/resources/testdata/deployment/tracing/1.9.0.yaml | Adds tracing fixture golden for v1 regime. |
| examples/mutations-and-gating/resources/testdata/deployment/tracing/2.0.0.yaml | Adds tracing fixture golden for v2 regime. |
| examples/mutations-and-gating/resources/testdata/configmap/manifest.yaml | Adds goldengen manifest for ConfigMap regimes. |
| examples/mutations-and-gating/resources/testdata/configmap/default/1.9.0.yaml | Adds ConfigMap golden for default fixture. |
| examples/mutations-and-gating/resources/testdata/configmap/metrics/1.9.0.yaml | Adds ConfigMap golden for metrics-on fixture. |
| examples/mutations-and-gating/README.md | Updates docs to reference feature.NewBooleanGate. |
| examples/mutations-and-gating/app/controller.go | Extracts component assembly into BuildComponent shared by controller + tests. |
| examples/mutations-and-gating/app/component_test.go | Adds component-level goldengen matrix + completeness assertions. |
| examples/mutations-and-gating/app/testdata/component/manifest.yaml | Adds goldengen manifest for component regimes. |
| examples/mutations-and-gating/app/testdata/component/all/1.9.0.yaml | Adds component golden output (all features) for v1 regime. |
| examples/mutations-and-gating/app/testdata/component/all/2.0.0.yaml | Adds component golden output (all features) for v2 regime. |
| examples/mutations-and-gating/app/testdata/component/minimal/1.9.0.yaml | Adds component golden output (minimal) for v1 regime. |
| examples/mutations-and-gating/app/testdata/component/minimal/2.0.0.yaml | Adds component golden output (minimal) for v2 regime. |
| examples/grace-inconsistency/resources/deployment_test.go | Pins golden via resource factory (ensures factory behavior is tested). |
| examples/grace-inconsistency/app/controller.go | Extracts component build into BuildComponent to share with tests. |
| examples/grace-inconsistency/app/component_test.go | Adds component-level golden test for grace inconsistency example. |
| examples/grace-inconsistency/app/testdata/component.yaml | Adds component golden YAML. |
| examples/extraction-and-guards/resources/configmap_test.go | Pins golden via factory and wires shared extracted state. |
| examples/extraction-and-guards/resources/secret_test.go | Pins golden via factory and wires shared extracted state. |
| examples/extraction-and-guards/app/controller.go | Extracts component assembly into BuildComponent shared by controller + tests. |
| examples/extraction-and-guards/app/component_test.go | Adds component-level golden test for extractor/guard example. |
| examples/extraction-and-guards/app/testdata/component.yaml | Adds component golden YAML. |
| examples/custom-resource/resources/certificate_test.go | Adds mutation registration/firing assertions via MutationInspector + keeps shape golden. |
| examples/component-prerequisites/resources/deployment_test.go | Adds mutation registration/firing assertions; pins goldens via factory. |
| examples/component-prerequisites/resources/configmap_test.go | Pins golden via factory. |
| examples/component-prerequisites/app/controller.go | Extracts infra/app component builders for shared controller/test assembly. |
| examples/component-prerequisites/app/component_test.go | Adds component-level golden tests for infra + app components. |
| examples/component-prerequisites/app/testdata/infra-component.yaml | Adds infra component golden YAML. |
| examples/component-prerequisites/app/testdata/app-component.yaml | Adds app component golden YAML. |
| extra_css: | ||
| - stylesheets/extra.css | ||
|
|
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: |
| with: | ||
| path: site | ||
|
|
||
| deploy: | ||
| name: Deploy to GitHub Pages | ||
| needs: build | ||
| if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' | ||
| runs-on: ubuntu-latest |
Make the top-level token read-only (inherited by the PR build job, which does not need write scopes) and grant pages:write and id-token:write only to the deploy job. Addresses the least-privilege review feedback.
|
Thanks for the review. Resolution:
|
Description
Publishes the project documentation as a Material for MkDocs site on GitHub Pages, and runs a comprehensive quality pass over the entire documentation set. Every page is rewritten to a consistent standard with API references verified against source, a hands-on getting-started tutorial is added, and the README is trimmed to a minimal entry point that links to the site.
Changes
mkdocs.yml(Material theme: instant search, dark mode, code copy, content tabs, Mermaid), a pinnedrequirements-docs.txt, and.github/workflows/docs.ymlthat builds the site in--strictmode on pull requests and publishes to GitHub Pages when a release is published (so the live site tracks the latest released version), with a manualworkflow_dispatchfor ad-hoc publishing. Addsmake docs-serveandmake docs-buildfor local preview.goldengencoverage andAssertComplete; the Guidelines into a practical set grounded in real production usage.feature.NewBooleanGateandcomponent.OrphanWhenconveniences across the docs and examples.Challenges
Several example fixtures were genericized so the public docs and examples carry no consumer-specific naming, and the
mutations-and-gatingexample was reworked to demonstrate all three testing layers (includinggoldengen.Resource/Componentcoverage). Prettier and Mermaid have a couple of sharp edges that are now handled: grid-card lists need 4-space indentation protected from the formatter, and a semicolon in Mermaid note text silently breaks the whole diagram.Testing
mkdocs build --strictis clean (zero broken links or anchors), and the same strict build runs on every pull request via the new workflow.make allpasses: formatting, lint, the full unit and envtest suite, example tests, and example builds, including the version-matrix and the reworked mutations-and-gating example.Manual step required
In repository Settings → Pages, set Source = GitHub Actions so the deploy job can publish. With that set, the site publishes when you publish a release (or via the manual
workflow_dispatchrun); thesourcehawk.github.iolinks in the README resolve once it is live. Merging this PR alone does not publish.