mirror of
https://github.com/kharonsec/br-acc
synced 2026-04-25 17:15:02 +02:00
feat: Update PR label from description template (#27)
* feat: update PR label from template - Search the PR text for checkboxes marked in the format [x] release:...`` - Only accepts these labels (the same as the pull_request_template.md template): release:major, release:feature, release:patterns, release:api, release:data, release:privacy, release:fix, release:docs, release:infra, release:security - The job fails if more than one release:* is checked - Removes other old release:* from the PR and adds only the chosen one (keeps “exactly one” in sync) * fix(ci): run auto-labeler on pull_request_target --------- Co-authored-by: bruno cesar <brunoclz@brunos-MacBook-Pro.local>
This commit is contained in:
96
.github/workflows/auto-label.yml
vendored
Normal file
96
.github/workflows/auto-label.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
name: Auto Labeler via PR Description
|
||||
|
||||
on:
|
||||
# pull_request_target is required to write labels on PRs from forks.
|
||||
pull_request_target:
|
||||
types: [opened, edited, synchronize, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
apply-labels:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
issues: write # PR labels are managed via the Issues API.
|
||||
|
||||
steps:
|
||||
- name: Read description and apply labels
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Only apply labels that exist in .github/pull_request_template.md
|
||||
// Change type (choose one release label from taxonomy):
|
||||
const allowedReleaseLabels = new Set([
|
||||
'release:major',
|
||||
'release:feature',
|
||||
'release:patterns',
|
||||
'release:api',
|
||||
'release:data',
|
||||
'release:privacy',
|
||||
'release:fix',
|
||||
'release:docs',
|
||||
'release:infra',
|
||||
'release:security',
|
||||
]);
|
||||
|
||||
const body = context.payload.pull_request.body || '';
|
||||
if (!body.trim()) return;
|
||||
|
||||
// Matches: - [x] `release:major`
|
||||
const checkedReleaseLabelRegex = /\[x\]\s*`(release:[^`]+)`/gi;
|
||||
const selected = [];
|
||||
let match;
|
||||
while ((match = checkedReleaseLabelRegex.exec(body)) !== null) {
|
||||
const label = (match[1] || '').trim();
|
||||
if (allowedReleaseLabels.has(label)) selected.push(label);
|
||||
}
|
||||
|
||||
const uniqueSelected = [...new Set(selected)];
|
||||
if (uniqueSelected.length === 0) {
|
||||
console.log('No release label selected in PR template; skipping.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (uniqueSelected.length > 1) {
|
||||
throw new Error(
|
||||
`Multiple release labels selected: ${uniqueSelected.join(', ')}. Select exactly one.`
|
||||
);
|
||||
}
|
||||
|
||||
const chosen = uniqueSelected[0];
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const issue_number = context.issue.number;
|
||||
|
||||
// Sync: remove other release:* labels from the allowed set, then add the chosen one.
|
||||
const { data: existing } = await github.rest.issues.listLabelsOnIssue({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
});
|
||||
|
||||
const existingReleaseLabels = existing
|
||||
.map(l => l.name)
|
||||
.filter(name => allowedReleaseLabels.has(name));
|
||||
|
||||
const toRemove = existingReleaseLabels.filter(name => name !== chosen);
|
||||
for (const name of toRemove) {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
name,
|
||||
});
|
||||
console.log(`Removed label: ${name}`);
|
||||
}
|
||||
|
||||
if (!existingReleaseLabels.includes(chosen)) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
labels: [chosen],
|
||||
});
|
||||
console.log(`Added label: ${chosen}`);
|
||||
} else {
|
||||
console.log(`Label already present: ${chosen}`);
|
||||
}
|
||||
Reference in New Issue
Block a user