Files
renovate/lib/modules/manager/helmfile/schema.ts
Sebastian Poxhofer a31f9cf0f9 refactor(schemas): prefer Nullish schema utils instead of z.nullish() (#44565)
* ci(linter): add renovate/prefer-zod-nullish rule

Add a custom oxlint rule that flags zod chains calling .optional() and
.nullable() adjacently (in either order) and suggests .nullish(), which
is equivalent (both accept undefined | null in zod v4).

Fix all 26 pre-existing violations across 6 schema files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(linter): prefer schema-utils Nullish over zod .nullish()

Rename prefer-zod-nullish to prefer-nullish-util and extend it to flag
.nullish() itself, including the standalone forms z.nullish(x) and
z.optional(z.nullable(x)). Migrate all call sites to Nullish() and
DeepNullish() from schema-utils, which normalize null to undefined in
parsed output. Schemas with more than one nullish position are wrapped
in DeepNullish(); nullish object properties with nullish members use
Nullish(DeepNullish(...)) to keep the optional property type marker.

Spec files are exempt (result.spec.ts intentionally tests
null-preserving parses). Spec assertions expecting null in parsed
output were updated to undefined. Note: docker manifests with an
explicit "mediaType": null are now accepted and treated like an absent
mediaType instead of failing the discriminated union.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 10:15:55 +00:00

39 lines
1.1 KiB
TypeScript

import { z } from 'zod/v4';
import {
LooseArray,
LooseRecord,
Nullish,
Yaml,
} from '../../../util/schema-utils/index.ts';
export const HelmRepository = z.object({
name: z.string(),
url: z.string(),
oci: z.boolean().optional(),
});
export type HelmRepository = z.infer<typeof HelmRepository>;
export const HelmRelease = z.object({
name: z.string(),
chart: z.string(),
version: Nullish(z.string().or(z.number())).transform((version) =>
version ? version.toString() : null,
),
strategicMergePatches: z.unknown().optional(),
jsonPatches: z.unknown().optional(),
transformers: z.unknown().optional(),
});
export type HelmRelease = z.infer<typeof HelmRelease>;
export const Doc = z.object({
releases: LooseArray(HelmRelease).optional(),
templates: LooseRecord(HelmRelease).optional(),
repositories: LooseArray(HelmRepository).optional(),
});
export type Doc = z.infer<typeof Doc>;
export const LockVersion = Yaml.pipe(
z.object({ version: z.string() }).transform(({ version }) => version),
);
export type LockVersion = z.infer<typeof LockVersion>;