Skip to content

ci: auto-delete PR head branch on close #2

ci: auto-delete PR head branch on close

ci: auto-delete PR head branch on close #2

Workflow file for this run

name: PR Labeler
on:
pull_request_target:
types: [opened, reopened, synchronize, edited]
permissions:
contents: read
pull-requests: write
jobs:
label:
name: Apply PR labels
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const author = (pr.user && pr.user.login) || "";
const isDependabot =
author === "dependabot[bot]" ||
author === "dependabot-preview[bot]";
const files = await github.paginate(
github.rest.pulls.listFiles,
{
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
per_page: 100,
}
);
const paths = files.map((f) => f.filename);
core.info(`Changed files (${paths.length}):\n ` + paths.join("\n "));
const isCore = (f) =>
f === "python/FlightRadarAPI/core.py" ||
f === "python/FlightRadarAPI/request.py" ||
f === "nodejs/FlightRadarAPI/core.js" ||
f === "nodejs/FlightRadarAPI/request.js";
const isEntities = (f) =>
/^(python|nodejs)\/FlightRadarAPI\/entities\//.test(f);
const isInPackage = (f) =>
/^(python|nodejs)\/FlightRadarAPI\//.test(f);
const isTests = (f) => /^(python|nodejs)\/tests\//.test(f);
const isCi = (f) => f.startsWith(".github/");
const isDeps = (f) =>
f === "python/pyproject.toml" ||
f === "nodejs/package.json" ||
f === "nodejs/package-lock.json";
const isBuild = (f) =>
/(^|\/)Makefile$/.test(f) ||
f === "nodejs/.eslintrc.json" ||
f === "python/.flake8" ||
f === ".gitignore" ||
f === "nodejs/.npmignore";
const isDocs = (f) =>
f.startsWith("docs/") ||
f === "mkdocs.yml" ||
/\.md$/i.test(f);
const isPython = (f) => f.startsWith("python/");
const isNode = (f) => f.startsWith("nodejs/");
const desired = new Set();
for (const f of paths) {
if (isCore(f)) desired.add("api:core");
if (isEntities(f)) desired.add("api:entities");
if (isInPackage(f) && !isCore(f) && !isEntities(f)) desired.add("api");
if (isTests(f)) desired.add("tests");
if (isCi(f)) desired.add("ci");
if (isDeps(f)) desired.add("deps");
if (isBuild(f)) desired.add("build");
if (isDocs(f)) desired.add("docs");
if (isPython(f)) desired.add("pkg:python");
if (isNode(f)) desired.add("pkg:node");
}
// Dependabot PRs (we only enable Dependabot for security advisories).
if (isDependabot) {
desired.add("deps");
desired.add("security");
}
// Title-based detection (conventional commits: `type(scope)!: subject`).
const titleMap = {
feat: "feature",
fix: "bug",
perf: "performance",
revert: "revert",
docs: "docs",
ci: "ci",
build: "build",
};
const title = pr.title || "";
const titleMatch = title.match(/^(\w+)(?:\(([^)]+)\))?!?:/);
const titleType = titleMatch ? titleMatch[1].toLowerCase() : null;
const titleScope = titleMatch && titleMatch[2]
? titleMatch[2].toLowerCase()
: null;
if (titleType && titleMap[titleType]) {
desired.add(titleMap[titleType]);
}
if (titleScope === "deps" || titleScope === "deps-dev") {
desired.add("deps");
}
// Sync: only manage our labels — leave anything else (issue labels, etc.) alone.
const managed = new Set([
"api:core", "api:entities", "api", "tests",
"ci", "build", "feature", "docs",
"revert", "performance", "bug",
"deps", "security", "pkg:python", "pkg:node",
]);
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const current = new Set(currentLabels.map((l) => l.name));
const toAdd = [...desired].filter((l) => !current.has(l));
const toRemove = [...current].filter(
(l) => managed.has(l) && !desired.has(l)
);
for (const name of toRemove) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
name,
});
}
if (toAdd.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: toAdd,
});
}
core.info(
`Desired: [${[...desired].join(", ")}] | ` +
`Added: [${toAdd.join(", ")}] | ` +
`Removed: [${toRemove.join(", ")}]`
);