Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(logs): add a new log when an issue consumed at least one operation #386

Merged
merged 41 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c21e2f2
Merge pull request #1 from actions/main
C0ZEN Nov 22, 2020
c913fa4
Merge pull request #2 from actions/main
C0ZEN Jan 16, 2021
9cf9bf2
Merge pull request #3 from actions/main
C0ZEN Jan 16, 2021
f11f623
Merge pull request #4 from actions/main
C0ZEN Jan 16, 2021
0f1457a
Merge pull request #5 from actions/main
C0ZEN Jan 17, 2021
fef6333
Merge pull request #6 from actions/main
C0ZEN Jan 18, 2021
e1ba62c
Merge pull request #7 from actions/main
C0ZEN Jan 23, 2021
abab4a6
Merge pull request #8 from actions/main
C0ZEN Feb 9, 2021
920683c
Merge pull request #9 from actions/main
C0ZEN Feb 13, 2021
a98474b
Merge pull request #10 from actions/main
C0ZEN Feb 18, 2021
915ed27
Merge pull request #11 from actions/main
C0ZEN Mar 1, 2021
4b097b3
Merge pull request #12 from actions/main
C0ZEN Mar 1, 2021
5575ade
docs(only-labels): enhance the docs and fix duplicate (#341)
C0ZEN Mar 4, 2021
b806328
build(deps-dev): bump @typescript-eslint/eslint-plugin (#342)
dependabot[bot] Mar 4, 2021
c6b2c30
build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350)
dependabot[bot] Mar 4, 2021
5a8ec1e
Merge pull request #14 from actions/main
C0ZEN Mar 4, 2021
6c29691
test: add more coverage for the stale label behaviour (#352) (#15)
C0ZEN Mar 5, 2021
d485d43
test: add more coverage for the stale label behaviour (#352) (#17)
C0ZEN Mar 9, 2021
25621f6
test: add more coverage for the stale label behaviour (#352) (#18)
C0ZEN Mar 9, 2021
6257990
docs(operations-per-run): improve the doc for this option
C0ZEN Mar 10, 2021
c38af01
feat(logs): add a new log when an issue consumed at least one operation
C0ZEN Mar 10, 2021
173c540
Merge branch 'main' into feature/log-operations-per-issue
C0ZEN Mar 10, 2021
d0d072d
chore(readme): improve the operations per run
C0ZEN Mar 17, 2021
6d7053e
chore(readme): improve the operations per run
C0ZEN Mar 17, 2021
4236350
chore(readme): improve the operations per run
C0ZEN Mar 17, 2021
e7b8a38
chore(readme): improve the operations per run
C0ZEN Mar 17, 2021
304e352
chore(readme): improve the operations per run
C0ZEN Mar 17, 2021
c78dbd5
chore(readme): improve the operations per run
C0ZEN Mar 19, 2021
9a29082
Merge branch 'main' into feature/log-operations-per-issue
C0ZEN Apr 27, 2021
ee8f729
Typo in how to perform check for specific labels (#357)
romainr Apr 28, 2021
94499a2
feat(any-of-labels): add 2 new options to customize for issues/PRs (#…
C0ZEN Apr 28, 2021
8d43c50
feat(logs): enhance the logs for assignees and milestones (#382)
C0ZEN Apr 28, 2021
8025ac6
Merge branch 'main' into feature/log-operations-per-issue
C0ZEN Apr 28, 2021
72abf2b
Merge branch 'main' into feature/log-operations-per-issue
C0ZEN Apr 28, 2021
2570e86
style(typo): fix typo plural issue
C0ZEN Apr 28, 2021
ee986e5
Merge branch 'main' into feature/log-operations-per-issue
C0ZEN Apr 30, 2021
385b1d6
style(naming): rename two methods
C0ZEN Apr 30, 2021
783c103
chore(error): remove a potential useless throw of error
C0ZEN Apr 30, 2021
7fae5fa
style(naming): rename one method
C0ZEN Apr 30, 2021
4cf12ba
refactor(issue): change the way to count the operations
C0ZEN Apr 30, 2021
96bee75
refactor(operations): create a method to reduce code duplication
C0ZEN May 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 59 additions & 46 deletions README.md

Large diffs are not rendered by default.

89 changes: 71 additions & 18 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Issue = void 0;
const is_labeled_1 = __nccwpck_require__(6792);
const is_pull_request_1 = __nccwpck_require__(5400);
class Issue {
const operations_1 = __nccwpck_require__(7957);
class Issue extends operations_1.Operations {
constructor(options, issue) {
super();
this._options = options;
this.title = issue.title;
this.number = issue.number;
Expand Down Expand Up @@ -239,7 +241,7 @@ const issue_1 = __nccwpck_require__(4783);
const issue_logger_1 = __nccwpck_require__(2984);
const logger_1 = __nccwpck_require__(6212);
const milestones_1 = __nccwpck_require__(4601);
const operations_1 = __nccwpck_require__(7957);
const stale_operations_1 = __nccwpck_require__(5080);
const statistics_1 = __nccwpck_require__(3334);
/***
* Handle processing of issues for staleness/closure.
Expand All @@ -253,7 +255,7 @@ class IssuesProcessor {
this.removedLabelIssues = [];
this.options = options;
this.client = github_1.getOctokit(this.options.repoToken);
this._operations = new operations_1.Operations(this.options);
this._operations = new stale_operations_1.StaleOperations(this.options);
this._logger.info(chalk_1.default.yellow('Starting the stale action process...'));
if (this.options.debugOnly) {
this._logger.warning(chalk_1.default.yellowBright('Executing in debug mode!'));
Expand All @@ -268,6 +270,13 @@ class IssuesProcessor {
const millisSinceLastUpdated = new Date().getTime() - new Date(timestamp).getTime();
return millisSinceLastUpdated <= daysInMillis;
}
static _endIssueProcessing(issue) {
const consumedOperationsCount = issue.getConsumedOperationsCount();
if (consumedOperationsCount > 0) {
const issueLogger = new issue_logger_1.IssueLogger(issue);
issueLogger.info(chalk_1.default.cyan(consumedOperationsCount), `operation${consumedOperationsCount > 1 ? '' : ''} consumed for this $$type`);
}
}
processIssues(page = 1) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
Expand All @@ -276,7 +285,7 @@ class IssuesProcessor {
const actor = yield this.getActor();
if (issues.length <= 0) {
this._logger.info(chalk_1.default.green('No more issues found to process. Exiting...'));
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.setOperationsLeft(this._operations.getUnconsumedOperationsCount()).logStats();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.setOperationsLeft(this._operations.getOperationsLeftCount()).logStats();
return this._operations.getOperationsLeftCount();
}
else {
Expand Down Expand Up @@ -313,6 +322,7 @@ class IssuesProcessor {
});
if (!hasAllWhitelistedLabels) {
issueLogger.info(`Skipping this $$type because it doesn't have all the required labels`);
IssuesProcessor._endIssueProcessing(issue);
continue; // Don't process issues without all of the required labels
}
else {
Expand All @@ -326,14 +336,17 @@ class IssuesProcessor {
const shouldMarkAsStale = should_mark_when_stale_1.shouldMarkWhenStale(daysBeforeStale);
if (!staleMessage && shouldMarkAsStale) {
issueLogger.info(`Skipping $$type due to empty stale message`);
IssuesProcessor._endIssueProcessing(issue);
continue;
}
if (issue.state === 'closed') {
issueLogger.info(`Skipping $$type because it is closed`);
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process closed issues
}
if (issue.locked) {
issueLogger.info(`Skipping $$type because it is locked`);
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process locked issues
}
// Try to remove the close label when not close/locked issue or PR
Expand All @@ -345,11 +358,15 @@ class IssuesProcessor {
// Expecting that GitHub will always set a creation date on the issues and PRs
// But you never know!
if (!is_valid_date_1.isValidDate(createdAt)) {
core.setFailed(new Error(`Invalid issue field: "created_at". Expected a valid date`));
IssuesProcessor._endIssueProcessing(issue);
const errorMessage = `Invalid issue field: "created_at". Expected a valid date`;
core.setFailed(new Error(errorMessage));
throw new Error(errorMessage);
}
issueLogger.info(`$$type created the ${get_humanized_date_1.getHumanizedDate(createdAt)} (${issue.created_at})`);
if (!is_date_more_recent_than_1.isDateMoreRecentThan(createdAt, startDate)) {
issueLogger.info(`Skipping $$type because it was created before the specified start date`);
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process issues which were created before the start date
}
}
Expand All @@ -368,20 +385,24 @@ class IssuesProcessor {
yield this._removeStaleLabel(issue, staleLabel);
}
issueLogger.info(`Skipping $$type because it has an exempt label`);
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process exempt issues
}
const anyOfLabels = words_to_list_1.wordsToList(this.options.anyOfLabels);
if (anyOfLabels.length &&
!anyOfLabels.some((label) => is_labeled_1.isLabeled(issue, label))) {
issueLogger.info(`Skipping $$type because it does not have any of the required labels`);
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process issues without any of the required labels
}
const milestones = new milestones_1.Milestones(this.options, issue);
if (milestones.shouldExemptMilestones()) {
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process exempt milestones
}
const assignees = new assignees_1.Assignees(this.options, issue);
if (assignees.shouldExemptAssignees()) {
IssuesProcessor._endIssueProcessing(issue);
continue; // don't process exempt assignees
}
// should this issue be marked stale?
Expand All @@ -400,8 +421,9 @@ class IssuesProcessor {
issueLogger.info(`Found a stale $$type`);
yield this._processStaleIssue(issue, staleLabel, actor, closeMessage, closeLabel);
}
IssuesProcessor._endIssueProcessing(issue);
}
if (this._operations.hasOperationsLeft()) {
if (!this._operations.hasOperationsLeft()) {
this._logger.warning(chalk_1.default.yellowBright('No more operations left! Exiting...'));
this._logger.warning(chalk_1.default.yellowBright(`If you think that not enough issues were processed you could try to increase the quantity related to the ${this._logger.createOptionLink(option_1.Option.OperationsPerRun)} option which is currently set to ${chalk_1.default.cyan(this.options.operationsPerRun)}`));
return 0;
Expand Down Expand Up @@ -480,6 +502,7 @@ class IssuesProcessor {
const issueLogger = new issue_logger_1.IssueLogger(issue);
issueLogger.info(`Checking for label on $$type`);
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedItemsEventsCount();
const options = this.client.issues.listEvents.endpoint.merge({
owner: github_1.context.repo.owner,
Expand Down Expand Up @@ -566,6 +589,7 @@ class IssuesProcessor {
if (!skipMessage) {
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedItemsComment(issue);
yield this.client.issues.createComment({
owner: github_1.context.repo.owner,
Expand All @@ -580,6 +604,7 @@ class IssuesProcessor {
}
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedItemsLabel(issue);
(_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementStaleItemsCount(issue);
yield this.client.issues.addLabels({
Expand Down Expand Up @@ -607,6 +632,7 @@ class IssuesProcessor {
if (closeMessage) {
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedItemsComment(issue);
yield this.client.issues.createComment({
owner: github_1.context.repo.owner,
Expand All @@ -622,6 +648,7 @@ class IssuesProcessor {
if (closeLabel) {
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedItemsLabel(issue);
yield this.client.issues.addLabels({
owner: github_1.context.repo.owner,
Expand All @@ -636,6 +663,7 @@ class IssuesProcessor {
}
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementClosedItemsCount(issue);
yield this.client.issues.update({
owner: github_1.context.repo.owner,
Expand All @@ -658,6 +686,7 @@ class IssuesProcessor {
}
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedPullRequestsCount();
const pullRequest = yield this.client.pulls.get({
owner: github_1.context.repo.owner,
Expand Down Expand Up @@ -689,6 +718,7 @@ class IssuesProcessor {
issueLogger.info(`Deleting branch ${branch} from closed $$type`);
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedBranchesCount();
yield this.client.git.deleteRef({
owner: github_1.context.repo.owner,
Expand All @@ -713,6 +743,7 @@ class IssuesProcessor {
}
try {
this._operations.consumeOperation();
issue.consumeOperation();
(_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedItemsLabelsCount(issue);
yield this.client.issues.removeLabel({
owner: github_1.context.repo.owner,
Expand Down Expand Up @@ -1070,28 +1101,46 @@ exports.Milestones = Milestones;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Operations = void 0;
class Operations {
constructor(options) {
this._options = options;
this._operationsLeft = this._options.operationsPerRun;
constructor() {
this._operationsConsumed = 0;
}
consumeOperation() {
return this.consumeOperations(1);
}
consumeOperations(quantity) {
this._operationsLeft -= quantity;
this._operationsConsumed += quantity;
return this;
}
getUnconsumedOperationsCount() {
return this._options.operationsPerRun - this._operationsLeft;
getConsumedOperationsCount() {
return this._operationsConsumed;
}
}
exports.Operations = Operations;


/***/ }),

/***/ 5080:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.StaleOperations = void 0;
const operations_1 = __nccwpck_require__(7957);
class StaleOperations extends operations_1.Operations {
constructor(options) {
super();
this._options = options;
}
hasOperationsLeft() {
return this._operationsLeft <= 0;
return this._operationsConsumed < this._options.operationsPerRun;
}
getOperationsLeftCount() {
return this._operationsLeft;
return this._options.operationsPerRun - this._operationsConsumed;
}
}
exports.Operations = Operations;
exports.StaleOperations = StaleOperations;


/***/ }),
Expand Down Expand Up @@ -1721,8 +1770,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const core = __importStar(__nccwpck_require__(2186));
const is_valid_date_1 = __nccwpck_require__(891);
const issues_processor_1 = __nccwpck_require__(3292);
const is_valid_date_1 = __nccwpck_require__(891);
function _run() {
return __awaiter(this, void 0, void 0, function* () {
try {
Expand Down Expand Up @@ -1788,14 +1837,18 @@ function _getAndValidateArgs() {
'operations-per-run'
]) {
if (isNaN(parseInt(core.getInput(numberInput)))) {
core.setFailed(new Error(`Option "${numberInput}" did not parse to a valid integer`));
const errorMessage = `Option "${numberInput}" did not parse to a valid integer`;
core.setFailed(errorMessage);
throw new Error(errorMessage);
}
}
for (const optionalDateInput of ['start-date']) {
// Ignore empty dates because it is considered as the right type for a default value (so a valid one)
if (core.getInput(optionalDateInput) !== '') {
if (!is_valid_date_1.isValidDate(new Date(core.getInput(optionalDateInput)))) {
core.setFailed(new Error(`Option "${optionalDateInput}" did not parse to a valid date`));
const errorMessage = `Option "${optionalDateInput}" did not parse to a valid date`;
core.setFailed(errorMessage);
throw new Error(errorMessage);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ module.exports = {
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
verbose: true,
setupFilesAfterEnv: [`./jest/test.ts`]
};
11 changes: 11 additions & 0 deletions jest/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import chalk from 'chalk';

// Disabled the colors to:
// - improve the performances
// - avoid to mock chalk
// - avoid to have failing tests when testing the logs due to the extra text the log message will contains
//
// Note:
// If you need to debug the log colours you can remove this line temporarily
// But some tests will fail
chalk.level = 0;
28 changes: 15 additions & 13 deletions src/classes/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {IIssuesProcessorOptions} from '../interfaces/issues-processor-options';
import {ILabel} from '../interfaces/label';
import {IMilestone} from '../interfaces/milestone';
import {IsoDateString} from '../types/iso-date-string';
import {Operations} from './operations';

export class Issue implements IIssue {
export class Issue extends Operations implements IIssue {
private readonly _options: IIssuesProcessorOptions;
readonly title: string;
readonly number: number;
Expand All @@ -21,10 +22,23 @@ export class Issue implements IIssue {
readonly assignees: IAssignee[];
isStale: boolean;

get isPullRequest(): boolean {
return isPullRequest(this);
}

get staleLabel(): string {
return this._getStaleLabel();
}

get hasAssignees(): boolean {
return this.assignees.length > 0;
}

constructor(
options: Readonly<IIssuesProcessorOptions>,
issue: Readonly<IIssue>
) {
super();
this._options = options;
this.title = issue.title;
this.number = issue.number;
Expand All @@ -40,18 +54,6 @@ export class Issue implements IIssue {
this.isStale = isLabeled(this, this.staleLabel);
}

get isPullRequest(): boolean {
return isPullRequest(this);
}

get staleLabel(): string {
return this._getStaleLabel();
}

get hasAssignees(): boolean {
return this.assignees.length > 0;
}

private _getStaleLabel(): string {
return this.isPullRequest
? this._options.stalePrLabel
Expand Down