Imported from fluxcd/flux-schema (
AGENTS.md). Install upstream withnpx skills add fluxcd/flux-schema. Copyright stays with the author.
AGENTS.md
Guidance for AI coding assistants working in fluxcd/flux-schema. Read this file before making changes.
Contribution workflow for AI agents
These rules come from fluxcd/flux2/CONTRIBUTING.md and apply to every Flux repository.
- Do not add
Signed-off-byorCo-authored-bytrailers with your agent name. Only a human can legally certify the DCO. - Disclose AI assistance with an
Assisted-bytrailer naming your agent and model:
Thegit commit -s -m "Add feature X" --trailer "Assisted-by: <agent-name>/<model-id>"-sflag adds the human'sSigned-off-byfrom their git config — do not remove it. - Commit message format: Subject in imperative mood ("Add feature X" instead of "Adding feature X"), capitalized, no trailing period, ≤50 characters.
- Commit body: Add a succinct explanation explaining what and why, wrap at 72 characters.
- Trim verbiage: in PR descriptions, commit messages, and code comments. No marketing prose, no restating the diff, no emojis.
- Rebase, don't merge: Never merge
maininto the feature branch; rebase onto the latestmainand push with--force-with-lease. Squash before merge when asked. - Tests: New features, improvements and fixes must have test coverage.
Project
flux-schema is a Flux CLI plugin for Kubernetes schema extraction, manifest validation, and GitOps repository discovery. Single Go binary, cobra-based.
Read the README for an overview of the project and its features.
Code Structure
cmd/flux-schema/— themainpackage. One file per cobra subcommand (version.go, etc.), each registering itself ininit()viarootCmd.AddCommand(...).main.VERSIONis overridden at build time by the Makefile.internal/extractor/— OpenAPI v2 swagger and CRD → standalone-strict JSON Schema extraction.ExtractKubernetes/ExtractOpenShift/ExtractCRDsare the entry points;transformers.goholds the pipeline steps (inlineRefs,injectGVK,replaceIntOrString,nullableOptional,closeAdditionalProperties,stripVendorExtensions) plus the exportedStripDescriptionspost-process.internal/validator/— JSON Schema validation of Kubernetes YAML manifests.loader.gocompiles schemas viasanthosh-tekuri/jsonschema/v6withDraft2020as the default draft;formats.goregisters the Kubernetes string formats (duration,date, etc.) that the library doesn't assert by default.internal/inventory/— GitOps repository discovery for thediscovercommand.Scanwalks a directory viaos.Root(reads are OS-confined to the scanned root, symlinks are not followed), classifies directories (kustomize-overlay,helm-chart,terraform-module; chart and Terraform subtrees are pruned), and lists every resource with its defining file; files referenced as kustomize patches are excluded to avoid double counting.NewInventoryconverts theResultinto the versionedInventoryenvelope fromapi/v1beta1/inventory_types.go.internal/tmpl/— Gotext/templaterenderer for the output-path and--schema-locationtemplates.SchemaVars(Group,GroupPrefix,Kind,Version) is the shared variable set; values are lowercased at render time andGroup: ""is normalized tocore.internal/yamldoc/— line-orientedbufio.SplitFuncthat splits a byte stream on\n---boundaries. Matches kubectl'ssplitYAMLDocumentbehavior.internal/flags/— reusablepflag.Valueimplementations for CLI flags shared across commands.cmd/flux-schema/main_test.go— hostsTestMain, the sharedexecuteCommand(args)test helper, andresetCmdArgs()which restores every command's flag defaults between tests. New commands must add their flag reset here or tests will leak state across subtests.
Build, Test, and Lint
All development goes through the Makefile — do not invoke go build directly, because the Makefile stamps main.VERSION via -ldflags and runs tidy/fmt/vet as prerequisites.
make build— build./bin/flux-schemawith VERSION stamped from gitmake test— runstidy,fmt,vet, thengo test ./... -coverprofile cover.out- Single test:
make test GO_TEST_ARGS="-run TestVersionCmd ./cmd/flux-schema/"
- Single test:
make lint— runs golangci-lint with revive, staticcheck, and goimportsmake run GO_RUN_ARGS="version -o json"— build then run the CLI with args
After changing any shell script under scripts/ or actions/, run shellcheck scripts/*.sh actions/validate/*.sh — CI runs the same check and fails on any warning.
CI (.github/workflows/test.yaml) runs make test + make lint and fails if the working tree becomes dirty, so always run make test before committing.
Code Conventions
- File header: every
.gofile must start with the two-line Apache-2.0 header — enforced by golangci-lint'srevive.file-headerrule. - Struct tags: only
jsonandinlineare permitted on struct fields (revivestruct-tagrule). - Flag wiring: for any flag with a fixed set of accepted values, add a type under
internal/flags/and register it withcmd.Flags().VarP(&args.x, "name", "n", args.x.Description())rather thanStringVarP— this gets validation, thea|b|ctype hint in--help, and consistent error messages for free. - Command output: inside cobra
RunEhandlers (and helpers they call), emit viacmd.Printf/cmd.PrintErrfand pass*cobra.Commandto helpers — notfmt.Fprintf(cmd.OutOrStdout(), ...).rootCmd.SetOut(os.Stdout)inmain.goalready routescmd.Print*to stdout, and the pattern avoids the_, _ = fmt.Fprintf(...)noise that errcheck forces. - Config file sync: any new flag added to a subcommand that supports
--config(currentlyvalidate) must also be added to the matching API struct inapi/v1beta1/config_types.go(ValidateConfigfor validate) with a lower camelCasejson:tag, and wired intoapplyValidateConfigwith the same!flags.Changed("<name>")gate as the existing fields. - Tests use Gomega (
. "github.com/onsi/gomega"dot-import is accepted — staticcheck ST1001 is disabled project-wide). Table-driven tests are the norm.
Writing Documentation
User-facing changes (flags, commands, report shape, GitHub Action inputs) must be reflected in the docs. The tree is:
README.md— features list, install, quickstart, commands table, doc links.docs/manifests-validation.md—validatereference: flag table, schema resolution, skip rules, CEL rules, config file with example.fluxschema.yml.docs/custom-schema-catalog.md—extract crd/extract k8s/extract openshiftreference and catalog hosting/refresh.docs/field-index.md— the.fields.txtfield index format emitted byextract --with-field-index: naming, line grammar, annotations.docs/repo-discovery.md—discoverreference: flags, classification rules, output formats, and how AI agents should read the inventory.docs/config.md+docs/config-v1beta1.json— config file envelope and its JSON Schema.docs/report.md+docs/report-v1beta1.json— report file envelope and its JSON Schema.docs/inventory.md+docs/inventory-v1beta1.json— inventory envelope (discoveroutput) and its JSON Schema.actions/setup/README.md+actions/validate/README.md— GitHub Action inputs and example workflows.
Apply these rules:
- New or changed flag: update the flag table in the matching guide. For
validateflags that are config-file-eligible, also extend the example.fluxschema.ymlblock in the "Config file" section. - New subcommand: add a row to
README.md's "Commands" table and either a new section in an existing guide or a dedicated guide underdocs/. - Report shape change: update
docs/report.md(andschema-1.0.0.jsonper its versioning rules) and the JSON example under "Output" indocs/manifests-validation.md. - Inventory shape change: edit
api/v1beta1/inventory_types.go, runmake generate-json-schemasto regeneratedocs/inventory-v1beta1.json(also copied into the catalog), then updatedocs/inventory.mdand the examples indocs/repo-discovery.md. - GitHub Action change: when a
validate.shargument or anaction.yamlinput changes, refresh the inputs table and example workflow inactions/validate/README.md.
Builtin Schema Catalog
catalog/latest/ holds the JSON Schemas for Kubernetes and Flux ecosystem CRDs. It is the default schema source for the validate command.
scripts/gen-k8s-schemas.sh -d <dir> [-v <version>]— generates the native Kubernetes schemas.scripts/gen-flux-schemas.sh -d <dir> [-v <version>]— generates the Flux CRD schemas.scripts/gen-crd-schemas.sh -r <owner/repo> -d <dir> [-v <version>]— generates CRD schemas for an arbitrary upstream repo (used for gateway-api and flux-operator).scripts/update-catalog-readme.sh -f <readme>— rewrites the versions table incatalog/README.mdfrom env vars exported by thegen-*scripts.
All generator scripts pass --strip-description so catalog schemas stay small (about 54% reduction on native K8s). If you add another generator, keep that flag on.
Don't hand-edit files under catalog/latest/ — they are kept up-to-date by the .github/workflows/update-catalog.yaml workflow.