Skip to content

Commit

Permalink
feat(issue): remove the stale label when the creation date of the lab…
Browse files Browse the repository at this point in the history
…el is sooner than the update date
  • Loading branch information
C0ZEN committed Nov 14, 2021
1 parent 747f6ab commit b66d9b3
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ To help us have a clear vision over the workflow and also for you if you are jus
- Fetch all the open issues per batch of 20, sorted by update date from the oldest first
- Check if the issue is locked and stop the processing if this is the case
- Check if the issue has any of the ignored labels and stop the processing if this is the case (coming from the `issue-ignore-any-labels` input)
- Check if the issue has already a stale state (stale label)
- If the issue has a stale label, check if it was updated after the addition of the stale label
- If it was updated, remove the stale state (stale label) and stop the processing
- Else, continue (todo -> handle the closing logic)
- Check if the issue last update is older than X days (coming from the `issue-days-before-stale`)
- If the issue last update is older than X days (coming from the `issue-days-before-stale`)
- Add a label to stale (coming from the `issue-stale-label` input, ignored in `dry-run` mode)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@ Contributions of any kind are welcome!

[Geoffrey 'C0ZEN' Testelin](https://github.com/C0ZEN) was originally a contributor of [@actions/stale](https://github.com/actions/stale) (see the [contributors](https://github.com/actions/stale/graphs/contributors)).
Due to slower cadence and different opinions over how the project should go forward, he decided to start from scratch on his own.
The main difference is that this project aims to provide the best stale action as possible, the lack of skills is the limit. ;)
The main difference is that this project aims to provide the best stale action as possible based on consumers needs, even if it may be hard to provide such features. #noLimit - we do what we can to have an amazing stale action ;)
81 changes: 78 additions & 3 deletions src/core/issues/issue-processor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,36 @@ describe(`IssueProcessor`, (): void => {
expect(loggerInfoSpy).toHaveBeenCalledWith(`Already stale`);
expect(processForStaleSpy).not.toHaveBeenCalled();
});

describe(`when the stale state was removed`, (): void => {
beforeEach((): void => {
processToRemoveStaleSpy.mockResolvedValue(true);
});

it(`should stop the processing`, async (): Promise<void> => {
expect.assertions(2);

await issueProcessor.process();

expect(stopProcessingSpy).toHaveBeenCalledTimes(1);
expect(stopProcessingSpy).toHaveBeenCalledWith();
});
});

describe(`when the stale state was not removed`, (): void => {
beforeEach((): void => {
processToRemoveStaleSpy.mockResolvedValue(false);
});

it(`should stop the processing`, async (): Promise<void> => {
expect.assertions(2);

await issueProcessor.process();

expect(stopProcessingSpy).toHaveBeenCalledTimes(1);
expect(stopProcessingSpy).toHaveBeenCalledWith();
});
});
});

