import { execFileSync } from "node:child_process"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; import { debianAdapter } from "@/engine/adapter/debian"; import { katalogLaden } from "@/engine/katalog/laden"; import { profileAufloesen } from "@/engine/profile/aufloesen"; import { profileRendern } from "@/engine/profile/rendern"; /** shellcheck über Docker – läuft nur, wenn Docker und das Image da sind, und sagt das sonst. */ function shellcheckVerfuegbar(): boolean { try { execFileSync("docker", ["image", "inspect", "koalaman/shellcheck:stable"], { stdio: "ignore" }); return true; } catch { console.warn("shellcheck übersprungen: docker oder koalaman/shellcheck:stable fehlt"); return false; } } describe.runIf(shellcheckVerfuegbar())("shellcheck", () => { it("findet in den gerenderten Katalogprofilen nichts", async () => { const katalog = await katalogLaden("catalog"); const profile = new Map(katalog.profile.map((p) => [p.eintrag.id, p.eintrag])); const ordner = mkdtempSync(join(tmpdir(), "pd-sc-")); for (const { eintrag: distro } of katalog.distributionen) { const aufgeloest = profileAufloesen(["docker", "zabbix-agent"], profile, "debian", { base: { fail2ban: true }, "zabbix-agent": { server: "zbx" }, }); if (!aufgeloest.ok) throw new Error("Auflösung fehlgeschlagen"); const { skript } = profileRendern( aufgeloest.profile, debianAdapter, { os: distro.os, gast: { name: "g", benutzer: "u" } }, [debianAdapter.benutzerAnlegen({ name: "u", sshSchluessel: ["ssh-ed25519 AAAA u"], sudo: true })], ); writeFileSync(join(ordner, `${distro.id}.sh`), skript); } const ausgabe = (() => { try { execFileSync( "bash", ["-c", `docker run --rm -v ${ordner}:/s:ro koalaman/shellcheck:stable -s bash /s/*.sh`], { stdio: "pipe" }, ); return ""; } catch (fehler) { return String((fehler as { stdout?: Buffer }).stdout ?? fehler); } })(); expect(ausgabe).toBe(""); }, 60_000); it("findet in den Betriebsskripten nichts (Installer, Paket, CLI-Build)", () => { const dateien = [ "deploy/install-lxc.sh", "deploy/im-container.sh", "scripts/paket-bauen.sh", "scripts/cli-pruefen.sh", "cli/bauen.sh", ]; const ausgabe = (() => { try { execFileSync( "docker", [ "run", "--rm", "-v", `${process.cwd()}:/mnt:ro`, "-w", "/mnt", "koalaman/shellcheck:stable", ...dateien, ], { stdio: "pipe" }, ); return ""; } catch (fehler) { return String((fehler as { stdout?: Buffer }).stdout ?? fehler); } })(); expect(ausgabe).toBe(""); }, 60_000); });