chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
const LABELS = {
|
||||
"new-cli": {
|
||||
color: "0E8A16",
|
||||
description: "Adds a new CLI or generated harness",
|
||||
},
|
||||
"existing-cli-fix": {
|
||||
color: "1D76DB",
|
||||
description: "Fixes or improves an existing CLI harness",
|
||||
},
|
||||
"cli-anything-skill": {
|
||||
color: "5319E7",
|
||||
description: "Changes CLI-Anything plugin or skill files",
|
||||
},
|
||||
"cli-anything-hub": {
|
||||
color: "FBCA04",
|
||||
description: "Changes CLI-Hub, registries, or hub docs",
|
||||
},
|
||||
"documentation": {
|
||||
color: "0075CA",
|
||||
description: "Documentation issue or improvement",
|
||||
},
|
||||
"github-actions": {
|
||||
color: "6F42C1",
|
||||
description: "Changes GitHub Actions or automation",
|
||||
},
|
||||
};
|
||||
|
||||
const SCRIPT_MANAGED_LABELS = ["new-cli", "existing-cli-fix", "documentation"];
|
||||
const REGISTRY_FILES = new Set([
|
||||
"registry.json",
|
||||
"public_registry.json",
|
||||
"matrix_registry.json",
|
||||
]);
|
||||
|
||||
function isHarnessFile(path) {
|
||||
return /^[^/]+\/agent-harness\//.test(path);
|
||||
}
|
||||
|
||||
function isNewHarnessManifest(file) {
|
||||
return (
|
||||
file.status === "added" &&
|
||||
/^[^/]+\/agent-harness\/(setup\.py|pyproject\.toml)$/.test(file.filename)
|
||||
);
|
||||
}
|
||||
|
||||
function isDocumentationFile(path) {
|
||||
if (/(^|\/)SKILL\.md$/i.test(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
/^README(?:_[A-Z]+)?\.md$/.test(path) ||
|
||||
/^(CONTRIBUTING|SECURITY)\.md$/.test(path) ||
|
||||
/^docs\//.test(path) ||
|
||||
/^[^/]+\/agent-harness\/.*\.md$/i.test(path) ||
|
||||
/^[^/]+\.md$/i.test(path)
|
||||
);
|
||||
}
|
||||
|
||||
function isHarnessImplementationFile(path) {
|
||||
return isHarnessFile(path) && !isDocumentationFile(path);
|
||||
}
|
||||
|
||||
function titleLooksLikeRegistryCli(title) {
|
||||
return /\b(add|introduce|new)\b/i.test(title) && /\b(cli|harness|registry)\b/i.test(title);
|
||||
}
|
||||
|
||||
function computeScriptLabels(files, title) {
|
||||
const paths = files.map((file) => file.filename);
|
||||
const labelsToApply = new Set();
|
||||
|
||||
const hasHarnessImplementationChange = paths.some(isHarnessImplementationFile);
|
||||
const hasNewHarness = files.some(isNewHarnessManifest);
|
||||
const registryOnly = paths.length > 0 && paths.every((path) => REGISTRY_FILES.has(path));
|
||||
const registryNewCli = registryOnly && titleLooksLikeRegistryCli(title || "");
|
||||
const documentationOnly = paths.length > 0 && paths.every(isDocumentationFile);
|
||||
|
||||
if (hasNewHarness || registryNewCli) {
|
||||
labelsToApply.add("new-cli");
|
||||
} else if (hasHarnessImplementationChange) {
|
||||
labelsToApply.add("existing-cli-fix");
|
||||
}
|
||||
|
||||
if (documentationOnly) {
|
||||
labelsToApply.add("documentation");
|
||||
}
|
||||
|
||||
return labelsToApply;
|
||||
}
|
||||
|
||||
async function ensureLabels(github, owner, repo, core) {
|
||||
const existing = await github.paginate(github.rest.issues.listLabelsForRepo, {
|
||||
owner,
|
||||
repo,
|
||||
per_page: 100,
|
||||
});
|
||||
const existingNames = new Set(existing.map((label) => label.name));
|
||||
|
||||
for (const [name, definition] of Object.entries(LABELS)) {
|
||||
if (existingNames.has(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(`Creating missing label: ${name}`);
|
||||
await github.rest.issues.createLabel({
|
||||
owner,
|
||||
repo,
|
||||
name,
|
||||
color: definition.color,
|
||||
description: definition.description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function syncScriptLabels(github, owner, repo, pullNumber, currentLabels, labelsToApply, core) {
|
||||
for (const label of labelsToApply) {
|
||||
if (currentLabels.has(label)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(`Adding label: ${label}`);
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pullNumber,
|
||||
labels: [label],
|
||||
});
|
||||
}
|
||||
|
||||
for (const label of SCRIPT_MANAGED_LABELS) {
|
||||
if (!currentLabels.has(label) || labelsToApply.has(label)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(`Removing label: ${label}`);
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pullNumber,
|
||||
name: label,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.status !== 404) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
const pullRequest = context.payload.pull_request;
|
||||
if (!pullRequest) {
|
||||
core.info("No pull_request payload found; skipping PR labeling.");
|
||||
return;
|
||||
}
|
||||
|
||||
const { owner, repo } = context.repo;
|
||||
const pullNumber = pullRequest.number;
|
||||
|
||||
await ensureLabels(github, owner, repo, core);
|
||||
|
||||
const files = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const labelsToApply = computeScriptLabels(files, pullRequest.title);
|
||||
|
||||
const currentLabels = new Set((pullRequest.labels || []).map((label) => label.name));
|
||||
await syncScriptLabels(github, owner, repo, pullNumber, currentLabels, labelsToApply, core);
|
||||
};
|
||||
|
||||
module.exports.computeScriptLabels = computeScriptLabels;
|
||||
module.exports.LABELS = LABELS;
|
||||
module.exports.SCRIPT_MANAGED_LABELS = SCRIPT_MANAGED_LABELS;
|
||||
Reference in New Issue
Block a user