From 405998ad51a96775df44b9231d44b2902819fc47 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Mon, 31 Aug 2026 16:43:21 -0700 Subject: [PATCH] Normalize sheriff exemption labels AI-assisted: implemented and validated by Codex under maintainer direction. --- scripts/github/sheriff.mjs | 11 +++++++++-- tests/github-sheriff.test.mjs | 8 +++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/scripts/github/sheriff.mjs b/scripts/github/sheriff.mjs index 76a78eec7..0cbbb4f8e 100644 --- a/scripts/github/sheriff.mjs +++ b/scripts/github/sheriff.mjs @@ -50,6 +50,10 @@ const CONTRIBUTOR_POLICY_LABELS = new Set([ ]); const SHERIFF_WAIT_COMMAND = /^\/sheriff\s+wait\s*$/i; +function normalizeLabelName(label) { + return String(label || '').trim().toLowerCase(); +} + const PR_QUERY = ` query($owner: String!, $name: String!, $after: String) { repository(owner: $owner, name: $name) { @@ -145,7 +149,9 @@ export function evaluatePullRequest(pr, options = {}) { const closeDays = Number.isFinite(options.closeDays) ? options.closeDays : 14; const maintainers = loginSet(options.maintainers || DEFAULT_MAINTAINERS); const regularContributors = loginSet(options.regularContributors || DEFAULT_REGULAR_CONTRIBUTORS); - const exemptLabels = new Set(options.exemptLabels || DEFAULT_EXEMPT_LABELS); + const exemptLabels = new Set( + (options.exemptLabels || DEFAULT_EXEMPT_LABELS).map(normalizeLabelName), + ); const trustedMarkerAuthors = loginSet(options.trustedMarkerAuthors || DEFAULT_TRUSTED_MARKER_AUTHORS); const autoCloseRegulars = options.autoCloseRegulars === true; @@ -266,7 +272,8 @@ export function evaluatePullRequest(pr, options = {}) { const warningAlreadyPosted = Boolean(warningPostedAt && (!contributorActionBlockerAt || !isAfter(contributorActionBlockerAt, warningPostedAt))); const closeAlreadyPosted = hasMarker(pr.comments, CLOSE_MARKER, trustedMarkerAuthors); - const exemptFromClose = [...labels].some((label) => exemptLabels.has(label)); + const exemptFromClose = [...labels] + .some((label) => exemptLabels.has(normalizeLabelName(label))); const regularContributor = regularContributors.has(author); const shouldWarn = staleEligible && !warningAlreadyPosted; const shouldClose = contributorActionRequired diff --git a/tests/github-sheriff.test.mjs b/tests/github-sheriff.test.mjs index fb916275f..80de7d974 100644 --- a/tests/github-sheriff.test.mjs +++ b/tests/github-sheriff.test.mjs @@ -691,13 +691,19 @@ describe('github sheriff', () => { ], }; const closePlan = evaluatePullRequest(pr(source), { now: NOW, autoCloseRegulars: true }); - const exemptPlan = evaluatePullRequest(pr({ ...source, labels: ['do not close'] }), { + const exemptPlan = evaluatePullRequest(pr({ ...source, labels: ['Do Not Close'] }), { now: NOW, autoCloseRegulars: true, }); + const customExemptPlan = evaluatePullRequest(pr({ ...source, labels: ['Keep Open'] }), { + now: NOW, + autoCloseRegulars: true, + exemptLabels: ['keep open'], + }); assert.equal(closePlan.shouldClose, true); assert.equal(exemptPlan.shouldClose, false); + assert.equal(customExemptPlan.shouldClose, false); }); it('keeps stale comments idempotent', () => {