From 5575ade590242005a11a066fead65f3d19d13fc7 Mon Sep 17 00:00:00 2001 From: Geoffrey Testelin Date: Thu, 4 Mar 2021 12:38:05 +0100 Subject: [PATCH 01/15] docs(only-labels): enhance the docs and fix duplicate (#341) * docs(only-labels): remove duplicated option and improve descriptions a bad rebase happend * docs(readme): use a multi-line array and remove the optional column the option column was not helpful since each value is optional the multi-line array will allow to have a better UI in small devices and basically in GitHub too due to the max-width * style(readme): break line for the statistics * docs(readme): add a better description for the ascending option * docs(action): add missing punctuation --- README.md | 93 +++++++++++++++++++++++++++--------------------------- action.yml | 10 +++--- 2 files changed, 52 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index fc9d55eb0..3709c6abb 100644 --- a/README.md +++ b/README.md @@ -4,51 +4,52 @@ Warns and then closes issues and PRs that have had no activity for a specified a ### Arguments -| Input | Description | Usage | -| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -------- | -| `repo-token` | PAT(Personal Access Token) for authorizing repository. _Defaults to **${{ github.token }}**_ | Optional | -| `days-before-stale` | Idle number of days before marking an issue/PR as stale. _Defaults to **60**_ | Optional | -| `days-before-issue-stale` | Idle number of days before marking an issue as stale (override `days-before-stale`). | Optional | -| `days-before-pr-stale` | Idle number of days before marking an PR as stale (override `days-before-stale`). | Optional | -| `days-before-close` | Idle number of days before closing an stale issue/PR. _Defaults to **7**_ | Optional | -| `days-before-issue-close` | Idle number of days before closing an stale issue (override `days-before-close`). | Optional | -| `days-before-pr-close` | Idle number of days before closing an stale PR (override `days-before-close`). | Optional | -| `stale-issue-message` | Message to post on the stale issue. | Optional | -| `stale-pr-message` | Message to post on the stale PR. | Optional | -| `close-issue-message` | Message to post on the stale issue while closing it. | Optional | -| `close-pr-message` | Message to post on the stale PR while closing it. | Optional | -| `stale-issue-label` | Label to apply on the stale issue. _Defaults to **Stale**_ | Optional | -| `close-issue-label` | Label to apply on closing issue (automatically removed if no longer closed nor locked). | Optional | -| `stale-pr-label` | Label to apply on the stale PR. _Defaults to **Stale**_ | Optional | -| `close-pr-label` | Label to apply on the closing PR (automatically removed if no longer closed nor locked). | Optional | -| `exempt-issue-labels` | Labels on an issue exempted from being marked as stale. | Optional | -| `exempt-pr-labels` | Labels on the PR exempted from being marked as stale. | Optional | -| `only-labels` | Only issues and PRs with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered"). | Optional | -| `only-labels` | Only labels checked for stale issue/PR. | Optional | -| `only-issue-labels` | Only labels checked for stale issue (override `only-labels`). | Optional | -| `only-pr-labels` | Only labels checked for stale PR (override `only-labels`). | Optional | -| `any-of-labels` | Only issues and PRs with ANY of these labels are checked. Separate multiple labels with commas (eg. "incomplete,waiting-feedback"). | Optional | -| `operations-per-run` | Maximum number of operations per run (GitHub API CRUD related). _Defaults to **30**_ | Optional | -| `remove-stale-when-updated` | Remove stale label from issue/PR on updates or comments. _Defaults to **true**_ | Optional | -| `debug-only` | Dry-run on action. _Defaults to **false**_ | Optional | -| `ascending` | Order to get issues/PR. _Defaults to **false**_ | Optional | -| `skip-stale-issue-message` | Skip adding stale message on stale issue. _Defaults to **false**_ | Optional | -| `skip-stale-pr-message` | Skip adding stale message on stale PR. _Defaults to **false**_ | Optional | -| `start-date` | The date used to skip the stale action on issue/PR created before it (ISO 8601 or RFC 2822). | Optional | -| `delete-branch` | Delete the git branch after closing a stale pull request. _Defaults to **false**_ | Optional | -| `exempt-milestones` | Milestones on an issue or a PR exempted from being marked as stale. | Optional | -| `exempt-issue-milestones` | Milestones on an issue exempted from being marked as stale (override `exempt-milestones`). | Optional | -| `exempt-pr-milestones` | Milestones on the PR exempted from being marked as stale (override `exempt-milestones`). | Optional | -| `exempt-all-milestones` | Exempt all issues and PRs with milestones from being marked as stale. (priority over `exempt-milestones` rules) | Optional | -| `exempt-all-issue-milestones` | Exempt all issues with milestones from being marked as stale. (override `exempt-all-milestones`). | Optional | -| `exempt-all-pr-milestones` | Exempt all PRs with milestones from being marked as stale. (override `exempt-all-milestones`). | Optional | -| `exempt-assignees` | Assignees on an issue or a PR exempted from being marked as stale. | Optional | -| `exempt-issue-assignees` | Assignees on an issue exempted from being marked as stale (override `exempt-assignees`). | Optional | -| `exempt-pr-assignees` | Assignees on the PR exempted from being marked as stale (override `exempt-assignees`). | Optional | -| `exempt-all-assignees` | Exempt all issues and PRs with assignees from being marked as stale. (priority over `exempt-assignees` rules) | Optional | -| `exempt-all-issue-assignees` | Exempt all issues with assignees from being marked as stale. (override `exempt-all-assignees`). | Optional | -| `exempt-all-pr-assignees` | Exempt all PRs with assignees from being marked as stale. (override `exempt-all-assignees`). | Optional | -| `enable-statistics` | Display some statistics at the end of the logs regarding the stale workflow (only when the logs are enabled). _Defaults to **true**_ | Optional | +Every argument is optional. + +| Input | Description | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `repo-token` | PAT(Personal Access Token) for authorizing repository.
_Defaults to **${{ github.token }}**_. | +| `days-before-stale` | Idle number of days before marking an issue/PR as stale.
_Defaults to **60**_. | +| `days-before-issue-stale` | Idle number of days before marking an issue as stale.
_Override `days-before-stale`_. | +| `days-before-pr-stale` | Idle number of days before marking an PR as stale.
_Override `days-before-stale`_. | +| `days-before-close` | Idle number of days before closing an stale issue/PR.
_Defaults to **7**_. | +| `days-before-issue-close` | Idle number of days before closing an stale issue.
_Override `days-before-close`_. | +| `days-before-pr-close` | Idle number of days before closing an stale PR.
_Override `days-before-close`_. | +| `stale-issue-message` | Message to post on the stale issue. | +| `stale-pr-message` | Message to post on the stale PR. | +| `close-issue-message` | Message to post on the stale issue while closing it. | +| `close-pr-message` | Message to post on the stale PR while closing it. | +| `stale-issue-label` | Label to apply on the stale issue.
_Defaults to **Stale**_. | +| `close-issue-label` | Label to apply on closing issue (automatically removed if no longer closed nor locked). | +| `stale-pr-label` | Label to apply on the stale PR.
_Defaults to **Stale**_. | +| `close-pr-label` | Label to apply on the closing PR (automatically removed if no longer closed nor locked). | +| `exempt-issue-labels` | Labels on an issue exempted from being marked as stale. | +| `exempt-pr-labels` | Labels on the PR exempted from being marked as stale. | +| `only-labels` | Only issues and PRs with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered"). | +| `only-issue-labels` | Only issues with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | +| `only-pr-labels` | Only PRs with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | +| `any-of-labels` | Only issues and PRs with ANY of these labels are checked. Separate multiple labels with commas (eg. "incomplete,waiting-feedback"). | +| `operations-per-run` | Maximum number of operations per run (GitHub API CRUD related).
_Defaults to **30**_. | +| `remove-stale-when-updated` | Remove stale label from issue/PR on updates or comments.
_Defaults to **true**_. | +| `debug-only` | Dry-run on action.
_Defaults to **false**_. | +| `ascending` | Order to get issues/PR (true is ascending, false is descending).
_Defaults to **false**_. | +| `skip-stale-issue-message` | Skip adding stale message on stale issue.
_Defaults to **false**_. | +| `skip-stale-pr-message` | Skip adding stale message on stale PR.
_Defaults to **false**_. | +| `start-date` | The date used to skip the stale action on issue/PR created before it (ISO 8601 or RFC 2822). | +| `delete-branch` | Delete the git branch after closing a stale pull request.
_Defaults to **false**_. | +| `exempt-milestones` | Milestones on an issue or a PR exempted from being marked as stale. | +| `exempt-issue-milestones` | Milestones on an issue exempted from being marked as stale.
_Override `exempt-milestones`_. | +| `exempt-pr-milestones` | Milestones on the PR exempted from being marked as stale.
_Override `exempt-milestones`_. | +| `exempt-all-milestones` | Exempt all issues and PRs with milestones from being marked as stale.
_Priority over `exempt-milestones` rules_. | +| `exempt-all-issue-milestones` | Exempt all issues with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | +| `exempt-all-pr-milestones` | Exempt all PRs with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | +| `exempt-assignees` | Assignees on an issue or a PR exempted from being marked as stale. | +| `exempt-issue-assignees` | Assignees on an issue exempted from being marked as stale.
_Override `exempt-assignees`_. | +| `exempt-pr-assignees` | Assignees on the PR exempted from being marked as stale.
_Override `exempt-assignees`_. | +| `exempt-all-assignees` | Exempt all issues and PRs with assignees from being marked as stale.
_Priority over `exempt-assignees` rules_. | +| `exempt-all-issue-assignees` | Exempt all issues with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | +| `exempt-all-pr-assignees` | Exempt all PRs with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | +| `enable-statistics` | Display some statistics at the end of the logs regarding the stale workflow (only when the logs are enabled).
_Defaults to **true**_. | ### Usage @@ -274,7 +275,7 @@ jobs: To see the debug output from this action, you must set the secret `ACTIONS_STEP_DEBUG` to `true` in your repository. There is a lot of logs so this can be very helpful! -**Statistics:** +**Statistics:** If the logs are enabled, you can also enable the statistics log which will be visible at the end of the logs once all issues were processed. This is very helpful to have a quick understanding of the whole stale workflow. Set `enable-statistics` to `true` in your workflow configuration file. diff --git a/action.yml b/action.yml index 1bb6375cd..0b3f202ef 100644 --- a/action.yml +++ b/action.yml @@ -46,7 +46,7 @@ inputs: description: 'The label to apply when an issue is closed.' required: false exempt-issue-labels: - description: 'The labels that mean an issue is exempt from being marked stale. Separate multiple labels with commas (eg. "label1,label2")' + description: 'The labels that mean an issue is exempt from being marked stale. Separate multiple labels with commas (eg. "label1,label2").' default: '' required: false stale-pr-label: @@ -57,11 +57,11 @@ inputs: description: 'The label to apply when a pull request is closed.' required: false exempt-pr-labels: - description: 'The labels that mean a pull request is exempt from being marked as stale. Separate multiple labels with commas (eg. "label1,label2")' + description: 'The labels that mean a pull request is exempt from being marked as stale. Separate multiple labels with commas (eg. "label1,label2").' default: '' required: false exempt-milestones: - description: 'The milestones that mean an issue or a pull request is exempt from being marked as stale. Separate multiple milestones with commas (eg. "milestone1,milestone2")' + description: 'The milestones that mean an issue or a pull request is exempt from being marked as stale. Separate multiple milestones with commas (eg. "milestone1,milestone2").' default: '' required: false exempt-issue-milestones: @@ -113,7 +113,7 @@ inputs: default: 'false' required: false ascending: - description: 'The order to get issues or pull requests. Defaults to false, which is descending' + description: 'The order to get issues or pull requests. Defaults to false, which is descending.' default: 'false' required: false skip-stale-pr-message: @@ -133,7 +133,7 @@ inputs: default: '' required: false exempt-assignees: - description: 'The assignees which exempt an issue or a pull request from being marked as stale. Separate multiple assignees with commas (eg. "user1,user2")' + description: 'The assignees which exempt an issue or a pull request from being marked as stale. Separate multiple assignees with commas (eg. "user1,user2").' default: '' required: false exempt-issue-assignees: From b806328b6300b24eb4388a4b22763f725d8b927d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Mar 2021 06:38:32 -0500 Subject: [PATCH 02/15] build(deps-dev): bump @typescript-eslint/eslint-plugin (#342) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.16.1/packages/eslint-plugin) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 56 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 115b9800d..e71f28348 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1883,13 +1883,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", - "integrity": "sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz", + "integrity": "sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.15.2", - "@typescript-eslint/scope-manager": "4.15.2", + "@typescript-eslint/experimental-utils": "4.16.1", + "@typescript-eslint/scope-manager": "4.16.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -1899,43 +1899,43 @@ }, "dependencies": { "@typescript-eslint/experimental-utils": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz", - "integrity": "sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz", + "integrity": "sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", + "@typescript-eslint/scope-manager": "4.16.1", + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/typescript-estree": "4.16.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/scope-manager": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", - "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz", + "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2" + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/visitor-keys": "4.16.1" } }, "@typescript-eslint/types": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", - "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz", + "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", - "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz", + "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2", + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/visitor-keys": "4.16.1", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -1944,12 +1944,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", - "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz", + "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", + "@typescript-eslint/types": "4.16.1", "eslint-visitor-keys": "^2.0.0" } }, diff --git a/package.json b/package.json index 7ee29ea4e..105513d80 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/lodash.deburr": "^4.1.6", "@types/node": "^14.14.31", "@types/semver": "^7.3.4", - "@typescript-eslint/eslint-plugin": "^4.15.2", + "@typescript-eslint/eslint-plugin": "^4.16.1", "@typescript-eslint/parser": "^4.15.2", "@vercel/ncc": "^0.27.0", "eslint": "^7.21.0", From c6b2c30dc4507d151f0bc120b69a0ba21158e117 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Mar 2021 06:38:50 -0500 Subject: [PATCH 03/15] build(deps): bump @octokit/rest from 18.3.0 to 18.3.2 (#350) Bumps [@octokit/rest](https://github.com/octokit/rest.js) from 18.3.0 to 18.3.2. - [Release notes](https://github.com/octokit/rest.js/releases) - [Commits](https://github.com/octokit/rest.js/compare/v18.3.0...v18.3.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index e71f28348..0696b8e8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1561,9 +1561,9 @@ } }, "@octokit/openapi-types": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.2.0.tgz", - "integrity": "sha512-MInMij2VK5o96Ei6qaHjxBglSZWOXQs9dTZfnGX2Xnr2mhA+yk9L/QCH4RcJGISJJCBclLHuY3ytq+iRgDfX7w==" + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.2.2.tgz", + "integrity": "sha512-b3nHy/0uufJJsaZERwZM0syLRO6gfr6vvBPLewQxBKzzbhGDx1ygTyoELMNADD7mIPPzGMqbfdCeJTSeZueZwA==" }, "@octokit/plugin-paginate-rest": { "version": "2.2.4", @@ -1613,14 +1613,14 @@ } }, "@octokit/rest": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.0.tgz", - "integrity": "sha512-R45oBVhnq3HAOGVtC6lHY7LX7TGWqbbcD4KvBHoT4QIjgJzfqKag3m/DUJwLnp8xrokz1spZmspTIXiDeQqJSA==", + "version": "18.3.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.2.tgz", + "integrity": "sha512-TSTI47/jLqdq8qvc/a/P/VApBal7QHeISPZ8a1v7ma8NN/YdU5HRTSCb15+IvzUeuM7Iagp0aG+ypvQXJgmgQw==", "requires": { "@octokit/core": "^3.2.3", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "4.13.0" + "@octokit/plugin-rest-endpoint-methods": "4.13.2" }, "dependencies": { "@octokit/auth-token": { @@ -1663,11 +1663,11 @@ } }, "@octokit/plugin-rest-endpoint-methods": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.0.tgz", - "integrity": "sha512-Ofusy7BwHkU7z4TNsVdf7wm5W3KR625KqlQj4AiWPnBvclmZU0Y2bVK8b8Mz8nW7sEX9TJcCdX6KeaincE/cLw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.2.tgz", + "integrity": "sha512-pnn0lGE05nqZ+EZuZgJBffJ4QRAlrlvg3LBFjCKHqUUWCI3PMqZ8kPJOxFj0R3B3D5hoGambtEIpCnaRD6nRJw==", "requires": { - "@octokit/types": "^6.11.0", + "@octokit/types": "^6.11.2", "deprecation": "^2.3.1" } }, @@ -1687,11 +1687,11 @@ } }, "@octokit/types": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.11.0.tgz", - "integrity": "sha512-RMLAmpPZf/a33EsclBazKg02NCCj4rC69V9sUgf0SuWTjmnBD2QC1nIVtJo7RJrGnwG1+aoFBb2yTrWm/8AS7w==", + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.11.2.tgz", + "integrity": "sha512-EKQRFZU/oOfUlqk9ntLIE5UO/bcOx8exFpdXGBciJP90f05me3mza0sacIpqVqmiIQP3nJsBjnZHMmtijE5XwQ==", "requires": { - "@octokit/openapi-types": "^5.2.0" + "@octokit/openapi-types": "^5.2.2" } }, "is-plain-object": { diff --git a/package.json b/package.json index 105513d80..e76646bc4 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "dependencies": { "@actions/core": "^1.2.6", "@actions/github": "^4.0.0", - "@octokit/rest": "^18.3.0", + "@octokit/rest": "^18.3.2", "lodash.deburr": "^4.1.0", "semver": "^7.3.4" }, From 6c29691325334e43f69da5b6274acc006a74fb38 Mon Sep 17 00:00:00 2001 From: Geoffrey Testelin Date: Fri, 5 Mar 2021 21:08:47 +0100 Subject: [PATCH 04/15] test: add more coverage for the stale label behaviour (#352) (#15) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- __tests__/main.spec.ts | 90 +++++++++- package-lock.json | 366 ++++++++++++++++++++++++----------------- package.json | 10 +- src/interfaces/user.ts | 2 +- 4 files changed, 309 insertions(+), 159 deletions(-) diff --git a/__tests__/main.spec.ts b/__tests__/main.spec.ts index b6efe3bc8..1fe15800b 100644 --- a/__tests__/main.spec.ts +++ b/__tests__/main.spec.ts @@ -1,5 +1,6 @@ import * as github from '@actions/github'; import {Issue} from '../src/classes/issue'; +import {IComment} from '../src/interfaces/comment'; import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options'; import {IssuesProcessorMock} from './classes/issues-processor-mock'; import {DefaultProcessorOptions} from './constants/default-processor-options'; @@ -2105,7 +2106,7 @@ test('processing a previously closed issue with a close label will remove the cl staleIssueLabel: 'stale' }; const now: Date = new Date(); - const oneWeekAgo: Date = new Date(now.getDate() - 7); + const oneWeekAgo: Date = new Date(now.setDate(now.getDate() - 7)); const TestIssueList: Issue[] = [ generateIssue( opts, @@ -2141,7 +2142,7 @@ test('processing a closed issue with a close label will not remove the close lab staleIssueLabel: 'stale' }; const now: Date = new Date(); - const oneWeekAgo: Date = new Date(now.getDate() - 7); + const oneWeekAgo: Date = new Date(now.setDate(now.getDate() - 7)); const TestIssueList: Issue[] = [ generateIssue( opts, @@ -2177,7 +2178,7 @@ test('processing a locked issue with a close label will not remove the close lab staleIssueLabel: 'stale' }; const now: Date = new Date(); - const oneWeekAgo: Date = new Date(now.getDate() - 7); + const oneWeekAgo: Date = new Date(now.setDate(now.getDate() - 7)); const TestIssueList: Issue[] = [ generateIssue( opts, @@ -2204,3 +2205,86 @@ test('processing a locked issue with a close label will not remove the close lab expect(processor.removedLabelIssues).toHaveLength(0); }); + +test('processing an issue stale since less than the daysBeforeStale with a stale label created after daysBeforeClose should close the issue', async () => { + expect.assertions(3); + const opts: IIssuesProcessorOptions = { + ...DefaultProcessorOptions, + staleIssueLabel: 'stale-label', + daysBeforeStale: 30, + daysBeforeClose: 7, + closeIssueMessage: 'close message', + removeStaleWhenUpdated: false + }; + const now: Date = new Date(); + const updatedAt: Date = new Date(now.setDate(now.getDate() - 9)); + const labelCreatedAt: Date = new Date(now.setDate(now.getDate() - 17)); + const TestIssueList: Issue[] = [ + generateIssue( + opts, + 1, + 'A real issue example; see https://github.com/actions/stale/issues/351', + updatedAt.toDateString(), + new Date(2021, 0, 16).toDateString(), + false, + ['stale-label'], // This was the problem for the user BTW, the issue was re-opened without removing the previous stale label + false, + false + ) + ]; + const processor = new IssuesProcessorMock( + opts, + async () => 'abot', + async p => (p === 1 ? TestIssueList : []), + async (): Promise => Promise.resolve([]), + async () => labelCreatedAt.toDateString() + ); + + // process our fake issue list + await processor.processIssues(1); + + expect(processor.removedLabelIssues).toHaveLength(0); + expect(processor.deletedBranchIssues).toHaveLength(0); + expect(processor.closedIssues).toHaveLength(1); // Expected at 0 by the user +}); + +test('processing an issue stale since less than the daysBeforeStale without a stale label should close the issue', async () => { + expect.assertions(3); + const opts: IIssuesProcessorOptions = { + ...DefaultProcessorOptions, + staleIssueLabel: 'stale-label', + daysBeforeStale: 30, + daysBeforeClose: 7, + closeIssueMessage: 'close message', + removeStaleWhenUpdated: false + }; + const now: Date = new Date(); + const updatedAt: Date = new Date(now.setDate(now.getDate() - 9)); + const TestIssueList: Issue[] = [ + generateIssue( + opts, + 1, + 'A real issue example; see https://github.com/actions/stale/issues/351 but without the old stale label from the previous close', + updatedAt.toDateString(), + new Date(2021, 0, 16).toDateString(), + false, + [], + false, + false + ) + ]; + const processor = new IssuesProcessorMock( + opts, + async () => 'abot', + async p => (p === 1 ? TestIssueList : []), + async (): Promise => Promise.resolve([]), + async () => new Date().toDateString() + ); + + // process our fake issue list + await processor.processIssues(1); + + expect(processor.removedLabelIssues).toHaveLength(0); + expect(processor.deletedBranchIssues).toHaveLength(0); + expect(processor.closedIssues).toHaveLength(0); +}); diff --git a/package-lock.json b/package-lock.json index 0696b8e8e..f55af56f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1561,9 +1561,9 @@ } }, "@octokit/openapi-types": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.2.2.tgz", - "integrity": "sha512-b3nHy/0uufJJsaZERwZM0syLRO6gfr6vvBPLewQxBKzzbhGDx1ygTyoELMNADD7mIPPzGMqbfdCeJTSeZueZwA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.0.tgz", + "integrity": "sha512-5q2qBz4iZ0xS/DEJ0ROusFbN4cVlbJE9GvOByen+mv7artuGXfVhONqcuRd7jYN2glTmCnzcZw+X6LrjRVqs0A==" }, "@octokit/plugin-paginate-rest": { "version": "2.2.4", @@ -1613,14 +1613,14 @@ } }, "@octokit/rest": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.2.tgz", - "integrity": "sha512-TSTI47/jLqdq8qvc/a/P/VApBal7QHeISPZ8a1v7ma8NN/YdU5HRTSCb15+IvzUeuM7Iagp0aG+ypvQXJgmgQw==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.3.tgz", + "integrity": "sha512-OxElwBanZn1AShCaIrRTLM9PwhGE5/busMke/go30OWAQ+eJMD7Us/67mtapE77EYY4FM2tvb4Eg25rZaA/NPA==", "requires": { "@octokit/core": "^3.2.3", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "4.13.2" + "@octokit/plugin-rest-endpoint-methods": "4.13.3" }, "dependencies": { "@octokit/auth-token": { @@ -1663,11 +1663,11 @@ } }, "@octokit/plugin-rest-endpoint-methods": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.2.tgz", - "integrity": "sha512-pnn0lGE05nqZ+EZuZgJBffJ4QRAlrlvg3LBFjCKHqUUWCI3PMqZ8kPJOxFj0R3B3D5hoGambtEIpCnaRD6nRJw==", + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.3.tgz", + "integrity": "sha512-nMGS2osFcWXRfHkDR0d+lB1zpMPTZJ0NjysPUfs7BT5/juNG/Q0+5UB6nC1f62jPzun154qekzwOb7Q5oahCXQ==", "requires": { - "@octokit/types": "^6.11.2", + "@octokit/types": "^6.12.0", "deprecation": "^2.3.1" } }, @@ -1687,11 +1687,11 @@ } }, "@octokit/types": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.11.2.tgz", - "integrity": "sha512-EKQRFZU/oOfUlqk9ntLIE5UO/bcOx8exFpdXGBciJP90f05me3mza0sacIpqVqmiIQP3nJsBjnZHMmtijE5XwQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.12.0.tgz", + "integrity": "sha512-KwOf16soD7aDEEi/PgNeJlHzjZPfrmmNy+7WezSdrpnqZ7YImBJcNnX9+5RUHt1MnA4h8oISRHTqaZDGsX9DRQ==", "requires": { - "@octokit/openapi-types": "^5.2.2" + "@octokit/openapi-types": "^5.3.0" } }, "is-plain-object": { @@ -1976,41 +1976,41 @@ } }, "@typescript-eslint/parser": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.2.tgz", - "integrity": "sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.16.1.tgz", + "integrity": "sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", + "@typescript-eslint/scope-manager": "4.16.1", + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/typescript-estree": "4.16.1", "debug": "^4.1.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", - "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz", + "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2" + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/visitor-keys": "4.16.1" } }, "@typescript-eslint/types": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", - "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz", + "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", - "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz", + "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2", + "@typescript-eslint/types": "4.16.1", + "@typescript-eslint/visitor-keys": "4.16.1", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -2019,12 +2019,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", - "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz", + "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", + "@typescript-eslint/types": "4.16.1", "eslint-visitor-keys": "^2.0.0" } }, @@ -2210,13 +2210,15 @@ "dev": true }, "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, @@ -2233,13 +2235,14 @@ "dev": true }, "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", "dev": true, "requires": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.1" } }, "asn1": { @@ -2602,6 +2605,16 @@ } } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3058,22 +3071,27 @@ } }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" } }, "es-to-primitive": { @@ -3417,13 +3435,10 @@ } }, "eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", + "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.4", @@ -3498,14 +3513,14 @@ } }, "eslint-plugin-github": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.1.1.tgz", - "integrity": "sha512-MzCh4P4zVvR/13AHtumzZ3znq0cbUE7lXehyBEpFURD/EHdx/+7qW+0c+ySTrteImpX9LGLJFTYNtu10BifkbQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.1.2.tgz", + "integrity": "sha512-ng738ugjNNF0BY4HQ9qo51xxQZZYtdYC//dhis+j8FL9BEsQ6x5BPmMbaKNP7PZ9wBUBTA7U8p4xFxUJlMi/PA==", "dev": true, "requires": { "@typescript-eslint/eslint-plugin": ">=2.25.0", "@typescript-eslint/parser": ">=2.25.0", - "eslint-config-prettier": ">=6.10.1", + "eslint-config-prettier": ">=8.0.0", "eslint-plugin-eslint-comments": ">=3.0.1", "eslint-plugin-import": ">=2.20.1", "eslint-plugin-prettier": ">=3.1.2", @@ -3515,9 +3530,9 @@ } }, "eslint-plugin-import": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", - "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", "dev": true, "requires": { "array-includes": "^3.1.1", @@ -3525,7 +3540,7 @@ "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.3", + "eslint-import-resolver-node": "^0.3.4", "eslint-module-utils": "^2.6.0", "has": "^1.0.3", "minimatch": "^3.0.4", @@ -3554,6 +3569,15 @@ "isarray": "^1.0.0" } }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3571,11 +3595,12 @@ } }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } } @@ -3591,9 +3616,9 @@ } }, "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -4150,18 +4175,23 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -4244,9 +4274,9 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "growly": { @@ -4281,6 +4311,12 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4288,9 +4324,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "has-value": { @@ -4520,6 +4556,21 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -4527,9 +4578,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-ci": { @@ -4635,6 +4686,12 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -4655,6 +4712,12 @@ } } }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-plain-object": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-4.1.1.tgz", @@ -4667,12 +4730,13 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { - "has": "^1.0.3" + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" } }, "is-stream": { @@ -8097,9 +8161,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", "dev": true }, "object-keys": { @@ -8126,15 +8190,15 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.pick": { @@ -8155,14 +8219,14 @@ } }, "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, @@ -9229,45 +9293,23 @@ } }, "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" - } - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { @@ -9496,12 +9538,11 @@ } }, "ts-jest": { - "version": "26.5.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.2.tgz", - "integrity": "sha512-bwyJ2zJieSugf7RB+o8fgkMeoMVMM2KPDE0UklRLuACxjwJsOrZNo6chrcScmK33YavPSwhARffy8dZx5LJdUQ==", + "version": "26.5.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.3.tgz", + "integrity": "sha512-nBiiFGNvtujdLryU7MiMQh1iPmnZ/QvOskBbD2kURiI1MwqvxlxNnaAB/z9TbslMqCsSbu5BXvSSQPc5tvHGeA==", "dev": true, "requires": { - "@types/jest": "26.x", "bs-logger": "0.x", "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", @@ -9611,11 +9652,23 @@ } }, "typescript": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.2.tgz", - "integrity": "sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", "dev": true }, + "unbox-primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", + "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.0", + "has-symbols": "^1.0.0", + "which-boxed-primitive": "^1.0.1" + } + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -9820,6 +9873,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", diff --git a/package.json b/package.json index e76646bc4..445b7615d 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "dependencies": { "@actions/core": "^1.2.6", "@actions/github": "^4.0.0", - "@octokit/rest": "^18.3.2", + "@octokit/rest": "^18.3.3", "lodash.deburr": "^4.1.0", "semver": "^7.3.4" }, @@ -42,17 +42,17 @@ "@types/node": "^14.14.31", "@types/semver": "^7.3.4", "@typescript-eslint/eslint-plugin": "^4.16.1", - "@typescript-eslint/parser": "^4.15.2", + "@typescript-eslint/parser": "^4.16.1", "@vercel/ncc": "^0.27.0", "eslint": "^7.21.0", - "eslint-plugin-github": "^4.0.1", + "eslint-plugin-github": "^4.1.2", "eslint-plugin-jest": "^24.1.5", "jest": "^26.6.3", "jest-circus": "^26.6.3", "jest-silent-reporter": "^0.4.0", "js-yaml": "^4.0.0", "prettier": "^2.2.1", - "ts-jest": "^26.5.2", - "typescript": "^4.2.2" + "ts-jest": "^26.5.3", + "typescript": "^4.2.3" } } diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index 2394d4d0c..4e454f6d2 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -1,4 +1,4 @@ export interface IUser { - type: string; + type: string | 'User'; login: string; } From d485d43a7b34b04ef32cf9253a8c82d2e634bab0 Mon Sep 17 00:00:00 2001 From: Geoffrey Testelin Date: Tue, 9 Mar 2021 19:36:05 +0100 Subject: [PATCH 05/15] test: add more coverage for the stale label behaviour (#352) (#17) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- README.md | 104 +- .../constants/default-processor-options.ts | 2 +- dist/index.js | 2919 ++++++++++++++++- package-lock.json | 65 +- package.json | 4 +- src/classes/assignees.ts | 4 +- src/classes/issues-processor.ts | 99 +- src/classes/loggers/issue-logger.ts | 37 +- src/classes/loggers/logger.ts | 25 +- src/classes/milestones.ts | 200 +- src/classes/operations.ts | 33 + src/classes/statistics.ts | 14 +- src/enums/option.ts | 44 + src/main.ts | 13 +- 15 files changed, 3276 insertions(+), 289 deletions(-) create mode 100644 src/classes/operations.ts create mode 100644 src/enums/option.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 699ef3c7d..fcd39da73 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v2 - run: | - npm install + npm ci npm run all test: # make sure the action works on a clean machine without building runs-on: ubuntu-latest diff --git a/README.md b/README.md index 3709c6abb..8409b591d 100644 --- a/README.md +++ b/README.md @@ -2,54 +2,68 @@ Warns and then closes issues and PRs that have had no activity for a specified amount of time. -### Arguments +## All options + +### List of options Every argument is optional. -| Input | Description | -| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| `repo-token` | PAT(Personal Access Token) for authorizing repository.
_Defaults to **${{ github.token }}**_. | -| `days-before-stale` | Idle number of days before marking an issue/PR as stale.
_Defaults to **60**_. | -| `days-before-issue-stale` | Idle number of days before marking an issue as stale.
_Override `days-before-stale`_. | -| `days-before-pr-stale` | Idle number of days before marking an PR as stale.
_Override `days-before-stale`_. | -| `days-before-close` | Idle number of days before closing an stale issue/PR.
_Defaults to **7**_. | -| `days-before-issue-close` | Idle number of days before closing an stale issue.
_Override `days-before-close`_. | -| `days-before-pr-close` | Idle number of days before closing an stale PR.
_Override `days-before-close`_. | -| `stale-issue-message` | Message to post on the stale issue. | -| `stale-pr-message` | Message to post on the stale PR. | -| `close-issue-message` | Message to post on the stale issue while closing it. | -| `close-pr-message` | Message to post on the stale PR while closing it. | -| `stale-issue-label` | Label to apply on the stale issue.
_Defaults to **Stale**_. | -| `close-issue-label` | Label to apply on closing issue (automatically removed if no longer closed nor locked). | -| `stale-pr-label` | Label to apply on the stale PR.
_Defaults to **Stale**_. | -| `close-pr-label` | Label to apply on the closing PR (automatically removed if no longer closed nor locked). | -| `exempt-issue-labels` | Labels on an issue exempted from being marked as stale. | -| `exempt-pr-labels` | Labels on the PR exempted from being marked as stale. | -| `only-labels` | Only issues and PRs with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered"). | -| `only-issue-labels` | Only issues with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | -| `only-pr-labels` | Only PRs with ALL these labels are checked. Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | -| `any-of-labels` | Only issues and PRs with ANY of these labels are checked. Separate multiple labels with commas (eg. "incomplete,waiting-feedback"). | -| `operations-per-run` | Maximum number of operations per run (GitHub API CRUD related).
_Defaults to **30**_. | -| `remove-stale-when-updated` | Remove stale label from issue/PR on updates or comments.
_Defaults to **true**_. | -| `debug-only` | Dry-run on action.
_Defaults to **false**_. | -| `ascending` | Order to get issues/PR (true is ascending, false is descending).
_Defaults to **false**_. | -| `skip-stale-issue-message` | Skip adding stale message on stale issue.
_Defaults to **false**_. | -| `skip-stale-pr-message` | Skip adding stale message on stale PR.
_Defaults to **false**_. | -| `start-date` | The date used to skip the stale action on issue/PR created before it (ISO 8601 or RFC 2822). | -| `delete-branch` | Delete the git branch after closing a stale pull request.
_Defaults to **false**_. | -| `exempt-milestones` | Milestones on an issue or a PR exempted from being marked as stale. | -| `exempt-issue-milestones` | Milestones on an issue exempted from being marked as stale.
_Override `exempt-milestones`_. | -| `exempt-pr-milestones` | Milestones on the PR exempted from being marked as stale.
_Override `exempt-milestones`_. | -| `exempt-all-milestones` | Exempt all issues and PRs with milestones from being marked as stale.
_Priority over `exempt-milestones` rules_. | -| `exempt-all-issue-milestones` | Exempt all issues with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | -| `exempt-all-pr-milestones` | Exempt all PRs with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | -| `exempt-assignees` | Assignees on an issue or a PR exempted from being marked as stale. | -| `exempt-issue-assignees` | Assignees on an issue exempted from being marked as stale.
_Override `exempt-assignees`_. | -| `exempt-pr-assignees` | Assignees on the PR exempted from being marked as stale.
_Override `exempt-assignees`_. | -| `exempt-all-assignees` | Exempt all issues and PRs with assignees from being marked as stale.
_Priority over `exempt-assignees` rules_. | -| `exempt-all-issue-assignees` | Exempt all issues with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | -| `exempt-all-pr-assignees` | Exempt all PRs with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | -| `enable-statistics` | Display some statistics at the end of the logs regarding the stale workflow (only when the logs are enabled).
_Defaults to **true**_. | +| Input | Description | +| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `repo-token` | PAT(Personal Access Token) for authorizing repository.
_Defaults to **${{ github.token }}**_. | +| `days-before-stale` | Idle number of days before marking an issue/PR as stale.
_Defaults to **60**_. | +| `days-before-issue-stale` | Idle number of days before marking an issue as stale.
_Override `days-before-stale`_. | +| `days-before-pr-stale` | Idle number of days before marking an PR as stale.
_Override `days-before-stale`_. | +| `days-before-close` | Idle number of days before closing an stale issue/PR.
_Defaults to **7**_. | +| `days-before-issue-close` | Idle number of days before closing an stale issue.
_Override `days-before-close`_. | +| `days-before-pr-close` | Idle number of days before closing an stale PR.
_Override `days-before-close`_. | +| `stale-issue-message` | Message to post on the stale issue. | +| `stale-pr-message` | Message to post on the stale PR. | +| `close-issue-message` | Message to post on the stale issue while closing it. | +| `close-pr-message` | Message to post on the stale PR while closing it. | +| `stale-issue-label` | Label to apply on the stale issue.
_Defaults to **Stale**_. | +| `close-issue-label` | Label to apply on closing issue.
Automatically removed if no longer closed nor locked). | +| `stale-pr-label` | Label to apply on the stale PR.
_Defaults to **Stale**_. | +| `close-pr-label` | Label to apply on the closing PR.
Automatically removed if no longer closed nor locked). | +| `exempt-issue-labels` | Labels on an issue exempted from being marked as stale. | +| `exempt-pr-labels` | Labels on the PR exempted from being marked as stale. | +| `only-labels` | Only issues and PRs with ALL these labels are checked.
Separate multiple labels with commas (eg. "question,answered"). | +| `only-issue-labels` | Only issues with ALL these labels are checked.
Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | +| `only-pr-labels` | Only PRs with ALL these labels are checked.
Separate multiple labels with commas (eg. "question,answered").
_Override `only-labels`_. | +| `any-of-labels` | Only issues and PRs with ANY of these labels are checked.
Separate multiple labels with commas (eg. "incomplete,waiting-feedback"). | +| `operations-per-run` | Maximum number of operations per run.
GitHub API CRUD related.
_Defaults to **30**_. | +| `remove-stale-when-updated` | Remove stale label from issue/PR on updates or comments.
_Defaults to **true**_. | +| `debug-only` | Dry-run on action.
_Defaults to **false**_. | +| `ascending` | Order to get issues/PR.
`true` is ascending, `false` is descending.
_Defaults to **false**_. | +| `skip-stale-issue-message` | Skip adding stale message on stale issue.
_Defaults to **false**_. | +| `skip-stale-pr-message` | Skip adding stale message on stale PR.
_Defaults to **false**_. | +| `start-date` | The date used to skip the stale action on issue/PR created before it.
ISO 8601 or RFC 2822. | +| `delete-branch` | Delete the git branch after closing a stale pull request.
_Defaults to **false**_. | +| `exempt-milestones` | Milestones on an issue or a PR exempted from being marked as stale. | +| `exempt-issue-milestones` | Milestones on an issue exempted from being marked as stale.
_Override `exempt-milestones`_. | +| `exempt-pr-milestones` | Milestones on the PR exempted from being marked as stale.
_Override `exempt-milestones`_. | +| `exempt-all-milestones` | Exempt all issues and PRs with milestones from being marked as stale.
_Priority over `exempt-milestones` rules_. | +| `exempt-all-issue-milestones` | Exempt all issues with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | +| `exempt-all-pr-milestones` | Exempt all PRs with milestones from being marked as stale.
_Override `exempt-all-milestones`_. | +| `exempt-assignees` | Assignees on an issue or a PR exempted from being marked as stale. | +| `exempt-issue-assignees` | Assignees on an issue exempted from being marked as stale.
_Override `exempt-assignees`_. | +| `exempt-pr-assignees` | Assignees on the PR exempted from being marked as stale.
_Override `exempt-assignees`_. | +| `exempt-all-assignees` | Exempt all issues and PRs with assignees from being marked as stale.
_Priority over `exempt-assignees` rules_. | +| `exempt-all-issue-assignees` | Exempt all issues with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | +| `exempt-all-pr-assignees` | Exempt all PRs with assignees from being marked as stale.
_Override `exempt-all-assignees`_. | +| `enable-statistics` | Display some statistics at the end of the logs regarding the stale workflow.
Only when the logs are enabled.
_Defaults to **true**_. | + +### Detailed options + +#### operations-per-run + +Used to limit the number of operations made with the GitHub API to avoid reaching the [rate limit](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). +Based on your project, your GitHub business plan and the date of the cron job you set for this action, you can increase this limit to a higher number. + +When [debugging](#Debugging), you can set it to a much higher number like `1000` since there will be fewer operations made with the GitHub API. +Only the actor and the batch of issues (100 per batch) will consume the operations. + +Default value: `30` ### Usage diff --git a/__tests__/constants/default-processor-options.ts b/__tests__/constants/default-processor-options.ts index 4c8979388..e89a80f61 100644 --- a/__tests__/constants/default-processor-options.ts +++ b/__tests__/constants/default-processor-options.ts @@ -42,5 +42,5 @@ export const DefaultProcessorOptions: IIssuesProcessorOptions = Object.freeze({ exemptAllAssignees: false, exemptAllIssueAssignees: undefined, exemptAllPrAssignees: undefined, - enableStatistics: false + enableStatistics: true }); diff --git a/dist/index.js b/dist/index.js index cbe4c6af4..fa6a1b1d9 100644 --- a/dist/index.js +++ b/dist/index.js @@ -36,11 +36,11 @@ class Assignees { } const exemptAssignees = this._getExemptAssignees(); if (exemptAssignees.length === 0) { - this._issueLogger.info(`No option was specified to skip the stale process for this $$type`); + this._issueLogger.info(`No assignee option was specified to skip the stale process for this $$type`); this._logSkip(); return false; } - this._issueLogger.info(`Found ${exemptAssignees.length} assignee${exemptAssignees.length > 1 ? 's' : ''} on this $$type`); + this._issueLogger.info(`Found ${exemptAssignees.length} assignee${exemptAssignees.length > 1 ? 's' : ''} that can exempt stale on this $$type`); const hasExemptAssignee = exemptAssignees.some((exemptAssignee) => this._hasAssignee(exemptAssignee)); if (!hasExemptAssignee) { this._issueLogger.info('No assignee on this $$type can exempt the stale process'); @@ -191,6 +191,25 @@ exports.Issue = Issue; "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -200,14 +219,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.IssuesProcessor = void 0; +const core = __importStar(__nccwpck_require__(2186)); const github_1 = __nccwpck_require__(5438); +const chalk_1 = __importDefault(__nccwpck_require__(8818)); +const option_1 = __nccwpck_require__(5931); const get_humanized_date_1 = __nccwpck_require__(965); const is_date_more_recent_than_1 = __nccwpck_require__(1473); const is_valid_date_1 = __nccwpck_require__(891); const is_labeled_1 = __nccwpck_require__(6792); -const is_pull_request_1 = __nccwpck_require__(5400); const should_mark_when_stale_1 = __nccwpck_require__(2461); const words_to_list_1 = __nccwpck_require__(1883); const assignees_1 = __nccwpck_require__(7236); @@ -215,6 +239,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 statistics_1 = __nccwpck_require__(3334); /*** * Handle processing of issues for staleness/closure. @@ -222,19 +247,20 @@ const statistics_1 = __nccwpck_require__(3334); class IssuesProcessor { constructor(options) { this._logger = new logger_1.Logger(); - this._operationsLeft = 0; this.staleIssues = []; this.closedIssues = []; this.deletedBranchIssues = []; this.removedLabelIssues = []; this.options = options; - this._operationsLeft = this.options.operationsPerRun; this.client = github_1.getOctokit(this.options.repoToken); + this._operations = new operations_1.Operations(this.options); + this._logger.info(chalk_1.default.yellow('Starting the stale action process...')); if (this.options.debugOnly) { - this._logger.warning('Executing in debug mode. Debug output will be written but no issues will be processed.'); + this._logger.warning(chalk_1.default.yellowBright('Executing in debug mode!')); + this._logger.warning(chalk_1.default.yellowBright('The debug output will be written but no issues/PRs will be processed.')); } if (this.options.enableStatistics) { - this._statistics = new statistics_1.Statistics(this.options); + this._statistics = new statistics_1.Statistics(); } } static _updatedSince(timestamp, num_days) { @@ -249,10 +275,12 @@ class IssuesProcessor { const issues = yield this.getIssues(page); const actor = yield this.getActor(); if (issues.length <= 0) { - this._logger.info('---'); - (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.setOperationsLeft(this._operationsLeft).logStats(); - this._logger.info('No more issues found to process. Exiting.'); - return this._operationsLeft; + 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(); + return this._operations.getOperationsLeftCount(); + } + else { + this._logger.info(chalk_1.default.yellow(`Processing the batch of issues ${chalk_1.default.cyan(`#${page}`)} containing ${chalk_1.default.cyan(issues.length)} issue${issues.length > 1 ? 's' : ''}...`)); } for (const issue of issues.values()) { const issueLogger = new issue_logger_1.IssueLogger(issue); @@ -317,7 +345,7 @@ 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)) { - throw new Error(`Invalid issue field: "created_at". Expected a valid date`); + core.setFailed(new Error(`Invalid issue field: "created_at". Expected a valid date`)); } issueLogger.info(`$$type created the ${get_humanized_date_1.getHumanizedDate(createdAt)} (${issue.created_at})`); if (!is_date_more_recent_than_1.isDateMoreRecentThan(createdAt, startDate)) { @@ -350,7 +378,6 @@ class IssuesProcessor { } const milestones = new milestones_1.Milestones(this.options, issue); if (milestones.shouldExemptMilestones()) { - issueLogger.info(`Skipping $$type because it has an exempted milestone`); continue; // don't process exempt milestones } const assignees = new assignees_1.Assignees(this.options, issue); @@ -374,10 +401,12 @@ class IssuesProcessor { yield this._processStaleIssue(issue, staleLabel, actor, closeMessage, closeLabel); } } - if (this._operationsLeft <= 0) { - this._logger.warning('Reached max number of operations to process. Exiting.'); + 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; } + this._logger.info(chalk_1.default.green(`Batch ${chalk_1.default.cyan(`#${page}`)} processed.`)); // do the next batch return this.processIssues(page + 1); }); @@ -388,7 +417,7 @@ class IssuesProcessor { return __awaiter(this, void 0, void 0, function* () { // find any comments since date on the given issue try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedIssuesCommentsCount(); const comments = yield this.client.issues.listComments({ owner: github_1.context.repo.owner, @@ -409,7 +438,7 @@ class IssuesProcessor { return __awaiter(this, void 0, void 0, function* () { let actor; try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); actor = yield this.client.users.getAuthenticated(); } catch (error) { @@ -425,8 +454,7 @@ class IssuesProcessor { // generate type for response const endpoint = this.client.issues.listForRepo; try { - this._operationsLeft -= 1; - (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedIssuesCount(); + this._operations.consumeOperation(); const issueResult = yield this.client.issues.listForRepo({ owner: github_1.context.repo.owner, repo: github_1.context.repo.repo, @@ -435,6 +463,7 @@ class IssuesProcessor { direction: this.options.ascending ? 'asc' : 'desc', page }); + (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedIssuesCount(issueResult.data.length); return issueResult.data.map((issue) => new issue_1.Issue(this.options, issue)); } catch (error) { @@ -450,7 +479,7 @@ class IssuesProcessor { return __awaiter(this, void 0, void 0, function* () { const issueLogger = new issue_logger_1.IssueLogger(issue); issueLogger.info(`Checking for label on $$type`); - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementFetchedIssuesEventsCount(); const options = this.client.issues.listEvents.endpoint.merge({ owner: github_1.context.repo.owner, @@ -476,8 +505,7 @@ class IssuesProcessor { issueLogger.info(`$$type marked stale on: ${markedStaleOn}`); const issueHasComments = yield this._hasCommentsSince(issue, markedStaleOn, actor); issueLogger.info(`$$type has been commented on: ${issueHasComments}`); - const isPr = is_pull_request_1.isPullRequest(issue); - const daysBeforeClose = isPr + const daysBeforeClose = issue.isPullRequest ? this._getDaysBeforePrClose() : this._getDaysBeforeIssueClose(); issueLogger.info(`Days before $$type close: ${daysBeforeClose}`); @@ -537,7 +565,7 @@ class IssuesProcessor { } if (!skipMessage) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedComment(); yield this.client.issues.createComment({ owner: github_1.context.repo.owner, @@ -551,7 +579,7 @@ class IssuesProcessor { } } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedLabel(); (_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementStaleIssuesCount(); yield this.client.issues.addLabels({ @@ -578,7 +606,7 @@ class IssuesProcessor { } if (closeMessage) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementAddedComment(); yield this.client.issues.createComment({ owner: github_1.context.repo.owner, @@ -593,7 +621,7 @@ class IssuesProcessor { } if (closeLabel) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_b = this._statistics) === null || _b === void 0 ? void 0 : _b.incrementAddedLabel(); yield this.client.issues.addLabels({ owner: github_1.context.repo.owner, @@ -607,7 +635,7 @@ class IssuesProcessor { } } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_c = this._statistics) === null || _c === void 0 ? void 0 : _c.incrementClosedIssuesCount(); yield this.client.issues.update({ owner: github_1.context.repo.owner, @@ -629,7 +657,7 @@ class IssuesProcessor { return; } try { - this._operationsLeft -= 1; + this._operations.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, @@ -660,7 +688,7 @@ class IssuesProcessor { const branch = pullRequest.head.ref; issueLogger.info(`Deleting branch ${branch} from closed $$type`); try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedBranchesCount(); yield this.client.git.deleteRef({ owner: github_1.context.repo.owner, @@ -680,12 +708,11 @@ class IssuesProcessor { const issueLogger = new issue_logger_1.IssueLogger(issue); issueLogger.info(`Removing label "${label}" from $$type`); this.removedLabelIssues.push(issue); - // @todo remove the debug only to be able to test the code below if (this.options.debugOnly) { return; } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); (_a = this._statistics) === null || _a === void 0 ? void 0 : _a.incrementDeletedLabelsCount(); yield this.client.issues.removeLabel({ owner: github_1.context.repo.owner, @@ -768,28 +795,13 @@ exports.IssuesProcessor = IssuesProcessor; "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.IssueLogger = void 0; -const core = __importStar(__nccwpck_require__(2186)); +const chalk_1 = __importDefault(__nccwpck_require__(8818)); +const logger_1 = __nccwpck_require__(6212); /** * @description * Each log will prefix the message with the issue number @@ -803,18 +815,19 @@ const core = __importStar(__nccwpck_require__(2186)); * @example * warning('The $$type will stale') => "The pull request will stale" */ -class IssueLogger { +class IssueLogger extends logger_1.Logger { constructor(issue) { + super(); this._issue = issue; } - warning(message) { - core.warning(this._format(message)); + warning(...message) { + super.warning(this._format(...message)); } - info(message) { - core.info(this._format(message)); + info(...message) { + super.info(this._format(...message)); } - error(message) { - core.error(this._format(message)); + error(...message) { + super.error(this._format(...message)); } _replaceTokens(message) { return this._replaceTypeToken(message); @@ -825,13 +838,24 @@ class IssueLogger { .replace(/\$\$type/g, this._issue.isPullRequest ? 'pull request' : 'issue'); } _prefixWithIssueNumber(message) { - return `[#${this._getIssueNumber()}] ${message}`; + return `${this._getPrefix()} ${message}`; } _getIssueNumber() { return this._issue.number; } - _format(message) { - return this._prefixWithIssueNumber(this._replaceTokens(message)); + _format(...message) { + return this._prefixWithIssueNumber(this._replaceTokens(message.join(' '))); + } + _getPrefix() { + return this._issue.isPullRequest + ? this._getPullRequestPrefix() + : this._getIssuePrefix(); + } + _getIssuePrefix() { + return chalk_1.default.red(`[#${this._getIssueNumber()}]`); + } + _getPullRequestPrefix() { + return chalk_1.default.blue(`[#${this._getIssueNumber()}]`); } } exports.IssueLogger = IssueLogger; @@ -863,18 +887,29 @@ var __importStar = (this && this.__importStar) || function (mod) { __setModuleDefault(result, mod); return result; }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Logger = void 0; const core = __importStar(__nccwpck_require__(2186)); +const chalk_1 = __importDefault(__nccwpck_require__(8818)); +const terminal_link_1 = __importDefault(__nccwpck_require__(1898)); class Logger { - warning(message) { - core.warning(message); + warning(...message) { + core.warning(chalk_1.default.whiteBright(...message)); + } + info(...message) { + core.info(chalk_1.default.whiteBright(...message)); } - info(message) { - core.info(message); + error(...message) { + core.error(chalk_1.default.whiteBright(...message)); } - error(message) { - core.error(message); + createLink(name, link) { + return terminal_link_1.default(name, link); + } + createOptionLink(option) { + return chalk_1.default.magenta(this.createLink(option, `https://github.com/actions/stale#${option}`)); } } exports.Logger = Logger; @@ -894,42 +929,89 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Milestones = void 0; const lodash_deburr_1 = __importDefault(__nccwpck_require__(1601)); const words_to_list_1 = __nccwpck_require__(1883); +const issue_logger_1 = __nccwpck_require__(2984); class Milestones { constructor(options, issue) { this._options = options; this._issue = issue; + this._issueLogger = new issue_logger_1.IssueLogger(issue); } static _cleanMilestone(milestone) { return lodash_deburr_1.default(milestone.toLowerCase()); } shouldExemptMilestones() { + if (!this._issue.milestone) { + this._issueLogger.info('This $$type has no milestone'); + this._logSkip(); + return false; + } if (this._shouldExemptAllMilestones()) { + this._issueLogger.info('Skipping $$type because it has an exempt milestone'); return true; } const exemptMilestones = this._getExemptMilestones(); - return exemptMilestones.some((exemptMilestone) => this._hasMilestone(exemptMilestone)); + if (exemptMilestones.length === 0) { + this._issueLogger.info(`No milestone option was specified to skip the stale process for this $$type`); + this._logSkip(); + return false; + } + this._issueLogger.info(`Found ${exemptMilestones.length} milestone${exemptMilestones.length > 1 ? 's' : ''} that can exempt stale on this $$type`); + const hasExemptMilestone = exemptMilestones.some((exemptMilestone) => this._hasMilestone(exemptMilestone)); + if (!hasExemptMilestone) { + this._issueLogger.info('No milestone on this $$type can exempt the stale process'); + this._logSkip(); + } + else { + this._issueLogger.info('Skipping this $$type because it has an exempt milestone'); + } + return hasExemptMilestone; } _getExemptMilestones() { - return words_to_list_1.wordsToList(this._issue.isPullRequest + return this._issue.isPullRequest ? this._getExemptPullRequestMilestones() - : this._getExemptIssueMilestones()); + : this._getExemptIssueMilestones(); } _getExemptIssueMilestones() { - return this._options.exemptIssueMilestones !== '' - ? this._options.exemptIssueMilestones - : this._options.exemptMilestones; + if (this._options.exemptIssueMilestones === '') { + this._issueLogger.info('The option "exemptIssueMilestones" is disabled. No specific milestone can skip the stale process for this $$type'); + if (this._options.exemptMilestones === '') { + this._issueLogger.info('The option "exemptMilestones" is disabled. No specific milestone can skip the stale process for this $$type'); + return []; + } + const exemptMilestones = words_to_list_1.wordsToList(this._options.exemptMilestones); + this._issueLogger.info(`The option "exemptMilestones" is set. ${exemptMilestones.length} milestone${exemptMilestones.length === 1 ? '' : 's'} can skip the stale process for this $$type`); + return exemptMilestones; + } + const exemptMilestones = words_to_list_1.wordsToList(this._options.exemptIssueMilestones); + this._issueLogger.info(`The option "exemptIssueMilestones" is set. ${exemptMilestones.length} milestone${exemptMilestones.length === 1 ? '' : 's'} can skip the stale process for this $$type`); + return exemptMilestones; } _getExemptPullRequestMilestones() { - return this._options.exemptPrMilestones !== '' - ? this._options.exemptPrMilestones - : this._options.exemptMilestones; + if (this._options.exemptPrMilestones === '') { + this._issueLogger.info('The option "exemptPrMilestones" is disabled. No specific milestone can skip the stale process for this $$type'); + if (this._options.exemptMilestones === '') { + this._issueLogger.info('The option "exemptMilestones" is disabled. No specific milestone can skip the stale process for this $$type'); + return []; + } + const exemptMilestones = words_to_list_1.wordsToList(this._options.exemptMilestones); + this._issueLogger.info(`The option "exemptMilestones" is set. ${exemptMilestones.length} milestone${exemptMilestones.length === 1 ? '' : 's'} can skip the stale process for this $$type`); + return exemptMilestones; + } + const exemptMilestones = words_to_list_1.wordsToList(this._options.exemptPrMilestones); + this._issueLogger.info(`The option "exemptPrMilestones" is set. ${exemptMilestones.length} milestone${exemptMilestones.length === 1 ? '' : 's'} can skip the stale process for this $$type`); + return exemptMilestones; } _hasMilestone(milestone) { if (!this._issue.milestone) { return false; } - return (Milestones._cleanMilestone(milestone) === - Milestones._cleanMilestone(this._issue.milestone.title)); + const cleanMilestone = Milestones._cleanMilestone(milestone); + const isSameMilestone = cleanMilestone === + Milestones._cleanMilestone(this._issue.milestone.title); + if (isSameMilestone) { + this._issueLogger.info(`The milestone "${milestone}" is set on this $$type and is an exempt milestone`); + } + return isSameMilestone; } _shouldExemptAllMilestones() { if (this._issue.milestone) { @@ -941,38 +1023,93 @@ class Milestones { } _shouldExemptAllIssueMilestones() { if (this._options.exemptAllIssueMilestones === true) { + this._issueLogger.info('The option "exemptAllIssueMilestones" is enabled. Any milestone on this $$type will skip the stale process'); return true; } else if (this._options.exemptAllIssueMilestones === false) { + this._issueLogger.info('The option "exemptAllIssueMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'); return false; } + this._logExemptAllMilestonesOption(); return this._options.exemptAllMilestones; } _shouldExemptAllPullRequestMilestones() { if (this._options.exemptAllPrMilestones === true) { + this._issueLogger.info('The option "exemptAllPrMilestones" is enabled. Any milestone on this $$type will skip the stale process'); return true; } else if (this._options.exemptAllPrMilestones === false) { + this._issueLogger.info('The option "exemptAllPrMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'); return false; } + this._logExemptAllMilestonesOption(); return this._options.exemptAllMilestones; } + _logExemptAllMilestonesOption() { + if (this._options.exemptAllMilestones) { + this._issueLogger.info('The option "exemptAllMilestones" is enabled. Any milestone on this $$type will skip the stale process'); + } + else { + this._issueLogger.info('The option "exemptAllMilestones" is disabled. Only some specific milestones on this $$type will skip the stale process'); + } + } + _logSkip() { + this._issueLogger.info('Skip the milestones checks'); + } } exports.Milestones = Milestones; +/***/ }), + +/***/ 7957: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Operations = void 0; +class Operations { + constructor(options) { + this._options = options; + this._operationsLeft = this._options.operationsPerRun; + } + consumeOperation() { + return this.consumeOperations(1); + } + consumeOperations(quantity) { + this._operationsLeft -= quantity; + return this; + } + getUnconsumedOperationsCount() { + return this._options.operationsPerRun - this._operationsLeft; + } + hasOperationsLeft() { + return this._operationsLeft <= 0; + } + getOperationsLeftCount() { + return this._operationsLeft; + } +} +exports.Operations = Operations; + + /***/ }), /***/ 3334: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Statistics = void 0; +const chalk_1 = __importDefault(__nccwpck_require__(8818)); const logger_1 = __nccwpck_require__(6212); class Statistics { - constructor(options) { + constructor() { this._logger = new logger_1.Logger(); this._processedIssuesCount = 0; this._staleIssuesCount = 0; @@ -988,7 +1125,6 @@ class Statistics { this._fetchedIssuesEventsCount = 0; this._fetchedIssuesCommentsCount = 0; this._fetchedPullRequestsCount = 0; - this._options = options; } incrementProcessedIssuesCount(increment = 1) { this._processedIssuesCount += increment; @@ -1003,7 +1139,7 @@ class Statistics { return this; } setOperationsLeft(operationsLeft) { - this._operationsCount = this._options.operationsPerRun - operationsLeft; + this._operationsCount = operationsLeft; return this; } incrementClosedIssuesCount(increment = 1) { @@ -1047,7 +1183,7 @@ class Statistics { return this; } logStats() { - this._logger.info('Statistics'); + this._logger.info(chalk_1.default.yellow.bold('Statistics:')); this._logProcessedIssuesCount(); this._logStaleIssuesCount(); this._logUndoStaleIssuesCount(); @@ -1062,7 +1198,6 @@ class Statistics { this._logFetchedIssuesEventsCount(); this._logFetchedIssuesCommentsCount(); this._logFetchedPullRequestsCount(); - this._logger.info('---'); return this; } _logProcessedIssuesCount() { @@ -1109,13 +1244,69 @@ class Statistics { } _logCount(name, count) { if (count > 0) { - this._logger.info(`${name}: ${count}`); + this._logger.info(`${name}:`, chalk_1.default.cyan(count)); } } } exports.Statistics = Statistics; +/***/ }), + +/***/ 5931: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Option = void 0; +var Option; +(function (Option) { + Option["RepoToken"] = "repo-token"; + Option["StaleIssueMessage"] = "stale-issue-message"; + Option["StalePrMessage"] = "stale-pr-message"; + Option["CloseIssueMessage"] = "close-issue-message"; + Option["ClosePrMessage"] = "close-pr-message"; + Option["DaysBeforeStale"] = "days-before-stale"; + Option["DaysBeforeIssueStale"] = "days-before-issue-stale"; + Option["DaysBeforePrStale"] = "days-before-pr-stale"; + Option["DaysBeforeClose"] = "days-before-close"; + Option["DaysBeforeIssueClose"] = "days-before-issue-close"; + Option["DaysBeforePrClose"] = "days-before-pr-close"; + Option["StaleIssueLabel"] = "stale-issue-label"; + Option["CloseIssueLabel"] = "close-issue-label"; + Option["ExemptIssueLabels"] = "exempt-issue-labels"; + Option["StalePrLabel"] = "stale-pr-label"; + Option["ClosePrLabel"] = "close-pr-label"; + Option["ExemptPrLabels"] = "exempt-pr-labels"; + Option["OnlyLabels"] = "only-labels"; + Option["OnlyIssueLabels"] = "only-issue-labels"; + Option["OnlyPrLabels"] = "only-pr-labels"; + Option["AnyOfLabels"] = "any-of-labels"; + Option["OperationsPerRun"] = "operations-per-run"; + Option["RemoveStaleWhenUpdated"] = "remove-stale-when-updated"; + Option["DebugOnly"] = "debug-only"; + Option["Ascending"] = "ascending"; + Option["SkipStaleIssueMessage"] = "skip-stale-issue-message"; + Option["SkipStalePrMessage"] = "skip-stale-pr-message"; + Option["DeleteBranch"] = "delete-branch"; + Option["StartDate"] = "start-date"; + Option["ExemptMilestones"] = "exempt-milestones"; + Option["ExemptIssueMilestones"] = "exempt-issue-milestones"; + Option["ExemptPrMilestones"] = "exempt-pr-milestones"; + Option["ExemptAllMilestones"] = "exempt-all-milestones"; + Option["ExemptAllIssueMilestones"] = "exempt-all-issue-milestones"; + Option["ExemptAllPrMilestones"] = "exempt-all-pr-milestones"; + Option["ExemptAssignees"] = "exempt-assignees"; + Option["ExemptIssueAssignees"] = "exempt-issue-assignees"; + Option["ExemptPrAssignees"] = "exempt-pr-assignees"; + Option["ExemptAllAssignees"] = "exempt-all-assignees"; + Option["ExemptAllIssueAssignees"] = "exempt-all-issue-assignees"; + Option["ExemptAllPrAssignees"] = "exempt-all-pr-assignees"; + Option["EnableStatistics"] = "enable-statistics"; +})(Option = exports.Option || (exports.Option = {})); + + /***/ }), /***/ 965: @@ -1324,8 +1515,7 @@ function _run() { return __awaiter(this, void 0, void 0, function* () { try { const args = _getAndValidateArgs(); - const processor = new issues_processor_1.IssuesProcessor(args); - yield processor.processIssues(); + yield new issues_processor_1.IssuesProcessor(args).processIssues(); } catch (error) { core.error(error); @@ -1386,14 +1576,14 @@ function _getAndValidateArgs() { 'operations-per-run' ]) { if (isNaN(parseInt(core.getInput(numberInput)))) { - throw Error(`input ${numberInput} did not parse to a valid integer`); + core.setFailed(new Error(`Option "${numberInput}" did not parse to a valid integer`)); } } 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)))) { - throw new Error(`input ${optionalDateInput} did not parse to a valid date`); + core.setFailed(new Error(`Option "${optionalDateInput}" did not parse to a valid date`)); } } } @@ -4914,6 +5104,171 @@ exports.request = request; //# sourceMappingURL=index.js.map +/***/ }), + +/***/ 8512: +/***/ ((module) => { + +"use strict"; + +const ansiEscapes = module.exports; +// TODO: remove this in the next major version +module.exports.default = ansiEscapes; + +const ESC = '\u001B['; +const OSC = '\u001B]'; +const BEL = '\u0007'; +const SEP = ';'; +const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal'; + +ansiEscapes.cursorTo = (x, y) => { + if (typeof x !== 'number') { + throw new TypeError('The `x` argument is required'); + } + + if (typeof y !== 'number') { + return ESC + (x + 1) + 'G'; + } + + return ESC + (y + 1) + ';' + (x + 1) + 'H'; +}; + +ansiEscapes.cursorMove = (x, y) => { + if (typeof x !== 'number') { + throw new TypeError('The `x` argument is required'); + } + + let ret = ''; + + if (x < 0) { + ret += ESC + (-x) + 'D'; + } else if (x > 0) { + ret += ESC + x + 'C'; + } + + if (y < 0) { + ret += ESC + (-y) + 'A'; + } else if (y > 0) { + ret += ESC + y + 'B'; + } + + return ret; +}; + +ansiEscapes.cursorUp = (count = 1) => ESC + count + 'A'; +ansiEscapes.cursorDown = (count = 1) => ESC + count + 'B'; +ansiEscapes.cursorForward = (count = 1) => ESC + count + 'C'; +ansiEscapes.cursorBackward = (count = 1) => ESC + count + 'D'; + +ansiEscapes.cursorLeft = ESC + 'G'; +ansiEscapes.cursorSavePosition = isTerminalApp ? '\u001B7' : ESC + 's'; +ansiEscapes.cursorRestorePosition = isTerminalApp ? '\u001B8' : ESC + 'u'; +ansiEscapes.cursorGetPosition = ESC + '6n'; +ansiEscapes.cursorNextLine = ESC + 'E'; +ansiEscapes.cursorPrevLine = ESC + 'F'; +ansiEscapes.cursorHide = ESC + '?25l'; +ansiEscapes.cursorShow = ESC + '?25h'; + +ansiEscapes.eraseLines = count => { + let clear = ''; + + for (let i = 0; i < count; i++) { + clear += ansiEscapes.eraseLine + (i < count - 1 ? ansiEscapes.cursorUp() : ''); + } + + if (count) { + clear += ansiEscapes.cursorLeft; + } + + return clear; +}; + +ansiEscapes.eraseEndLine = ESC + 'K'; +ansiEscapes.eraseStartLine = ESC + '1K'; +ansiEscapes.eraseLine = ESC + '2K'; +ansiEscapes.eraseDown = ESC + 'J'; +ansiEscapes.eraseUp = ESC + '1J'; +ansiEscapes.eraseScreen = ESC + '2J'; +ansiEscapes.scrollUp = ESC + 'S'; +ansiEscapes.scrollDown = ESC + 'T'; + +ansiEscapes.clearScreen = '\u001Bc'; + +ansiEscapes.clearTerminal = process.platform === 'win32' ? + `${ansiEscapes.eraseScreen}${ESC}0f` : + // 1. Erases the screen (Only done in case `2` is not supported) + // 2. Erases the whole screen including scrollback buffer + // 3. Moves cursor to the top-left position + // More info: https://www.real-world-systems.com/docs/ANSIcode.html + `${ansiEscapes.eraseScreen}${ESC}3J${ESC}H`; + +ansiEscapes.beep = BEL; + +ansiEscapes.link = (text, url) => { + return [ + OSC, + '8', + SEP, + SEP, + url, + BEL, + text, + OSC, + '8', + SEP, + SEP, + BEL + ].join(''); +}; + +ansiEscapes.image = (buffer, options = {}) => { + let ret = `${OSC}1337;File=inline=1`; + + if (options.width) { + ret += `;width=${options.width}`; + } + + if (options.height) { + ret += `;height=${options.height}`; + } + + if (options.preserveAspectRatio === false) { + ret += ';preserveAspectRatio=0'; + } + + return ret + ':' + buffer.toString('base64') + BEL; +}; + +ansiEscapes.iTerm = { + setCwd: (cwd = process.cwd()) => `${OSC}50;CurrentDir=${cwd}${BEL}`, + + annotation: (message, options = {}) => { + let ret = `${OSC}1337;`; + + const hasX = typeof options.x !== 'undefined'; + const hasY = typeof options.y !== 'undefined'; + if ((hasX || hasY) && !(hasX && hasY && typeof options.length !== 'undefined')) { + throw new Error('`x`, `y` and `length` must be defined when `x` or `y` is defined'); + } + + message = message.replace(/\|/g, ''); + + ret += options.isHidden ? 'AddHiddenAnnotation=' : 'AddAnnotation='; + + if (options.length > 0) { + ret += + (hasX ? + [message, options.length, options.x, options.y] : + [options.length, message]).join('|'); + } else { + ret += message; + } + + return ret + BEL; + } +}; + + /***/ }), /***/ 3682: @@ -5092,100 +5447,2055 @@ function removeHook (state, name, method) { /***/ }), -/***/ 8932: -/***/ ((__unused_webpack_module, exports) => { +/***/ 6734: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; +/* module decorator */ module = __nccwpck_require__.nmd(module); -Object.defineProperty(exports, "__esModule", ({ value: true })); +const wrapAnsi16 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${code + offset}m`; +}; -class Deprecation extends Error { - constructor(message) { - super(message); // Maintains proper stack trace (only available on V8) +const wrapAnsi256 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${38 + offset};5;${code}m`; +}; - /* istanbul ignore next */ +const wrapAnsi16m = (fn, offset) => (...args) => { + const rgb = fn(...args); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } +const ansi2ansi = n => n; +const rgb2rgb = (r, g, b) => [r, g, b]; - this.name = 'Deprecation'; - } +const setLazyProperty = (object, property, get) => { + Object.defineProperty(object, property, { + get: () => { + const value = get(); -} + Object.defineProperty(object, property, { + value, + enumerable: true, + configurable: true + }); -exports.Deprecation = Deprecation; + return value; + }, + enumerable: true, + configurable: true + }); +}; +/** @type {typeof import('color-convert')} */ +let colorConvert; +const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { + if (colorConvert === undefined) { + colorConvert = __nccwpck_require__(5121); + } -/***/ }), + const offset = isBackground ? 10 : 0; + const styles = {}; -/***/ 8840: -/***/ ((module) => { + for (const [sourceSpace, suite] of Object.entries(colorConvert)) { + const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; + if (sourceSpace === targetSpace) { + styles[name] = wrap(identity, offset); + } else if (typeof suite === 'object') { + styles[name] = wrap(suite[targetSpace], offset); + } + } -"use strict"; + return styles; +}; +function assembleStyles() { + const codes = new Map(); + const styles = { + modifier: { + reset: [0, 0], + // 21 isn't widely supported and 22 does the same thing + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + + // Bright color + blackBright: [90, 39], + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39] + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + + // Bright color + bgBlackBright: [100, 49], + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49] + } + }; -/*! - * is-plain-object - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ + // Alias bright black as gray (and grey) + styles.color.gray = styles.color.blackBright; + styles.bgColor.bgGray = styles.bgColor.bgBlackBright; + styles.color.grey = styles.color.blackBright; + styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; + + for (const [groupName, group] of Object.entries(styles)) { + for (const [styleName, style] of Object.entries(group)) { + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; -function isObject(o) { - return Object.prototype.toString.call(o) === '[object Object]'; -} + group[styleName] = styles[styleName]; -function isPlainObject(o) { - var ctor,prot; + codes.set(style[0], style[1]); + } - if (isObject(o) === false) return false; + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + } - // If has modified constructor - ctor = o.constructor; - if (ctor === undefined) return true; + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); - // If has modified prototype - prot = ctor.prototype; - if (isObject(prot) === false) return false; + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; - // If constructor does not have an Object-specific method - if (prot.hasOwnProperty('isPrototypeOf') === false) { - return false; - } + setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); + setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); - // Most likely a plain Object - return true; + return styles; } -module.exports = isPlainObject; +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); /***/ }), -/***/ 1601: -/***/ ((module) => { +/***/ 8159: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -/** - * lodash (Custom Build) - * Build: `lodash modularize exports="npm" -o ./` - * Copyright jQuery Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ +/* MIT license */ +/* eslint-disable no-mixed-operators */ +const cssKeywords = __nccwpck_require__(4057); + +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) + +const reverseKeywords = {}; +for (const key of Object.keys(cssKeywords)) { + reverseKeywords[cssKeywords[key]] = key; +} + +const convert = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} +}; -/** Used as references for various `Number` constants. */ -var INFINITY = 1 / 0; +module.exports = convert; -/** `Object#toString` result references. */ -var symbolTag = '[object Symbol]'; +// Hide .channels and .labels properties +for (const model of Object.keys(convert)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } -/** Used to match Latin Unicode letters (excluding mathematical operators). */ -var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } -/** Used to compose unicode character classes. */ + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + const {channels, labels} = convert[model]; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); +} + +convert.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +convert.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; + + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100 + ]; +}; + +convert.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ + return ( + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) + ); +} + +convert.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + let currentClosestDistance = Infinity; + let currentClosestKeyword; + + for (const keyword of Object.keys(cssKeywords)) { + const value = cssKeywords[keyword]; + + // Compute comparative distance + const distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + + return currentClosestKeyword; +}; + +convert.keyword.rgb = function (keyword) { + return cssKeywords[keyword]; +}; + +convert.rgb.xyz = function (rgb) { + let r = rgb[0] / 255; + let g = rgb[1] / 255; + let b = rgb[2] / 255; + + // Assume sRGB + r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); + g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); + b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); + + const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y * 100, z * 100]; +}; + +convert.rgb.lab = function (rgb) { + const xyz = convert.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t2; + let t3; + let val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + const t1 = 2 * l - t2; + + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; +}; + +convert.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; + + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } +}; + +convert.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; + + // Wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + const i = Math.floor(6 * h); + const v = 1 - bl; + f = 6 * h - i; + + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + const n = wh + f * (v - wh); // Linear interpolation + + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces */ + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + /* eslint-enable max-statements-per-line,no-multi-spaces */ + + return [r * 255, g * 255, b * 255]; +}; + +convert.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; + + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // Assume sRGB + r = r > 0.0031308 + ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) + : r * 12.92; + + g = g > 0.0031308 + ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) + : g * 12.92; + + b = b > 0.0031308 + ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) + : b * 12.92; + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; + + const hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + const c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; + + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + let ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; + +convert.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; + + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + const ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert.ansi16.rgb = function (args) { + let color = args % 10; + + // Handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + const mult = (~~(args > 50) + 1) * 0.5; + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; + + return [r, g, b]; +}; + +convert.ansi256.rgb = function (args) { + // Handle greyscale + if (args >= 232) { + const c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert.rgb.hex = function (args) { + const integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + let colorString = match[0]; + + if (match[0].length === 3) { + colorString = colorString.split('').map(char => { + return char + char; + }).join(''); + } + + const integer = parseInt(colorString, 16); + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; + + return [r, g, b]; +}; + +convert.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let grayscale; + let hue; + + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } + + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; + + const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); + + let f = 0; + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; + + const c = s * v; + let f = 0; + + if (c < 1.0) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } + + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; + + /* eslint-disable max-statements-per-line */ + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + /* eslint-enable max-statements-per-line */ + + mg = (1.0 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; +}; + +convert.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const v = c + g * (1.0 - c); + let f = 0; + + if (v > 0.0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const l = g * (1.0 - c) + 0.5 * c; + let s = 0; + + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; +}; + +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; +}; + +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert.gray.hsl = function (args) { + return [0, 0, args[0]]; +}; + +convert.gray.hsv = convert.gray.hsl; + +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert.gray.hex = function (gray) { + const val = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (val << 16) + (val << 8) + val; + + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.rgb.gray = function (rgb) { + const val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; +}; + + +/***/ }), + +/***/ 5121: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const conversions = __nccwpck_require__(8159); +const route = __nccwpck_require__(4663); + +const convert = {}; + +const models = Object.keys(conversions); + +function wrapRaw(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + return fn(args); + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + const result = fn(args); + + // We're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (let len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +models.forEach(fromModel => { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + const routes = route(fromModel); + const routeModels = Object.keys(routes); + + routeModels.forEach(toModel => { + const fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); +}); + +module.exports = convert; + + +/***/ }), + +/***/ 4663: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const conversions = __nccwpck_require__(8159); + +/* + This function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + const graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + const models = Object.keys(conversions); + + for (let len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + const graph = buildGraph(); + const queue = [fromModel]; // Unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length) { + const current = queue.pop(); + const adjacents = Object.keys(conversions[current]); + + for (let len = adjacents.length, i = 0; i < len; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = conversions[graph[toModel].parent][toModel]; + + let cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +module.exports = function (fromModel) { + const graph = deriveBFS(fromModel); + const conversion = {}; + + const models = Object.keys(graph); + for (let len = models.length, i = 0; i < len; i++) { + const toModel = models[i]; + const node = graph[toModel]; + + if (node.parent === null) { + // No possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +}; + + + +/***/ }), + +/***/ 4057: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + + +/***/ }), + +/***/ 1538: +/***/ ((module) => { + +"use strict"; + + +module.exports = (flag, argv = process.argv) => { + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf('--'); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); +}; + + +/***/ }), + +/***/ 4955: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const os = __nccwpck_require__(2087); +const tty = __nccwpck_require__(3867); +const hasFlag = __nccwpck_require__(1538); + +const {env} = process; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false') || + hasFlag('color=never')) { + forceColor = 0; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = 1; +} + +if ('FORCE_COLOR' in env) { + if (env.FORCE_COLOR === 'true') { + forceColor = 1; + } else if (env.FORCE_COLOR === 'false') { + forceColor = 0; + } else { + forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3); + } +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} + +function supportsColor(haveStream, streamIsTTY) { + if (forceColor === 0) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (haveStream && !streamIsTTY && forceColor === undefined) { + return 0; + } + + const min = forceColor || 0; + + if (env.TERM === 'dumb') { + return min; + } + + if (process.platform === 'win32') { + // Windows 10 build 10586 is the first Windows release that supports 256 colors. + // Windows 10 build 14931 is the first release that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream, stream && stream.isTTY); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: translateLevel(supportsColor(true, tty.isatty(1))), + stderr: translateLevel(supportsColor(true, tty.isatty(2))) +}; + + +/***/ }), + +/***/ 8818: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const ansiStyles = __nccwpck_require__(6734); +const {stdout: stdoutColor, stderr: stderrColor} = __nccwpck_require__(4955); +const { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex +} = __nccwpck_require__(2415); + +const {isArray} = Array; + +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = [ + 'ansi', + 'ansi', + 'ansi256', + 'ansi16m' +]; + +const styles = Object.create(null); + +const applyOptions = (object, options = {}) => { + if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) { + throw new Error('The `level` option should be an integer from 0 to 3'); + } + + // Detect level if not set manually + const colorLevel = stdoutColor ? stdoutColor.level : 0; + object.level = options.level === undefined ? colorLevel : options.level; +}; + +class ChalkClass { + constructor(options) { + // eslint-disable-next-line no-constructor-return + return chalkFactory(options); + } +} + +const chalkFactory = options => { + const chalk = {}; + applyOptions(chalk, options); + + chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_); + + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); + + chalk.template.constructor = () => { + throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.'); + }; + + chalk.template.Instance = ChalkClass; + + return chalk.template; +}; + +function Chalk(options) { + return chalkFactory(options); +} + +for (const [styleName, style] of Object.entries(ansiStyles)) { + styles[styleName] = { + get() { + const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); + Object.defineProperty(this, styleName, {value: builder}); + return builder; + } + }; +} + +styles.visible = { + get() { + const builder = createBuilder(this, this._styler, true); + Object.defineProperty(this, 'visible', {value: builder}); + return builder; + } +}; + +const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256']; + +for (const model of usedModels) { + styles[model] = { + get() { + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler); + return createBuilder(this, styler, this._isEmpty); + }; + } + }; +} + +for (const model of usedModels) { + const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); + styles[bgModel] = { + get() { + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler); + return createBuilder(this, styler, this._isEmpty); + }; + } + }; +} + +const proto = Object.defineProperties(() => {}, { + ...styles, + level: { + enumerable: true, + get() { + return this._generator.level; + }, + set(level) { + this._generator.level = level; + } + } +}); + +const createStyler = (open, close, parent) => { + let openAll; + let closeAll; + if (parent === undefined) { + openAll = open; + closeAll = close; + } else { + openAll = parent.openAll + open; + closeAll = close + parent.closeAll; + } + + return { + open, + close, + openAll, + closeAll, + parent + }; +}; + +const createBuilder = (self, _styler, _isEmpty) => { + const builder = (...arguments_) => { + if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) { + // Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}` + return applyStyle(builder, chalkTag(builder, ...arguments_)); + } + + // Single argument is hot path, implicit coercion is faster than anything + // eslint-disable-next-line no-implicit-coercion + return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' ')); + }; + + // We alter the prototype because we must return a function, but there is + // no way to create a function with a different prototype + Object.setPrototypeOf(builder, proto); + + builder._generator = self; + builder._styler = _styler; + builder._isEmpty = _isEmpty; + + return builder; +}; + +const applyStyle = (self, string) => { + if (self.level <= 0 || !string) { + return self._isEmpty ? '' : string; + } + + let styler = self._styler; + + if (styler === undefined) { + return string; + } + + const {openAll, closeAll} = styler; + if (string.indexOf('\u001B') !== -1) { + while (styler !== undefined) { + // Replace any instances already present with a re-opening code + // otherwise only the part of the string until said closing code + // will be colored, and the rest will simply be 'plain'. + string = stringReplaceAll(string, styler.close, styler.open); + + styler = styler.parent; + } + } + + // We can move both next actions out of loop, because remaining actions in loop won't have + // any/visible effect on parts we add here. Close the styling before a linebreak and reopen + // after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92 + const lfIndex = string.indexOf('\n'); + if (lfIndex !== -1) { + string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex); + } + + return openAll + string + closeAll; +}; + +let template; +const chalkTag = (chalk, ...strings) => { + const [firstString] = strings; + + if (!isArray(firstString) || !isArray(firstString.raw)) { + // If chalk() was called by itself or with a string, + // return the string itself as a string. + return strings.join(' '); + } + + const arguments_ = strings.slice(1); + const parts = [firstString.raw[0]]; + + for (let i = 1; i < firstString.length; i++) { + parts.push( + String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'), + String(firstString.raw[i]) + ); + } + + if (template === undefined) { + template = __nccwpck_require__(500); + } + + return template(chalk, parts.join('')); +}; + +Object.defineProperties(Chalk.prototype, styles); + +const chalk = Chalk(); // eslint-disable-line new-cap +chalk.supportsColor = stdoutColor; +chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap +chalk.stderr.supportsColor = stderrColor; + +module.exports = chalk; + + +/***/ }), + +/***/ 500: +/***/ ((module) => { + +"use strict"; + +const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; +const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; +const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; +const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; + +const ESCAPES = new Map([ + ['n', '\n'], + ['r', '\r'], + ['t', '\t'], + ['b', '\b'], + ['f', '\f'], + ['v', '\v'], + ['0', '\0'], + ['\\', '\\'], + ['e', '\u001B'], + ['a', '\u0007'] +]); + +function unescape(c) { + const u = c[0] === 'u'; + const bracket = c[1] === '{'; + + if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { + return String.fromCharCode(parseInt(c.slice(1), 16)); + } + + if (u && bracket) { + return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); + } + + return ESCAPES.get(c) || c; +} + +function parseArguments(name, arguments_) { + const results = []; + const chunks = arguments_.trim().split(/\s*,\s*/g); + let matches; + + for (const chunk of chunks) { + const number = Number(chunk); + if (!Number.isNaN(number)) { + results.push(number); + } else if ((matches = chunk.match(STRING_REGEX))) { + results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character)); + } else { + throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); + } + } + + return results; +} + +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; + + const results = []; + let matches; + + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; + + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); + } + } + + return results; +} + +function buildStyle(chalk, styles) { + const enabled = {}; + + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); + } + } + + let current = chalk; + for (const [styleName, styles] of Object.entries(enabled)) { + if (!Array.isArray(styles)) { + continue; + } + + if (!(styleName in current)) { + throw new Error(`Unknown Chalk style: ${styleName}`); + } + + current = styles.length > 0 ? current[styleName](...styles) : current[styleName]; + } + + return current; +} + +module.exports = (chalk, temporary) => { + const styles = []; + const chunks = []; + let chunk = []; + + // eslint-disable-next-line max-params + temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => { + if (escapeCharacter) { + chunk.push(unescape(escapeCharacter)); + } else if (style) { + const string = chunk.join(''); + chunk = []; + chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string)); + styles.push({inverse, styles: parseStyle(style)}); + } else if (close) { + if (styles.length === 0) { + throw new Error('Found extraneous } in Chalk template literal'); + } + + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(character); + } + }); + + chunks.push(chunk.join('')); + + if (styles.length > 0) { + const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; + throw new Error(errMessage); + } + + return chunks.join(''); +}; + + +/***/ }), + +/***/ 2415: +/***/ ((module) => { + +"use strict"; + + +const stringReplaceAll = (string, substring, replacer) => { + let index = string.indexOf(substring); + if (index === -1) { + return string; + } + + const substringLength = substring.length; + let endIndex = 0; + let returnValue = ''; + do { + returnValue += string.substr(endIndex, index - endIndex) + substring + replacer; + endIndex = index + substringLength; + index = string.indexOf(substring, endIndex); + } while (index !== -1); + + returnValue += string.substr(endIndex); + return returnValue; +}; + +const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => { + let endIndex = 0; + let returnValue = ''; + do { + const gotCR = string[index - 1] === '\r'; + returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix; + endIndex = index + 1; + index = string.indexOf('\n', endIndex); + } while (index !== -1); + + returnValue += string.substr(endIndex); + return returnValue; +}; + +module.exports = { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex +}; + + +/***/ }), + +/***/ 8932: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +class Deprecation extends Error { + constructor(message) { + super(message); // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + this.name = 'Deprecation'; + } + +} + +exports.Deprecation = Deprecation; + + +/***/ }), + +/***/ 8840: +/***/ ((module) => { + +"use strict"; + + +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObject(o) { + return Object.prototype.toString.call(o) === '[object Object]'; +} + +function isPlainObject(o) { + var ctor,prot; + + if (isObject(o) === false) return false; + + // If has modified constructor + ctor = o.constructor; + if (ctor === undefined) return true; + + // If has modified prototype + prot = ctor.prototype; + if (isObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } + + // Most likely a plain Object + return true; +} + +module.exports = isPlainObject; + + +/***/ }), + +/***/ 1601: +/***/ ((module) => { + +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to match Latin Unicode letters (excluding mathematical operators). */ +var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + +/** Used to compose unicode character classes. */ var rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', rsComboSymbolsRange = '\\u20d0-\\u20f0'; @@ -7132,6 +9442,295 @@ function onceStrict (fn) { } +/***/ }), + +/***/ 8824: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const supportsColor = __nccwpck_require__(1507); +const hasFlag = __nccwpck_require__(7362); + +function parseVersion(versionString) { + if (/^\d{3,4}$/.test(versionString)) { + // Env var doesn't always use dots. example: 4601 => 46.1.0 + const m = /(\d{1,2})(\d{2})/.exec(versionString); + return { + major: 0, + minor: parseInt(m[1], 10), + patch: parseInt(m[2], 10) + }; + } + + const versions = (versionString || '').split('.').map(n => parseInt(n, 10)); + return { + major: versions[0], + minor: versions[1], + patch: versions[2] + }; +} + +function supportsHyperlink(stream) { + const {env} = process; + + if ('FORCE_HYPERLINK' in env) { + return !(env.FORCE_HYPERLINK.length > 0 && parseInt(env.FORCE_HYPERLINK, 10) === 0); + } + + if (hasFlag('no-hyperlink') || hasFlag('no-hyperlinks') || hasFlag('hyperlink=false') || hasFlag('hyperlink=never')) { + return false; + } + + if (hasFlag('hyperlink=true') || hasFlag('hyperlink=always')) { + return true; + } + + // If they specify no colors, they probably don't want hyperlinks. + if (!supportsColor.supportsColor(stream)) { + return false; + } + + if (stream && !stream.isTTY) { + return false; + } + + if (process.platform === 'win32') { + return false; + } + + if ('CI' in env) { + return false; + } + + if ('TEAMCITY_VERSION' in env) { + return false; + } + + if ('TERM_PROGRAM' in env) { + const version = parseVersion(env.TERM_PROGRAM_VERSION); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + if (version.major === 3) { + return version.minor >= 1; + } + + return version.major > 3; + // No default + } + } + + if ('VTE_VERSION' in env) { + // 0.50.0 was supposed to support hyperlinks, but throws a segfault + if (env.VTE_VERSION === '0.50.0') { + return false; + } + + const version = parseVersion(env.VTE_VERSION); + return version.major > 0 || version.minor >= 50; + } + + return false; +} + +module.exports = { + supportsHyperlink, + stdout: supportsHyperlink(process.stdout), + stderr: supportsHyperlink(process.stderr) +}; + + +/***/ }), + +/***/ 7362: +/***/ ((module) => { + +"use strict"; + + +module.exports = (flag, argv = process.argv) => { + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf('--'); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); +}; + + +/***/ }), + +/***/ 1507: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const os = __nccwpck_require__(2087); +const tty = __nccwpck_require__(3867); +const hasFlag = __nccwpck_require__(7362); + +const {env} = process; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false') || + hasFlag('color=never')) { + forceColor = 0; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = 1; +} + +if ('FORCE_COLOR' in env) { + if (env.FORCE_COLOR === 'true') { + forceColor = 1; + } else if (env.FORCE_COLOR === 'false') { + forceColor = 0; + } else { + forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3); + } +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} + +function supportsColor(haveStream, streamIsTTY) { + if (forceColor === 0) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (haveStream && !streamIsTTY && forceColor === undefined) { + return 0; + } + + const min = forceColor || 0; + + if (env.TERM === 'dumb') { + return min; + } + + if (process.platform === 'win32') { + // Windows 10 build 10586 is the first Windows release that supports 256 colors. + // Windows 10 build 14931 is the first release that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream, stream && stream.isTTY); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: translateLevel(supportsColor(true, tty.isatty(1))), + stderr: translateLevel(supportsColor(true, tty.isatty(2))) +}; + + +/***/ }), + +/***/ 1898: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const ansiEscapes = __nccwpck_require__(8512); +const supportsHyperlinks = __nccwpck_require__(8824); + +const terminalLink = (text, url, {target = 'stdout', ...options} = {}) => { + if (!supportsHyperlinks[target]) { + // If the fallback has been explicitly disabled, don't modify the text itself. + if (options.fallback === false) { + return text; + } + + return typeof options.fallback === 'function' ? options.fallback(text, url) : `${text} (\u200B${url}\u200B)`; + } + + return ansiEscapes.link(text, url); +}; + +module.exports = (text, url, options = {}) => terminalLink(text, url, options); + +module.exports.stderr = (text, url, options = {}) => terminalLink(text, url, {target: 'stderr', ...options}); + +module.exports.isSupported = supportsHyperlinks.stdout; +module.exports.stderr.isSupported = supportsHyperlinks.stderr; + + /***/ }), /***/ 4294: @@ -7568,6 +10167,14 @@ module.exports = require("tls");; /***/ }), +/***/ 3867: +/***/ ((module) => { + +"use strict"; +module.exports = require("tty");; + +/***/ }), + /***/ 8835: /***/ ((module) => { @@ -7605,8 +10212,8 @@ module.exports = require("zlib");; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed +/******/ id: moduleId, +/******/ loaded: false, /******/ exports: {} /******/ }; /******/ @@ -7619,11 +10226,23 @@ module.exports = require("zlib");; /******/ if(threw) delete __webpack_module_cache__[moduleId]; /******/ } /******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ +/******/ /* webpack/runtime/node module decorator */ +/******/ (() => { +/******/ __nccwpck_require__.nmd = (module) => { +/******/ module.paths = []; +/******/ if (!module.children) module.children = []; +/******/ return module; +/******/ }; +/******/ })(); +/******/ /******/ /* webpack/runtime/compat */ /******/ /******/ __nccwpck_require__.ab = __dirname + "/";/************************************************************************/ diff --git a/package-lock.json b/package-lock.json index f55af56f7..c3c903808 100644 --- a/package-lock.json +++ b/package-lock.json @@ -206,6 +206,19 @@ "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@babel/parser": { @@ -2643,14 +2656,54 @@ "dev": true }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "char-regex": { diff --git a/package.json b/package.json index 445b7615d..9220e8739 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "pack": "ncc build", "test": "jest", "test:only-errors": "jest --reporters jest-silent-reporter --silent", - "test:watch": "jest --watch --notify --expandf", + "test:watch": "jest --watch --notify --expand", "all": "npm run build && npm run format && npm run lint && npm run pack && npm test" }, "repository": { @@ -44,6 +44,7 @@ "@typescript-eslint/eslint-plugin": "^4.16.1", "@typescript-eslint/parser": "^4.16.1", "@vercel/ncc": "^0.27.0", + "chalk": "^4.1.0", "eslint": "^7.21.0", "eslint-plugin-github": "^4.1.2", "eslint-plugin-jest": "^24.1.5", @@ -52,6 +53,7 @@ "jest-silent-reporter": "^0.4.0", "js-yaml": "^4.0.0", "prettier": "^2.2.1", + "terminal-link": "^2.1.1", "ts-jest": "^26.5.3", "typescript": "^4.2.3" } diff --git a/src/classes/assignees.ts b/src/classes/assignees.ts index af844dcdd..5c0c8b2d2 100644 --- a/src/classes/assignees.ts +++ b/src/classes/assignees.ts @@ -42,7 +42,7 @@ export class Assignees { if (exemptAssignees.length === 0) { this._issueLogger.info( - `No option was specified to skip the stale process for this $$type` + `No assignee option was specified to skip the stale process for this $$type` ); this._logSkip(); @@ -52,7 +52,7 @@ export class Assignees { this._issueLogger.info( `Found ${exemptAssignees.length} assignee${ exemptAssignees.length > 1 ? 's' : '' - } on this $$type` + } that can exempt stale on this $$type` ); const hasExemptAssignee: boolean = exemptAssignees.some( diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 70a704a1c..311b18277 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -1,11 +1,13 @@ +import * as core from '@actions/core'; import {context, getOctokit} from '@actions/github'; import {GitHub} from '@actions/github/lib/utils'; import {GetResponseTypeFromEndpointMethod} from '@octokit/types'; +import chalk from 'chalk'; +import {Option} from '../enums/option'; import {getHumanizedDate} from '../functions/dates/get-humanized-date'; import {isDateMoreRecentThan} from '../functions/dates/is-date-more-recent-than'; import {isValidDate} from '../functions/dates/is-valid-date'; import {isLabeled} from '../functions/is-labeled'; -import {isPullRequest} from '../functions/is-pull-request'; import {shouldMarkWhenStale} from '../functions/should-mark-when-stale'; import {wordsToList} from '../functions/words-to-list'; import {IComment} from '../interfaces/comment'; @@ -18,6 +20,7 @@ import {Issue} from './issue'; import {IssueLogger} from './loggers/issue-logger'; import {Logger} from './loggers/logger'; import {Milestones} from './milestones'; +import {Operations} from './operations'; import {Statistics} from './statistics'; /*** @@ -33,8 +36,8 @@ export class IssuesProcessor { } private readonly _logger: Logger = new Logger(); + private readonly _operations: Operations; private readonly _statistics: Statistics | undefined; - private _operationsLeft = 0; readonly client: InstanceType; readonly options: IIssuesProcessorOptions; readonly staleIssues: Issue[] = []; @@ -44,31 +47,49 @@ export class IssuesProcessor { constructor(options: IIssuesProcessorOptions) { this.options = options; - this._operationsLeft = this.options.operationsPerRun; this.client = getOctokit(this.options.repoToken); + this._operations = new Operations(this.options); + + this._logger.info(chalk.yellow('Starting the stale action process...')); if (this.options.debugOnly) { + this._logger.warning(chalk.yellowBright('Executing in debug mode!')); this._logger.warning( - 'Executing in debug mode. Debug output will be written but no issues will be processed.' + chalk.yellowBright( + 'The debug output will be written but no issues/PRs will be processed.' + ) ); } if (this.options.enableStatistics) { - this._statistics = new Statistics(this.options); + this._statistics = new Statistics(); } } - async processIssues(page = 1): Promise { + async processIssues(page: Readonly = 1): Promise { // get the next batch of issues const issues: Issue[] = await this.getIssues(page); const actor: string = await this.getActor(); if (issues.length <= 0) { - this._logger.info('---'); - this._statistics?.setOperationsLeft(this._operationsLeft).logStats(); - this._logger.info('No more issues found to process. Exiting.'); + this._logger.info( + chalk.green('No more issues found to process. Exiting...') + ); + this._statistics + ?.setOperationsLeft(this._operations.getUnconsumedOperationsCount()) + .logStats(); - return this._operationsLeft; + return this._operations.getOperationsLeftCount(); + } else { + this._logger.info( + chalk.yellow( + `Processing the batch of issues ${chalk.cyan( + `#${page}` + )} containing ${chalk.cyan(issues.length)} issue${ + issues.length > 1 ? 's' : '' + }...` + ) + ); } for (const issue of issues.values()) { @@ -160,8 +181,10 @@ export class IssuesProcessor { // Expecting that GitHub will always set a creation date on the issues and PRs // But you never know! if (!isValidDate(createdAt)) { - throw new Error( - `Invalid issue field: "created_at". Expected a valid date` + core.setFailed( + new Error( + `Invalid issue field: "created_at". Expected a valid date` + ) ); } @@ -207,6 +230,7 @@ export class IssuesProcessor { } const anyOfLabels: string[] = wordsToList(this.options.anyOfLabels); + if ( anyOfLabels.length && !anyOfLabels.some((label: Readonly): boolean => @@ -222,9 +246,6 @@ export class IssuesProcessor { const milestones: Milestones = new Milestones(this.options, issue); if (milestones.shouldExemptMilestones()) { - issueLogger.info( - `Skipping $$type because it has an exempted milestone` - ); continue; // don't process exempt milestones } @@ -266,13 +287,27 @@ export class IssuesProcessor { } } - if (this._operationsLeft <= 0) { + if (this._operations.hasOperationsLeft()) { + this._logger.warning( + chalk.yellowBright('No more operations left! Exiting...') + ); this._logger.warning( - 'Reached max number of operations to process. Exiting.' + chalk.yellowBright( + `If you think that not enough issues were processed you could try to increase the quantity related to the ${this._logger.createOptionLink( + Option.OperationsPerRun + )} option which is currently set to ${chalk.cyan( + this.options.operationsPerRun + )}` + ) ); + return 0; } + this._logger.info( + chalk.green(`Batch ${chalk.cyan(`#${page}`)} processed.`) + ); + // do the next batch return this.processIssues(page + 1); } @@ -284,7 +319,7 @@ export class IssuesProcessor { ): Promise { // find any comments since date on the given issue try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementFetchedIssuesCommentsCount(); const comments = await this.client.issues.listComments({ owner: context.repo.owner, @@ -304,7 +339,7 @@ export class IssuesProcessor { let actor; try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); actor = await this.client.users.getAuthenticated(); } catch (error) { return context.actor; @@ -320,8 +355,7 @@ export class IssuesProcessor { type OctoKitIssueList = GetResponseTypeFromEndpointMethod; try { - this._operationsLeft -= 1; - this._statistics?.incrementFetchedIssuesCount(); + this._operations.consumeOperation(); const issueResult: OctoKitIssueList = await this.client.issues.listForRepo( { owner: context.repo.owner, @@ -332,6 +366,7 @@ export class IssuesProcessor { page } ); + this._statistics?.incrementFetchedIssuesCount(issueResult.data.length); return issueResult.data.map( (issue: Readonly): Issue => new Issue(this.options, issue) @@ -352,7 +387,7 @@ export class IssuesProcessor { issueLogger.info(`Checking for label on $$type`); - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementFetchedIssuesEventsCount(); const options = this.client.issues.listEvents.endpoint.merge({ owner: context.repo.owner, @@ -396,8 +431,7 @@ export class IssuesProcessor { ); issueLogger.info(`$$type has been commented on: ${issueHasComments}`); - const isPr: boolean = isPullRequest(issue); - const daysBeforeClose: number = isPr + const daysBeforeClose: number = issue.isPullRequest ? this._getDaysBeforePrClose() : this._getDaysBeforeIssueClose(); @@ -491,7 +525,7 @@ export class IssuesProcessor { if (!skipMessage) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementAddedComment(); await this.client.issues.createComment({ owner: context.repo.owner, @@ -505,7 +539,7 @@ export class IssuesProcessor { } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementAddedLabel(); this._statistics?.incrementStaleIssuesCount(); await this.client.issues.addLabels({ @@ -536,7 +570,7 @@ export class IssuesProcessor { if (closeMessage) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementAddedComment(); await this.client.issues.createComment({ owner: context.repo.owner, @@ -551,7 +585,7 @@ export class IssuesProcessor { if (closeLabel) { try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementAddedLabel(); await this.client.issues.addLabels({ owner: context.repo.owner, @@ -565,7 +599,7 @@ export class IssuesProcessor { } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementClosedIssuesCount(); await this.client.issues.update({ owner: context.repo.owner, @@ -588,7 +622,7 @@ export class IssuesProcessor { } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementFetchedPullRequestsCount(); const pullRequest = await this.client.pulls.get({ owner: context.repo.owner, @@ -625,7 +659,7 @@ export class IssuesProcessor { issueLogger.info(`Deleting branch ${branch} from closed $$type`); try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementDeletedBranchesCount(); await this.client.git.deleteRef({ owner: context.repo.owner, @@ -646,13 +680,12 @@ export class IssuesProcessor { issueLogger.info(`Removing label "${label}" from $$type`); this.removedLabelIssues.push(issue); - // @todo remove the debug only to be able to test the code below if (this.options.debugOnly) { return; } try { - this._operationsLeft -= 1; + this._operations.consumeOperation(); this._statistics?.incrementDeletedLabelsCount(); await this.client.issues.removeLabel({ owner: context.repo.owner, diff --git a/src/classes/loggers/issue-logger.ts b/src/classes/loggers/issue-logger.ts index ef4cd1a98..5db113018 100644 --- a/src/classes/loggers/issue-logger.ts +++ b/src/classes/loggers/issue-logger.ts @@ -1,4 +1,4 @@ -import * as core from '@actions/core'; +import chalk from 'chalk'; import {Issue} from '../issue'; import {Logger} from './logger'; @@ -15,23 +15,24 @@ import {Logger} from './logger'; * @example * warning('The $$type will stale') => "The pull request will stale" */ -export class IssueLogger implements Logger { +export class IssueLogger extends Logger { private readonly _issue: Issue; constructor(issue: Issue) { + super(); this._issue = issue; } - warning(message: Readonly): void { - core.warning(this._format(message)); + warning(...message: string[]): void { + super.warning(this._format(...message)); } - info(message: Readonly): void { - core.info(this._format(message)); + info(...message: string[]): void { + super.info(this._format(...message)); } - error(message: Readonly): void { - core.error(this._format(message)); + error(...message: string[]): void { + super.error(this._format(...message)); } private _replaceTokens(message: Readonly): string { @@ -51,14 +52,28 @@ export class IssueLogger implements Logger { } private _prefixWithIssueNumber(message: Readonly): string { - return `[#${this._getIssueNumber()}] ${message}`; + return `${this._getPrefix()} ${message}`; } private _getIssueNumber(): number { return this._issue.number; } - private _format(message: Readonly): string { - return this._prefixWithIssueNumber(this._replaceTokens(message)); + private _format(...message: string[]): string { + return this._prefixWithIssueNumber(this._replaceTokens(message.join(' '))); + } + + private _getPrefix(): string { + return this._issue.isPullRequest + ? this._getPullRequestPrefix() + : this._getIssuePrefix(); + } + + private _getIssuePrefix(): string { + return chalk.red(`[#${this._getIssueNumber()}]`); + } + + private _getPullRequestPrefix(): string { + return chalk.blue(`[#${this._getIssueNumber()}]`); } } diff --git a/src/classes/loggers/logger.ts b/src/classes/loggers/logger.ts index 8dce898e7..65bb83afd 100644 --- a/src/classes/loggers/logger.ts +++ b/src/classes/loggers/logger.ts @@ -1,15 +1,28 @@ import * as core from '@actions/core'; +import chalk from 'chalk'; +import terminalLink from 'terminal-link'; +import {Option} from '../../enums/option'; export class Logger { - warning(message: Readonly): void { - core.warning(message); + warning(...message: string[]): void { + core.warning(chalk.whiteBright(...message)); } - info(message: Readonly): void { - core.info(message); + info(...message: string[]): void { + core.info(chalk.whiteBright(...message)); } - error(message: Readonly): void { - core.error(message); + error(...message: string[]): void { + core.error(chalk.whiteBright(...message)); + } + + createLink(name: Readonly, link: Readonly): string { + return terminalLink(name, link); + } + + createOptionLink(option: Readonly