describe(`when the issue is not stale yet`, (): void => {
Expand Down Expand Up @@ -420,15 +450,60 @@ describe(`IssueProcessor`, (): void => {
mockedIssueRemoveStaleProcessor.mockClear();
});

it(`should remove the stale state on this issue`, async (): Promise<void> => {
it(`should check if the stale state should be removed`, async (): Promise<void> => {
expect.assertions(4);

await issueProcessor.processToRemoveStale$$();

expect(mockedIssueRemoveStaleProcessor).toHaveBeenCalledTimes(1);
expect(mockedIssueRemoveStaleProcessor).toHaveBeenCalledWith(issueProcessor);
expect(mockedIssueRemoveStaleProcessor.prototype.removeStale.mock.calls).toHaveLength(1);
expect(mockedIssueRemoveStaleProcessor.prototype.removeStale.mock.calls[0]).toHaveLength(0);
expect(mockedIssueRemoveStaleProcessor.prototype.shouldRemoveStale.mock.calls).toHaveLength(1);
expect(mockedIssueRemoveStaleProcessor.prototype.shouldRemoveStale.mock.calls[0]).toHaveLength(0);
});

describe(`when the stale state should be removed`, (): void => {
beforeEach((): void => {
mockedIssueRemoveStaleProcessor.prototype.shouldRemoveStale.mockResolvedValue(true);
});

it(`should remove the stale state on this issue`, async (): Promise<void> => {
expect.assertions(2);

await issueProcessor.processToRemoveStale$$();

expect(mockedIssueRemoveStaleProcessor.prototype.removeStale.mock.calls).toHaveLength(1);
expect(mockedIssueRemoveStaleProcessor.prototype.removeStale.mock.calls[0]).toHaveLength(0);
});

it(`should return true`, async (): Promise<void> => {
expect.assertions(1);

const result = await issueProcessor.processToRemoveStale$$();

expect(result).toBeTrue();
});
});

describe(`when the stale state should not be removed`, (): void => {
beforeEach((): void => {
mockedIssueRemoveStaleProcessor.prototype.shouldRemoveStale.mockResolvedValue(false);
});

it(`should not remove the stale state on this issue`, async (): Promise<void> => {
expect.assertions(1);

await issueProcessor.processToRemoveStale$$();

expect(mockedIssueRemoveStaleProcessor.prototype.removeStale.mock.calls).toHaveLength(0);
});

it(`should return false`, async (): Promise<void> => {
expect.assertions(1);

const result = await issueProcessor.processToRemoveStale$$();

expect(result).toBeFalse();
});
});
});
});
Expand Down
34 changes: 20 additions & 14 deletions src/core/issues/issue-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IssueLogger } from '@core/issues/issue-logger';
import { IssueRemoveStaleProcessor } from '@core/issues/issue-remove-stale-processor';
import { IssueStaleProcessor } from '@core/issues/issue-stale-processor';
import { IGithubApiIssue } from '@github/api/issues/interfaces/github-api-issue.interface';
import { iso8601ToDatetime } from '@utils/dates/iso-8601-to-datetime';
import { createLink } from '@utils/links/create-link';
import { LoggerFormatService } from '@utils/loggers/logger-format.service';
import _ from 'lodash';
Expand Down Expand Up @@ -45,10 +46,14 @@ export class IssueProcessor {
if (this.isAlreadyStale$$()) {
this.logger.info(`Already stale`);

await this.processToRemoveStale$$();
const isStaleStateRemoved: boolean = await this.processToRemoveStale$$();

// @todo add the closing logic here
this.stopProcessing$$();
if (!isStaleStateRemoved) {
// @todo add the closing logic here
this.stopProcessing$$();
} else {
this.stopProcessing$$();
}

return;
}
Expand All @@ -62,13 +67,7 @@ export class IssueProcessor {
* @returns {DateTime} Returns the updatedAt field formatted as a {DateTime}
*/
public getUpdatedAt(): DateTime {
const dateTime: DateTime = DateTime.fromISO(this.githubIssue.updatedAt);

if (_.isString(dateTime.invalidReason)) {
throw new Error(dateTime.invalidReason);
}

return dateTime;
return iso8601ToDatetime(this.githubIssue.updatedAt);
}

/**
Expand Down Expand Up @@ -119,13 +118,20 @@ export class IssueProcessor {

/**
* @description
* Used to remove the stale state from the issue
* Used to remove the stale state from the issue (when the conditions are met)
* Typically, the stale label should be removed by this
* @returns {Promise<void>} No useful information returned
* If the stale state was removed, the processing should be stopped
* @returns {Promise<boolean>} Returns true when the stale state was removed and the processing should be stopped
*/
public processToRemoveStale$$(): Promise<void> {
public async processToRemoveStale$$(): Promise<boolean> {
const issueRemoveStaleProcessor: IssueRemoveStaleProcessor = new IssueRemoveStaleProcessor(this);

return issueRemoveStaleProcessor.removeStale();
if (await issueRemoveStaleProcessor.shouldRemoveStale()) {
await issueRemoveStaleProcessor.removeStale();

return Promise.resolve(true);
}

return Promise.resolve(false);
}
}
Loading

0 comments on commit b66d9b3

Please sign in to comment.