Skip to content
Docs menu / konfig crd

konfig crd

Helm charts often ship CustomResourceDefinitions, and writing those custom resources by hand in TypeScript means guessing at field names. konfig crd reads the CRDs bundled with your registered charts and generates TypeScript types for them, so custom resources can be authored with editor completion and type checking. extract writes the type files; verify regenerates them into a temp directory and fails when the committed copies differ, which makes it a CI drift check.

Usage

Terminal window
konfig crd extract --release <id> | --all
konfig crd verify

Flags (extract)

NameDefaultDescription
--release <id>unsetChart release id to extract.
--allfalseExtract for every chart in the registry.

One of --release or --all is required. Passing neither prints Specify --release <id> or --all and fails with MissingCrdFlags. When both are given, --release wins and --all is ignored. Running --all against an empty registry prints No chart definitions found in <dir> and exits 0. verify has no flags or arguments.

What it reads

Both subcommands need four locations: the chart registry, the tarball cache, the output directory, and the minimum Helm version. Each is resolved through the shared precedence chain described on the konfig.json page: an environment variable if set, otherwise the matching konfig.json field, otherwise a built-in default. Outside a konfig project (no konfig.json found) only the environment variable and built-in default apply.

SettingEnvironment variablekonfig.json fieldDefault
Chart registry directoryKONFIG_CHARTS_DIRchartsinfra/k8s-konfig/charts
Tarball cacheKONFIG_HELM_CACHEhelm.cacheDir.konfig/helm-cache
Output directoryKONFIG_CRD_OUT_DIRcrd.outDir.generated/crd
Minimum Helm versionKONFIG_HELM_MIN_VERSIONhelm.minVersion3.16.0

The chart registry is a directory of TypeScript files, one per chart. Every .ts file whose name does not start with _ is imported and scanned for an export that carries the marker _konfigHelmRelease: true. That object becomes one registry entry with a repository URL, chart name, version, an optional id (defaulting to the file name without .ts), and an optional digest. Chart names, versions, and repository URLs (http(s) or oci) are checked against strict patterns so shell metacharacters never reach helm.

infra/k8s-konfig/charts/postgres.ts
export const chart = {
_konfigHelmRelease: true,
id: "postgres",
repo: "https://charts.bitnami.com/bitnami",
chart: "postgresql",
version: "16.0.0",
digest: "sha256:..."
}

Behaviour

Both subcommands start by running helm version --short. When helm is missing or older than the minimum version, the command fails with HelmVersionTooLow.

For each release, the command collects CRDs from two sources. First it runs helm pull --repo <repo> <chart> --version <v> --untar into a scoped temp directory and reads crds/*.yaml and crds/*.yml from the unpacked chart. Then it pulls the tarball into the cache and runs helm template <chart> <tgz> --include-crds --no-hooks. The two sets are parsed and de-duplicated by CRD name.

How the tarball is cached depends on whether the registry entry records a digest. With a digest, the tarball is verified and stored under <cache>/<chart>-<version>-<digest12>.tgz, and that file is looked up first on the next run. This is the same slot that konfig helm fetch and render-time Helm.release({ digest }) use. Without a digest, the tarball is stored under the plain <cache>/<chart>-<version>.tgz, and the pull is skipped when that file already exists.

For every CustomResourceDefinition, the command takes the OpenAPI schema of the first version that declares one and compiles it with json-schema-to-typescript into an exported type. The type is named <Resource>Input, where the resource part of the CRD name is split on - and _ and PascalCased, and it is followed by a comment naming the CRD, its group, and its versions. A CRD with no schema in any version is compiled as an open object ({ type: "object", additionalProperties: true }); a schema that fails to compile falls back to Record<string, unknown>.

Output goes to <outDir>/<id>.ts. Every file starts with the header line // Generated by @konfig.ts/cli, followed on the same line by a do-not-edit note. A chart without CRDs still gets a stub file with that header, a // No CRDs found in chart <chart>@<version> comment, and export {};, so its presence in the registry is visible.

verify regenerates every registry entry into a temp directory and compares each result byte-for-byte with the committed <outDir>/<id>.ts. A committed file that is missing, or that lacks the generated header, is reported as <id>.ts (missing generated header). A registry with no entries prints a No chart definitions found note and exits 0.

Exit codes and errors

ErrorWhen
ReleaseNotFound { releaseId }--release names an id that is not in the registry; the message lists the available ids.
MissingCrdFlagsNeither --release nor --all was given.
CrdDrift { drifted }verify found differences, after printing CRD drift detected in: ... and Run konfig crd extract --all to regenerate.
HelmVersionTooLowhelm is missing or older than the minimum version.
ChartRegistryErrorLoading the chart registry failed (for example a chart file could not be imported).
ChartRegistryEntryDecodeErrorA registry entry does not match the expected shape or patterns.
CrdInputDecodeErrorThe extract inputs (repo, chart, version) were rejected by the schema that guards the shell arguments.
CrdExtractError { chart, cause }Any other failure while extracting one chart, such as a failed pull, template, or write.

Example

Terminal window
KONFIG_CHARTS_DIR=infra/charts konfig crd extract --all
konfig crd verify # in CI: non-zero exit when .generated/crd is stale