chore: update more setup files

This commit is contained in:
Michael Smith 2025-04-16 20:29:09 +00:00
parent 39b524c0ec
commit bad778e037
5 changed files with 52 additions and 148 deletions

BIN
bun.lockb Executable file

Binary file not shown.

2
bunfig.toml Normal file
View File

@ -0,0 +1,2 @@
[test]
preload = ["./setup.ts"]

146
lint.ts
View File

@ -1,146 +0,0 @@
import { readFile, readdir, stat } from "node:fs/promises";
import * as path from "node:path";
import * as marked from "marked";
import grayMatter from "gray-matter";
const files = await readdir(".", { withFileTypes: true });
const dirs = files.filter((f) => {
return (
f.isDirectory() && !f.name.startsWith(".") && f.name !== "node_modules"
);
});
let badExit = false;
// error reports an error to the console and sets badExit to true
// so that the process will exit with a non-zero exit code.
const error = (...data: readonly unknown[]) => {
console.error(...data);
badExit = true;
};
const verifyCodeBlocks = (
tokens: readonly marked.Token[],
res = {
codeIsTF: false,
codeIsHCL: false,
},
) => {
for (const token of tokens) {
// Check in-depth.
if (token.type === "list") {
verifyCodeBlocks(token.items, res);
continue;
}
if (token.type === "list_item") {
if (token.tokens === undefined) {
throw new Error("Tokens are missing for type list_item");
}
verifyCodeBlocks(token.tokens, res);
continue;
}
if (token.type === "code") {
if (token.lang === "tf") {
res.codeIsTF = true;
}
if (token.lang === "hcl") {
res.codeIsHCL = true;
}
}
}
return res;
};
// Ensures that each README has the proper format.
// Exits with 0 if all is good!
for (const dir of dirs) {
const readme = path.join(dir.name, "README.md");
// Ensure exists
try {
await stat(readme);
} catch (ex) {
throw new Error(`Missing README.md in ${dir.name}`);
}
const content = await readFile(readme, "utf8");
const matter = grayMatter(content);
const data = matter.data as {
display_name?: string;
description?: string;
icon?: string;
maintainer_github?: string;
partner_github?: string;
verified?: boolean;
tags?: string[];
};
if (!data.display_name) {
error(dir.name, "missing display_name");
}
if (!data.description) {
error(dir.name, "missing description");
}
if (!data.icon) {
error(dir.name, "missing icon");
}
if (!data.maintainer_github) {
error(dir.name, "missing maintainer_github");
}
try {
await stat(path.join(".", dir.name, data.icon ?? ""));
} catch (ex) {
error(dir.name, "icon does not exist", data.icon);
}
const tokens = marked.lexer(content);
// Ensure there is an h1 and some text, then a code block
let h1 = false;
let code = false;
let paragraph = false;
let version = true;
for (const token of tokens) {
if (token.type === "heading" && token.depth === 1) {
h1 = true;
continue;
}
if (h1 && token.type === "heading") {
break;
}
if (token.type === "paragraph") {
paragraph = true;
continue;
}
if (token.type === "code") {
code = true;
if (token.lang === "tf" && !token.text.includes("version")) {
version = false;
error(dir.name, "missing version in tf code block");
}
}
}
if (!h1) {
error(dir.name, "missing h1");
}
if (!paragraph) {
error(dir.name, "missing paragraph after h1");
}
if (!code) {
error(dir.name, "missing example code block after paragraph");
}
const { codeIsTF, codeIsHCL } = verifyCodeBlocks(tokens);
if (!codeIsTF) {
error(dir.name, "missing example tf code block");
}
if (codeIsHCL) {
error(dir.name, "hcl code block should be tf");
}
}
if (badExit) {
process.exit(1);
}

View File

@ -4,7 +4,6 @@
"test": "bun test",
"fmt": "bun x prettier -w **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt **/*.tf .sample/main.tf",
"fmt:ci": "bun x prettier --check **/*.sh .sample/run.sh new.sh **/*.ts **/*.md *.md && terraform fmt -check **/*.tf .sample/main.tf",
"lint": "bun run lint.ts && ./terraform_validate.sh",
"update-version": "./update-version.sh"
},
"devDependencies": {
@ -25,4 +24,4 @@
"prettier-plugin-terraform-formatter"
]
}
}
}

49
setup.ts Normal file
View File

@ -0,0 +1,49 @@
import { readableStreamToText, spawn } from "bun";
import { afterAll } from "bun:test";
async function removeStatefiles(): Promise<void> {
const process = spawn([
"find",
".",
"-type",
"f",
"-o",
"-name",
"*.tfstate",
"-o",
"-name",
"*.tfstate.lock.info",
"-delete",
]);
await process.exited;
}
async function removeOldContainers(): Promise<void> {
let process = spawn([
"docker",
"ps",
"-a",
"-q",
"--filter",
"label=modules-test",
]);
let containerIDsRaw = await readableStreamToText(process.stdout);
let exitCode = await process.exited;
if (exitCode !== 0) {
throw new Error(containerIDsRaw);
}
containerIDsRaw = containerIDsRaw.trim();
if (containerIDsRaw === "") {
return;
}
process = spawn(["docker", "rm", "-f", ...containerIDsRaw.split("\n")]);
const stdout = await readableStreamToText(process.stdout);
exitCode = await process.exited;
if (exitCode !== 0) {
throw new Error(stdout);
}
}
afterAll(async () => {
await Promise.all([removeStatefiles(), removeOldContainers()]);
});