Files
openclaw/test/scripts/labeler-extension-coverage.test.ts
T
Peter Steinberger 3156b67708 ci(labeler): fix dead rules, cover all plugin dirs, drop vendored artifacts (#121348)
* ci(labeler): fix dead rules and cover unlabeled plugin dirs

* chore: drop vendored swabble workflow and empty ActivityWidget asset catalog
2026-08-09 22:28:02 -07:00

39 lines
1.5 KiB
TypeScript

import { readdirSync, readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
type LabelerRule = Array<{
"changed-files"?: Array<{
"any-glob-to-any-file"?: string[];
}>;
}>;
const repoRoot = path.resolve(fileURLToPath(new URL("../..", import.meta.url)));
const extensionsRoot = path.join(repoRoot, "extensions");
const labelerPath = path.join(repoRoot, ".github/labeler.yml");
const extensionDirectories = readdirSync(extensionsRoot, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name)
.sort();
const extensionDirectorySet = new Set(extensionDirectories);
const labeler = parse(readFileSync(labelerPath, "utf8")) as Record<string, LabelerRule>;
const extensionGlobDirectories = Object.values(labeler)
.flatMap((rules) => rules)
.flatMap((rule) => rule["changed-files"] ?? [])
.flatMap((changedFiles) => changedFiles["any-glob-to-any-file"] ?? [])
.flatMap((glob) => glob.match(/^extensions\/([^/]+)\//)?.[1] ?? []);
const coveredExtensionDirectories = new Set(extensionGlobDirectories);
describe("labeler extension coverage", () => {
it("covers every extension directory", () => {
expect(extensionDirectories.filter((dir) => !coveredExtensionDirectories.has(dir))).toEqual([]);
});
it("references only existing extension directories", () => {
expect(extensionGlobDirectories.filter((dir) => !extensionDirectorySet.has(dir))).toEqual([]);
});
});