Add support for adding & removing labels when no longer stale (#468)

* Add support for adding & removing labels when no longer stale

* Add remove/addLabelsWhenUpdatedFromStale to relevant spec files. Modify arguments to remove ambiguity in 'labels' var & parameter

* Change parameters for clarity, let autoformat do its thing

* PR feedback: More useful logging when removing labels

* Wrap client calls in try catches

* Use Unstale in variable names

* Don't run add label logic under debug

* Add test for labels added to unstale issues

* PR Feedback: logging

* Update README

* Rename vars to labels-to-add/remove-when-unstale

* Apply doc suggestions from code review

Co-authored-by: Geoffrey Testelin <geoffrey.testelin@gmail.com>

* PR Feedback

Co-authored-by: Geoffrey Testelin <geoffrey.testelin@gmail.com>
This commit is contained in:
Ben Villalobos
2021-06-08 06:31:20 -07:00
committed by GitHub
parent 52f5648db3
commit b1da9e1fb1
9 changed files with 212 additions and 11 deletions

View File

@@ -55,7 +55,9 @@ describe('Issue', (): void => {
exemptAllAssignees: false,
exemptAllIssueAssignees: undefined,
exemptAllPrAssignees: undefined,
enableStatistics: false
enableStatistics: false,
labelsToRemoveWhenUnstale: '',
labelsToAddWhenUnstale: ''
};
issueInterface = {
title: 'dummy-title',

View File

@@ -75,6 +75,7 @@ export class IssuesProcessor {
readonly closedIssues: Issue[] = [];
readonly deletedBranchIssues: Issue[] = [];
readonly removedLabelIssues: Issue[] = [];
readonly addedLabelIssues: Issue[] = [];
constructor(options: IIssuesProcessorOptions) {
this.options = options;
@@ -127,6 +128,13 @@ export class IssuesProcessor {
);
}
const labelsToAddWhenUnstale: string[] = wordsToList(
this.options.labelsToAddWhenUnstale
);
const labelsToRemoveWhenUnstale: string[] = wordsToList(
this.options.labelsToRemoveWhenUnstale
);
for (const issue of issues.values()) {
// Stop the processing if no more operations remains
if (!this.operations.hasRemainingOperations()) {
@@ -135,7 +143,12 @@ export class IssuesProcessor {
const issueLogger: IssueLogger = new IssueLogger(issue);
await issueLogger.grouping(`$$type #${issue.number}`, async () => {
await this.processIssue(issue, actor);
await this.processIssue(
issue,
actor,
labelsToAddWhenUnstale,
labelsToRemoveWhenUnstale
);
});
}
@@ -169,7 +182,12 @@ export class IssuesProcessor {
return this.processIssues(page + 1);
}
async processIssue(issue: Issue, actor: string): Promise<void> {
async processIssue(
issue: Issue,
actor: string,
labelsToAddWhenUnstale: Readonly<string>[],
labelsToRemoveWhenUnstale: Readonly<string>[]
): Promise<void> {
this._statistics?.incrementProcessedItemsCount(issue);
const issueLogger: IssueLogger = new IssueLogger(issue);
@@ -438,6 +456,8 @@ export class IssuesProcessor {
issue,
staleLabel,
actor,
labelsToAddWhenUnstale,
labelsToRemoveWhenUnstale,
closeMessage,
closeLabel
);
@@ -549,6 +569,8 @@ export class IssuesProcessor {
issue: Issue,
staleLabel: string,
actor: string,
labelsToAddWhenUnstale: Readonly<string>[],
labelsToRemoveWhenUnstale: Readonly<string>[],
closeMessage?: string,
closeLabel?: string
) {
@@ -608,6 +630,10 @@ export class IssuesProcessor {
);
await this._removeStaleLabel(issue, staleLabel);
// Are there labels to remove or add when an issue is no longer stale?
await this._removeLabelsWhenUnstale(issue, labelsToRemoveWhenUnstale);
await this._addLabelsWhenUnstale(issue, labelsToAddWhenUnstale);
issueLogger.info(`Skipping the process since the $$type is now un-stale`);
return; // Nothing to do because it is no longer stale
@@ -956,6 +982,63 @@ export class IssuesProcessor {
return this.options.removeStaleWhenUpdated;
}
private async _removeLabelsWhenUnstale(
issue: Issue,
removeLabels: Readonly<string>[]
): Promise<void> {
if (!removeLabels.length) {
return;
}
const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info(
`Removing all the labels specified via the ${this._logger.createOptionLink(
Option.LabelsToRemoveWhenUnstale
)} option.`
);
for (const label of removeLabels.values()) {
await this._removeLabel(issue, label);
}
}
private async _addLabelsWhenUnstale(
issue: Issue,
labelsToAdd: Readonly<string>[]
): Promise<void> {
if (!labelsToAdd.length) {
return;
}
const issueLogger: IssueLogger = new IssueLogger(issue);
issueLogger.info(
`Adding all the labels specified via the ${this._logger.createOptionLink(
Option.LabelsToAddWhenUnstale
)} option.`
);
this.addedLabelIssues.push(issue);
try {
this.operations.consumeOperation();
this._statistics?.incrementAddedItemsLabel(issue);
if (!this.options.debugOnly) {
await this.client.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: labelsToAdd
});
}
} catch (error) {
this._logger.error(
`Error when adding labels after updated from stale: ${error.message}`
);
}
}
private async _removeStaleLabel(
issue: Issue,
staleLabel: Readonly<string>

View File

@@ -40,5 +40,7 @@ export enum Option {
ExemptAllAssignees = 'exempt-all-assignees',
ExemptAllIssueAssignees = 'exempt-all-issue-assignees',
ExemptAllPrAssignees = 'exempt-all-pr-assignees',
EnableStatistics = 'enable-statistics'
EnableStatistics = 'enable-statistics',
LabelsToRemoveWhenUnstale = 'labels-to-remove-when-unstale',
LabelsToAddWhenUnstale = 'labels-to-add-when-unstale'
}

View File

@@ -45,4 +45,6 @@ export interface IIssuesProcessorOptions {
exemptAllIssueAssignees: boolean | undefined;
exemptAllPrAssignees: boolean | undefined;
enableStatistics: boolean;
labelsToRemoveWhenUnstale: string;
labelsToAddWhenUnstale: string;
}

View File

@@ -81,7 +81,9 @@ function _getAndValidateArgs(): IIssuesProcessorOptions {
exemptAllAssignees: core.getInput('exempt-all-assignees') === 'true',
exemptAllIssueAssignees: _toOptionalBoolean('exempt-all-issue-assignees'),
exemptAllPrAssignees: _toOptionalBoolean('exempt-all-pr-assignees'),
enableStatistics: core.getInput('enable-statistics') === 'true'
enableStatistics: core.getInput('enable-statistics') === 'true',
labelsToRemoveWhenUnstale: core.getInput('labels-to-remove-when-unstale'),
labelsToAddWhenUnstale: core.getInput('labels-to-add-when-unstale')
};
for (const numberInput of [