Skip to content

test(api): strict-decode config/samples to catch hallucinated CRD fields#1023

Merged
Defilan merged 1 commit into
defilantech:mainfrom
Defilan:fix/validate-samples-strict-decode
Jul 9, 2026
Merged

test(api): strict-decode config/samples to catch hallucinated CRD fields#1023
Defilan merged 1 commit into
defilantech:mainfrom
Defilan:fix/validate-samples-strict-decode

Conversation

@Defilan

@Defilan Defilan commented Jul 9, 2026

Copy link
Copy Markdown
Member

What

A Go test that strict-decodes every Model / InferenceService / ModelRouter document in config/samples/** into its typed struct, failing on unknown or mistyped fields.

Why

The Foreman gate runs Go-only checks, so a config/samples change with invalid CRD fields GATE-PASSes — nothing validates the YAML against the schema. Dogfooding #699 exposed this: a coder rewrote a sample with spec.url (the field is source), a spec.parameters block, modelRef as an object (it is a string), runtime as an object, and spec.service (it is endpoint). The manifest would fail kubectl apply, yet it GATE-PASSed and looked mergeable.

How

sigs.k8s.io/yaml.UnmarshalStrict (YAML → JSON → json.Decoder with DisallowUnknownFields) rejects unknown fields and type mismatches. The test iterates the sample docs, decodes the LLMKube CRD kinds into their structs, and skips foreign kinds (KEDA HTTPScaledObject, core Secret/Service).

Chosen over kubeconform + CRD-schema extraction (the approach floated in #1021): this needs no external tooling or CRD-to-JSON-Schema step, uses the types as the single source of truth, and — crucially — runs in make test, so it is gate-covered. A future #699 would GATE-FAIL, not merely fail a CI-only step.

Testing

Checklist


Assisted-by: Claude Code (identified the gate gap while reviewing Foreman output, wrote the guard; human-reviewed and DCO-signed by the maintainer).

The Foreman gate runs Go-only checks (fmt/vet/lint/test), so a config/samples
change with invalid CRD fields passes: nothing validates the YAML against the
schema. On defilantech#699 a coder rewrote a sample with spec.url (the field is source),
a spec.parameters block, modelRef as an object (it is a string), runtime as an
object, and spec.service (it is endpoint); the manifest would fail kubectl
apply, yet it GATE-PASSed.

Add a test that strict-decodes every Model/InferenceService/ModelRouter doc in
config/samples into its typed struct via sigs.k8s.io/yaml.UnmarshalStrict, so
an unknown or mistyped field fails in `make test` (gate-covered), not at
kubectl apply time. Foreign kinds (HTTPScaledObject, Secret, Service) are
skipped. A companion negative test proves the guard rejects the exact defilantech#699
field errors.

Fixes defilantech#1021

Signed-off-by: Christopher Maher <chris@mahercode.io>
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Defilan Defilan merged commit 1adaf51 into defilantech:main Jul 9, 2026
23 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