repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
scripts/scope.ts
Rawimport { execFileSync } from "node:child_process";
/**
* Pre-commit scope: run check + lint only for the extensions whose files are
* staged. Any staged file outside `extensions/<name>/` (scripts, root config,
* shared test helpers) widens the scope to the whole repository, because it can
* affect every extension. Pre-push stays repository-wide; this keeps the fast,
* offline pre-commit proportional to the change.
*/
function git(args: string[]): string {
return execFileSync("git", args, { encoding: "utf8" });
}
function run(args: string[]): void {
execFileSync("mise", ["run", ...args], { stdio: "inherit" });
}
const dryRun = process.argv.includes("--dry-run");
const staged = git(["diff", "--cached", "--name-only"])
.split("\n")
.map((line) => line.trim())
.filter(Boolean);
const extensions = new Set<string>();
let repositoryWide = false;
for (const file of staged) {
const match = /^extensions\/([^/]+)\//.exec(file);
if (match) extensions.add(match[1] as string);
else repositoryWide = true;
}
if (staged.length === 0) {
console.log("scope: nothing staged");
} else if (repositoryWide || extensions.size === 0) {
console.log("scope: repository-wide (shared files staged) → check + lint");
if (!dryRun) run(["//:check", ":::", "//:lint"]);
} else {
const names = [...extensions].sort();
console.log(`scope: ${names.join(", ")} → check + lint`);
if (!dryRun)
for (const name of names) {
run([`//extensions/${name}:check`]);
run([`//extensions/${name}:lint`]);
}
}