diff --git a/README.md b/README.md index 67c4ba3fd..f930eb1ab 100644 --- a/README.md +++ b/README.md @@ -60,5 +60,7 @@ jobs: stale-issue-message: 'Stale issue message' stale-pr-message: 'Stale issue message' stale-issue-label: 'no-issue-activity' + exempt-issue-label: 'awaiting-approval' stale-pr-label: 'no-pr-activity' + exempt-pr-label: 'awaiting-approval' ``` diff --git a/action.yml b/action.yml index f7f20f451..b2bb534d0 100644 --- a/action.yml +++ b/action.yml @@ -6,24 +6,28 @@ inputs: description: 'Token for the repo. Can be passed in using {{ secrets.GITHUB_TOKEN }}' required: true stale-issue-message: - description: 'The message to post on the issue when tagging it. If none provided, will not mark iusses stale.' + description: 'The message to post on the issue when tagging it. If none provided, will not mark issues stale.' stale-pr-message: - description: 'The message to post on the pr when tagging it. If none provided, will not mark prs stale.' + description: 'The message to post on the pr when tagging it. If none provided, will not mark pull requests stale.' days-before-stale: description: 'The number of days old an issue can be before marking it stale' default: 60 days-before-close: - description: 'The number of days to wait to close an issue or pr after it being marked stale' + description: 'The number of days to wait to close an issue or pull request after it being marked stale' default: 7 stale-issue-label: description: 'The label to apply when an issue is stale' default: 'Stale' + exempt-issue-label: + description: 'The label to apply when an issue is exempt from being marked stale' stale-pr-label: - description: 'The label to apply when a pr is stale' + description: 'The label to apply when a pull request is stale' default: 'Stale' + exempt-pr-label: + description: 'The label to apply when a pull request is exempt from being marked stale' operations-per-run: description: 'The maximum number of operations per run, used to control rate limiting' default: 30 runs: using: 'node12' - main: 'lib/main.js' \ No newline at end of file + main: 'lib/main.js' diff --git a/lib/main.js b/lib/main.js index a2dea0b19..b07059553 100644 --- a/lib/main.js +++ b/lib/main.js @@ -52,7 +52,11 @@ function processIssues(client, args, operationsLeft, page = 1) { continue; } let staleLabel = isPr ? args.stalePrLabel : args.staleIssueLabel; - if (isLabeledStale(issue, staleLabel)) { + let exemptLabel = isPr ? args.exemptPrLabel : args.exemptIssueLabel; + if (exemptLabel && isLabeled(issue, exemptLabel)) { + continue; + } + else if (isLabeled(issue, staleLabel)) { if (wasLastUpdatedBefore(issue, args.daysBeforeClose)) { operationsLeft -= yield closeIssue(client, issue); } @@ -71,7 +75,7 @@ function processIssues(client, args, operationsLeft, page = 1) { return yield processIssues(client, args, operationsLeft, page + 1); }); } -function isLabeledStale(issue, label) { +function isLabeled(issue, label) { const labelComparer = l => label.localeCompare(l.name, undefined, { sensitivity: 'accent' }) === 0; return issue.labels.filter(labelComparer).length > 0; } @@ -118,7 +122,9 @@ function getAndValidateArgs() { daysBeforeStale: parseInt(core.getInput('days-before-stale', { required: true })), daysBeforeClose: parseInt(core.getInput('days-before-close', { required: true })), staleIssueLabel: core.getInput('stale-issue-label', { required: true }), + exemptIssueLabel: core.getInput('exempt-issue-label'), stalePrLabel: core.getInput('stale-pr-label', { required: true }), + exemptPrLabel: core.getInput('exempt-pr-label'), operationsPerRun: parseInt(core.getInput('operations-per-run', { required: true })) }; for (var numberInput of [ diff --git a/src/main.ts b/src/main.ts index e2524b932..b24d62871 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,7 +12,9 @@ type Args = { daysBeforeStale: number; daysBeforeClose: number; staleIssueLabel: string; + exemptIssueLabel: string; stalePrLabel: string; + exemptPrLabel: string; operationsPerRun: number; }; @@ -59,8 +61,11 @@ async function processIssues( } let staleLabel = isPr ? args.stalePrLabel : args.staleIssueLabel; + let exemptLabel = isPr ? args.exemptPrLabel : args.exemptIssueLabel; - if (isLabeledStale(issue, staleLabel)) { + if (exemptLabel && isLabeled(issue, exemptLabel)) { + continue; + } else if (isLabeled(issue, staleLabel)) { if (wasLastUpdatedBefore(issue, args.daysBeforeClose)) { operationsLeft -= await closeIssue(client, issue); } else { @@ -85,7 +90,7 @@ async function processIssues( return await processIssues(client, args, operationsLeft, page + 1); } -function isLabeledStale(issue: Issue, label: string): boolean { +function isLabeled(issue: Issue, label: string): boolean { const labelComparer: (l: IssueLabel) => boolean = l => label.localeCompare(l.name, undefined, {sensitivity: 'accent'}) === 0; return issue.labels.filter(labelComparer).length > 0; @@ -151,7 +156,9 @@ function getAndValidateArgs(): Args { core.getInput('days-before-close', {required: true}) ), staleIssueLabel: core.getInput('stale-issue-label', {required: true}), + exemptIssueLabel: core.getInput('exempt-issue-label'), stalePrLabel: core.getInput('stale-pr-label', {required: true}), + exemptPrLabel: core.getInput('exempt-pr-label'), operationsPerRun: parseInt( core.getInput('operations-per-run', {required: true}) )