Repository: actions/stale
Pull request #312 (2021-02-13 11:22:42)

Bump typescript from 4.1.3 to 4.1.5
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.1.3 to 4.1.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/Microsoft/TypeScript/releases">typescript's releases</a>.</em></p>
<blockquote>
<h2>TypeScript 4.1.5</h2>
<p>This release contains a fix for <a href="https://github-redirect.dependabot.com/microsoft/TypeScript/issues/42718">an issue when language service plugins have no specified name</a>.</p>
<h2>TypeScript 4.1.4</h2>
<p>This release contains fixes for a <a href="https://github-redirect.dependabot.com/microsoft/TypeScript/issues/42712">security risk involving language service plugin loading</a>. More details are available <a href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-1639">here</a>.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/microsoft/TypeScript/commit/aace53f7d71af11e4b89dd074a1657964a22d0b4"><code>aace53f</code></a> Bump version to 4.1.5 and LKG</li>
<li><a href="https://github.com/microsoft/TypeScript/commit/af0ad8089777ef8df16b0980b0972f1e214308fe"><code>af0ad80</code></a> Handle if plugin doesnt specify name (<a href="https://github-redirect.dependabot.com/Microsoft/TypeScript/issues/42720">#42720</a>)</li>
<li><a href="https://github.com/microsoft/TypeScript/commit/c329d68d4591d31d966ab64e0da579c95a1c5e1d"><code>c329d68</code></a> Bump version to 4.1.4 and LKG</li>
<li><a href="https://github.com/microsoft/TypeScript/commit/7bc71732c1fd09d910433f7f020a2de312e9549f"><code>7bc7173</code></a> Allow only package names as plugin names</li>
<li>See full diff in <a href="https://github.com/Microsoft/TypeScript/compare/v4.1.3...v4.1.5">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typescript&package-manager=npm_and_yarn&previous-version=4.1.3&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.eslintrc.json b/.eslintrc.json
index 5f707a9..d4ca3d2 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -14,7 +14,9 @@
     "@typescript-eslint/no-unused-vars": "error",
     "@typescript-eslint/explicit-member-accessibility": [
       "error",
-      {"accessibility": "no-public"}
+      {
+        "accessibility": "no-public"
+      }
     ],
     "@typescript-eslint/no-require-imports": "error",
     "@typescript-eslint/array-type": "error",
@@ -47,7 +49,13 @@
     "@typescript-eslint/type-annotation-spacing": "error",
     "@typescript-eslint/unbound-method": "off",
     "no-shadow": "off",
-    "@typescript-eslint/no-shadow": "error"
+    "@typescript-eslint/no-shadow": "error",
+    "prettier/prettier": [
+      "error",
+      {
+        "endOfLine": "auto"
+      }
+    ]
   },
   "env": {
     "node": true,
diff --git a/.prettierrc.json b/.prettierrc.json
index b243c2f..8f6dcc5 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -6,5 +6,6 @@
   "singleQuote": true,
   "trailingComma": "none",
   "bracketSpacing": false,
-  "arrowParens": "avoid"
+  "arrowParens": "avoid",
+  "endOfLine": "auto"
 }
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6acf9be..27f75de 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -9,7 +9,7 @@
             "args": [
                 "-i"
             ],
-            "preLaunchTask": "tsc: build - tsconfig.json",
+            "preLaunchTask": "tsc: build - tsconfig.app.json",
             "internalConsoleOptions": "openOnSessionStart",
             "console": "integratedTerminal",
             "outFiles": [
@@ -17,4 +17,4 @@
             ]
         }
     ]
-}
\ No newline at end of file
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..34b5a69
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,19 @@
+### Building and testing
+
+Install the dependencies.
+
+```bash
+$ npm install
+```
+
+Build the typescript and package it for distribution.
+
+```bash
+$ npm run build && npm run pack
+```
+
+Run the tests :heavy_check_mark:
+
+```bash
+$ npm test
+```
diff --git a/README.md b/README.md
index dab01a8..5c1852e 100644
--- a/README.md
+++ b/README.md
@@ -2,59 +2,42 @@
 
 Warns and then closes issues and PRs that have had no activity for a specified amount of time.
 
-### Building and testing
-
-Install the dependencies
-
-```bash
-$ npm install
-```
-
-Build the typescript and package it for distribution
-
-```bash
-$ npm run build && npm run pack
-```
-
-Run the tests :heavy_check_mark:
-
-```bash
-$ npm test
-```
-
 ### 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.                                                             | Optional |
-| `stale-pr-label`            | Label to apply on the stale pr.                                                              | Optional |
-| `close-pr-label`            | Label to apply on the closing pr.                                                            | 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 |
-| `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 |
-| `only-labels`               | Only labels checked for stale issue/pr.                                                      | 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 |
-| `delete-branch`             | Delete the git branch after closing a stale pull request. _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 |
+| 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.                                                                                | Optional |
+| `stale-pr-label`              | Label to apply on the stale PR.                                                                                 | Optional |
+| `close-pr-label`              | Label to apply on the closing PR.                                                                               | 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 |
+| `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 |
+| `only-labels`                 | Only labels checked for stale issue/PR.                                                                         | 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 |
 
 ### Usage
 
@@ -97,7 +80,7 @@ jobs:
           days-before-close: 5
 ```
 
-Configure different stale timeouts but never close a pr:
+Configure different stale timeouts but never close a PR:
 
 ```yaml
 name: 'Close stale issues and PR'
@@ -113,7 +96,7 @@ jobs:
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
           stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
-          stale-pr-message: 'This pr is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
+          stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
           close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
           days-before-stale: 30
           days-before-close: 5
@@ -136,9 +119,9 @@ jobs:
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
           stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
-          stale-pr-message: 'This pr is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
+          stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
           close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
-          close-pr-message: 'This pr was closed because it has been stalled for 10 days with no activity.'
+          close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.'
           days-before-issue-stale: 30
           days-before-pr-stale: 45
           days-before-issue-close: 5
@@ -168,7 +151,7 @@ jobs:
           only-labels: 'awaiting-feedback,awaiting-answers'
 ```
 
-Configure the stale action to only stale issue/pr created after the 18th april 2020:
+Configure the stale action to only stale issue/PR created after the 18th april 2020:
 
 ```yaml
 name: 'Close stale issues and PRs'
@@ -203,6 +186,31 @@ jobs:
           exempt-pr-milestones: 'bugfix,improvement'
 ```
 
+Avoid stale for all PR with milestones:
+
+```yaml
+name: 'Close stale issues and PRs'
+on:
+  schedule:
+    - cron: '30 1 * * *'
+
+jobs:
+  stale:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/stale@v3
+        with:
+          exempt-all-pr-milestones: true
+```
+
 ### Debugging
 
-To see debug output from this action, you must set the secret `ACTIONS_STEP_DEBUG` to `true` in your repository. You can run this action in debug only mode (no actions will be taken on your issues) by passing `debug-only` `true` as an argument to the action.
+To see the debug output from this action, you must set the secret `ACTIONS_STEP_DEBUG` to `true` in your repository.  
+You can run this action in debug only mode (no actions will be taken on your issues and pull requests) by passing `debug-only` to `true` as an argument to the action.  
+You can also increase the maximum number of operations per run by passing `operations-per-run` to `100` for example.  
+Finally, you could also change the cron job frequency in the stale workflow to run stale more often.
+
+### Contributing
+
+You wish to contribute?  
+Check out the [contributing](CONTRIBUTING.md) file before helping us.
diff --git a/action.yml b/action.yml
index 41f667a..4847e78 100644
--- a/action.yml
+++ b/action.yml
@@ -10,13 +10,13 @@ inputs:
     description: 'The message to post on the issue when tagging it. If none provided, will not mark issues stale.'
     required: false
   stale-pr-message:
-    description: 'The message to post on the pr when tagging it. If none provided, will not mark pull requests stale.'
+    description: 'The message to post on the pull request when tagging it. If none provided, will not mark pull requests stale.'
     required: false
   close-issue-message:
     description: 'The message to post on the issue when closing it. If none provided, will not comment when closing an issue.'
     required: false
   close-pr-message:
-    description: 'The message to post on the pr when closing it. If none provided, will not comment when closing a pull requests.'
+    description: 'The message to post on the pull request when closing it. If none provided, will not comment when closing a pull requests.'
     required: false
   days-before-stale:
     description: 'The number of days old an issue or a pull request can be before marking it stale. Set to -1 to never mark issues or pull requests as stale automatically.'
@@ -57,19 +57,31 @@ 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 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 pr is exempt from being marked 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:
-    description: 'The milestones that mean an issue is exempt from being marked stale. Separate multiple milestones with commas (eg. "milestone1,milestone2"). Override "exempt-milestones" option regarding only the issue.'
+    description: 'The milestones that mean an issue is exempt from being marked as stale. Separate multiple milestones with commas (eg. "milestone1,milestone2"). Override "exempt-milestones" option regarding only the issues.'
     default: ''
     required: false
   exempt-pr-milestones:
-    description: 'The milestones that mean a pull request is exempt from being marked stale. Separate multiple milestones with commas (eg. "milestone1,milestone2"). Override "exempt-milestones" option regarding only the pull requests.'
+    description: 'The milestones that mean a pull request is exempt from being marked as stale. Separate multiple milestones with commas (eg. "milestone1,milestone2"). Override "exempt-milestones" option regarding only the pull requests.'
+    default: ''
+    required: false
+  exempt-all-milestones:
+    description: 'Exempt all issues and pull requests with milestones from being marked as stale. Default to false.'
+    default: 'false'
+    required: false
+  exempt-all-issue-milestones:
+    description: 'Exempt all issues with milestones from being marked as stale. Override "exempt-all-milestones" option regarding only the issues.'
+    default: ''
+    required: false
+  exempt-all-pr-milestones:
+    description: 'Exempt all pull requests with milestones from being marked as stale. Override "exempt-all-milestones" option regarding only the pull requests.'
     default: ''
     required: false
   only-labels:
@@ -105,7 +117,7 @@ inputs:
     default: 'false'
     required: false
   start-date:
-    description: 'The date used to skip the stale action on issue/pr created before it (ISO 8601 or RFC 2822).'
+    description: 'The date used to skip the stale action on issue/pull request created before it (ISO 8601 or RFC 2822).'
     default: ''
     required: false
 runs:
diff --git a/dist/index.js b/dist/index.js
index cc03880..ad4c58d 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -660,6 +660,9 @@ class Milestones {
         return lodash_deburr_1.default(label.toLowerCase());
     }
     shouldExemptMilestones() {
+        if (this._shouldExemptAllMilestones()) {
+            return true;
+        }
         const exemptMilestones = this._getExemptMilestones();
         return exemptMilestones.some((exemptMilestone) => this._hasMilestone(exemptMilestone));
     }
@@ -685,6 +688,32 @@ class Milestones {
         return (Milestones._cleanMilestone(milestone) ===
             Milestones._cleanMilestone(this._issue.milestone.title));
     }
+    _shouldExemptAllMilestones() {
+        if (this._issue.milestone) {
+            return this._issue.isPullRequest
+                ? this._shouldExemptAllPullRequestMilestones()
+                : this._shouldExemptAllIssueMilestones();
+        }
+        return false;
+    }
+    _shouldExemptAllIssueMilestones() {
+        if (this._options.exemptAllIssueMilestones === true) {
+            return true;
+        }
+        else if (this._options.exemptAllIssueMilestones === false) {
+            return false;
+        }
+        return this._options.exemptAllMilestones;
+    }
+    _shouldExemptAllPullRequestMilestones() {
+        if (this._options.exemptAllPrMilestones === true) {
+            return true;
+        }
+        else if (this._options.exemptAllPrMilestones === false) {
+            return false;
+        }
+        return this._options.exemptAllMilestones;
+    }
 }
 exports.Milestones = Milestones;
 
@@ -925,10 +954,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
 const core = __importStar(__nccwpck_require__(2186));
 const is_valid_date_1 = __nccwpck_require__(891);
 const issues_processor_1 = __nccwpck_require__(3292);
-function run() {
+function _run() {
     return __awaiter(this, void 0, void 0, function* () {
         try {
-            const args = getAndValidateArgs();
+            const args = _getAndValidateArgs();
             const processor = new issues_processor_1.IssuesProcessor(args);
             yield processor.processIssues();
         }
@@ -938,7 +967,7 @@ function run() {
         }
     });
 }
-function getAndValidateArgs() {
+function _getAndValidateArgs() {
     const args = {
         repoToken: core.getInput('repo-token'),
         staleIssueMessage: core.getInput('stale-issue-message'),
@@ -970,7 +999,10 @@ function getAndValidateArgs() {
             : undefined,
         exemptMilestones: core.getInput('exempt-milestones'),
         exemptIssueMilestones: core.getInput('exempt-issue-milestones'),
-        exemptPrMilestones: core.getInput('exempt-pr-milestones')
+        exemptPrMilestones: core.getInput('exempt-pr-milestones'),
+        exemptAllMilestones: core.getInput('exempt-all-milestones') === 'true',
+        exemptAllIssueMilestones: _toOptionalBoolean('exempt-all-issue-milestones'),
+        exemptAllPrMilestones: _toOptionalBoolean('exempt-all-pr-milestones')
     };
     for (const numberInput of [
         'days-before-stale',
@@ -991,7 +1023,17 @@ function getAndValidateArgs() {
     }
     return args;
 }
-run();
+function _toOptionalBoolean(argumentName) {
+    const argument = core.getInput(argumentName);
+    if (argument === 'true') {
+        return true;
+    }
+    else if (argument === 'false') {
+        return false;
+    }
+    return undefined;
+}
+_run();
 
 
 /***/ }),
diff --git a/package-lock.json b/package-lock.json
index 5e33050..2bb5a78 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1568,9 +1568,9 @@
       }
     },
     "@octokit/openapi-types": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-4.0.0.tgz",
-      "integrity": "sha512-o4Q9VPYaIdzxskfVuWk7Dcb6Ldq2xbd1QKmPCRx29nFdFxm+2Py74QLfbB3CgankZerHnNJ9wgINOkwa/O2qRg=="
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-4.0.3.tgz",
+      "integrity": "sha512-CXCe1Zzc/WhjpuAEgoUktAinZJ02l6W8q1hDkwBtaonEtO6cjo/3Pyb2J1t5y2q/SvjESDJ77xZ9UVHqQVvihw=="
     },
     "@octokit/plugin-paginate-rest": {
       "version": "2.2.4",
@@ -1620,14 +1620,14 @@
       }
     },
     "@octokit/rest": {
-      "version": "18.1.0",
-      "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.1.0.tgz",
-      "integrity": "sha512-YQfpTzWV3jdzDPyXQVO54f5I2t1zxk/S53Vbe+Aa5vQj6MdTx6sNEWzmUzUO8lSVowbGOnjcQHzW1A8ATr+/7g==",
+      "version": "18.1.1",
+      "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.1.1.tgz",
+      "integrity": "sha512-ZcCHMyfGT1qtJD72usigAfUQ6jU89ZUPFb2AOubR6WZ7/RRFVZUENVm1I2yvJBUicqTujezPW9cY1+o3Mb4rNA==",
       "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.10.1"
+        "@octokit/plugin-rest-endpoint-methods": "4.10.3"
       },
       "dependencies": {
         "@octokit/auth-token": {
@@ -1670,11 +1670,11 @@
           }
         },
         "@octokit/plugin-rest-endpoint-methods": {
-          "version": "4.10.1",
-          "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.10.1.tgz",
-          "integrity": "sha512-YGMiEidTORzgUmYZu0eH4q2k8kgQSHQMuBOBYiKxUYs/nXea4q/Ze6tDzjcRAPmHNJYXrENs1bEMlcdGKT+8ug==",
+          "version": "4.10.3",
+          "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.10.3.tgz",
+          "integrity": "sha512-CsNQeVY34Vs9iea2Z9/TCPlebxv6KpjO9f1BUPz+14qundTSYT9kgf8j5wA1k37VstfBQ4xnuURYdnbGzJBJXw==",
           "requires": {
-            "@octokit/types": "^6.8.2",
+            "@octokit/types": "^6.8.3",
             "deprecation": "^2.3.1"
           }
         },
@@ -1694,11 +1694,11 @@
           }
         },
         "@octokit/types": {
-          "version": "6.8.2",
-          "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.8.2.tgz",
-          "integrity": "sha512-RpG0NJd7OKSkWptiFhy1xCLkThs5YoDIKM21lEtDmUvSpbaIEfrxzckWLUGDFfF8RydSyngo44gDv8m2hHruUg==",
+          "version": "6.8.4",
+          "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.8.4.tgz",
+          "integrity": "sha512-iKAMx//mBk74NwXdeKg8kdYO5zb1n6Ypk5uxwM96U35rJQv4Y8lMQxfzhN8QyzQHaZkxQsl28bn+MPEhiqXb7w==",
           "requires": {
-            "@octokit/openapi-types": "^4.0.0",
+            "@octokit/openapi-types": "^4.0.3",
             "@types/node": ">= 8"
           }
         },
@@ -9560,9 +9560,9 @@
       }
     },
     "typescript": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz",
-      "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==",
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz",
+      "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==",
       "dev": true
     },
     "union-value": {
diff --git a/package.json b/package.json
index e1c5d14..68fd2a1 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
   "description": "Marks old issues and PRs as stale",
   "main": "lib/main.js",
   "scripts": {
-    "build": "tsc",
+    "build": "tsc --project tsconfig.app.json",
     "format": "prettier --write --ignore-unknown **/*.{md,json,yml,ts}",
     "format-check": "prettier --check --ignore-unknown **/*.{md,json,yml,ts}",
     "lint": "eslint src/**/*.ts",
@@ -30,7 +30,7 @@
   "dependencies": {
     "@actions/core": "^1.2.6",
     "@actions/github": "^4.0.0",
-    "@octokit/rest": "^18.1.0",
+    "@octokit/rest": "^18.1.1",
     "lodash.deburr": "^4.1.0",
     "semver": "^7.3.4"
   },
@@ -50,6 +50,6 @@
     "js-yaml": "^4.0.0",
     "prettier": "^2.2.1",
     "ts-jest": "^26.4.4",
-    "typescript": "^4.1.3"
+    "typescript": "^4.1.5"
   }
 }
diff --git a/src/classes/issue.spec.ts b/src/classes/issue.spec.ts
index 949211d..105c19a 100644
--- a/src/classes/issue.spec.ts
+++ b/src/classes/issue.spec.ts
@@ -39,7 +39,10 @@ describe('Issue', (): void => {
       stalePrMessage: '',
       startDate: undefined,
       stalePrLabel: 'dummy-stale-pr-label',
-      staleIssueLabel: 'dummy-stale-issue-label'
+      staleIssueLabel: 'dummy-stale-issue-label',
+      exemptAllMilestones: false,
+      exemptAllIssueMilestones: undefined,
+      exemptAllPrMilestones: undefined
     };
     issueInterface = {
       title: 'dummy-title',
diff --git a/src/classes/milestones.spec.ts b/src/classes/milestones.spec.ts
index 4703a7f..d010fb7 100644
--- a/src/classes/milestones.spec.ts
+++ b/src/classes/milestones.spec.ts
@@ -39,7 +39,10 @@ describe('Milestones', (): void => {
       startDate: undefined,
       exemptIssueMilestones: '',
       exemptPrMilestones: '',
-      exemptMilestones: ''
+      exemptMilestones: '',
+      exemptAllMilestones: false,
+      exemptAllIssueMilestones: undefined,
+      exemptAllPrMilestones: undefined
     };
     issueInterface = {
       created_at: '',
diff --git a/src/classes/milestones.ts b/src/classes/milestones.ts
index b208c85..eeb9139 100644
--- a/src/classes/milestones.ts
+++ b/src/classes/milestones.ts
@@ -19,6 +19,10 @@ export class Milestones {
   }
 
   shouldExemptMilestones(): boolean {
+    if (this._shouldExemptAllMilestones()) {
+      return true;
+    }
+
     const exemptMilestones: string[] = this._getExemptMilestones();
 
     return exemptMilestones.some((exemptMilestone: Readonly<string>): boolean =>
@@ -56,4 +60,34 @@ export class Milestones {
       Milestones._cleanMilestone(this._issue.milestone.title)
     );
   }
+
+  private _shouldExemptAllMilestones(): boolean {
+    if (this._issue.milestone) {
+      return this._issue.isPullRequest
+        ? this._shouldExemptAllPullRequestMilestones()
+        : this._shouldExemptAllIssueMilestones();
+    }
+
+    return false;
+  }
+
+  private _shouldExemptAllIssueMilestones(): boolean {
+    if (this._options.exemptAllIssueMilestones === true) {
+      return true;
+    } else if (this._options.exemptAllIssueMilestones === false) {
+      return false;
+    }
+
+    return this._options.exemptAllMilestones;
+  }
+
+  private _shouldExemptAllPullRequestMilestones(): boolean {
+    if (this._options.exemptAllPrMilestones === true) {
+      return true;
+    } else if (this._options.exemptAllPrMilestones === false) {
+      return false;
+    }
+
+    return this._options.exemptAllMilestones;
+  }
 }
diff --git a/src/interfaces/issues-processor-options.ts b/src/interfaces/issues-processor-options.ts
index 11253c9..8a74cab 100644
--- a/src/interfaces/issues-processor-options.ts
+++ b/src/interfaces/issues-processor-options.ts
@@ -30,4 +30,7 @@ export interface IIssuesProcessorOptions {
   exemptMilestones: string;
   exemptIssueMilestones: string;
   exemptPrMilestones: string;
+  exemptAllMilestones: boolean;
+  exemptAllIssueMilestones: boolean | undefined;
+  exemptAllPrMilestones: boolean | undefined;
 }
diff --git a/src/main.ts b/src/main.ts
index 130d1b0..7620c05 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -3,9 +3,9 @@ import {isValidDate} from './functions/dates/is-valid-date';
 import {IssuesProcessor} from './classes/issues-processor';
 import {IIssuesProcessorOptions} from './interfaces/issues-processor-options';
 
-async function run(): Promise<void> {
+async function _run(): Promise<void> {
   try {
-    const args = getAndValidateArgs();
+    const args = _getAndValidateArgs();
 
     const processor: IssuesProcessor = new IssuesProcessor(args);
     await processor.processIssues();
@@ -15,7 +15,7 @@ async function run(): Promise<void> {
   }
 }
 
-function getAndValidateArgs(): IIssuesProcessorOptions {
+function _getAndValidateArgs(): IIssuesProcessorOptions {
   const args: IIssuesProcessorOptions = {
     repoToken: core.getInput('repo-token'),
     staleIssueMessage: core.getInput('stale-issue-message'),
@@ -56,7 +56,10 @@ function getAndValidateArgs(): IIssuesProcessorOptions {
         : undefined,
     exemptMilestones: core.getInput('exempt-milestones'),
     exemptIssueMilestones: core.getInput('exempt-issue-milestones'),
-    exemptPrMilestones: core.getInput('exempt-pr-milestones')
+    exemptPrMilestones: core.getInput('exempt-pr-milestones'),
+    exemptAllMilestones: core.getInput('exempt-all-milestones') === 'true',
+    exemptAllIssueMilestones: _toOptionalBoolean('exempt-all-issue-milestones'),
+    exemptAllPrMilestones: _toOptionalBoolean('exempt-all-pr-milestones')
   };
 
   for (const numberInput of [
@@ -83,4 +86,18 @@ function getAndValidateArgs(): IIssuesProcessorOptions {
   return args;
 }
 
-run();
+function _toOptionalBoolean(
+  argumentName: Readonly<string>
+): boolean | undefined {
+  const argument: string = core.getInput(argumentName);
+
+  if (argument === 'true') {
+    return true;
+  } else if (argument === 'false') {
+    return false;
+  }
+
+  return undefined;
+}
+
+_run();
diff --git a/tsconfig.app.json b/tsconfig.app.json
new file mode 100644
index 0000000..2b5d80c
--- /dev/null
+++ b/tsconfig.app.json
@@ -0,0 +1,5 @@
+{
+  "extends": "./tsconfig.json",
+  "exclude": ["node_modules", "**/*.spec.ts"],
+  "include": ["src"]
+}
diff --git a/tsconfig.json b/tsconfig.json
index 4ba71e8..ed2e7fe 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,11 +3,10 @@
     "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
     "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
     "outDir": "./lib" /* Redirect output structure to the directory. */,
-    "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
     "strict": true /* Enable all strict type-checking options. */,
     "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
     "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
     //"sourceMap": true
   },
-  "exclude": ["node_modules", "**/*.test.ts"]
+  "include": ["src", "__tests__"]
 }
diff --git a/tsconfig.spec.json b/tsconfig.spec.json
new file mode 100644
index 0000000..14f9e85
--- /dev/null
+++ b/tsconfig.spec.json
@@ -0,0 +1,5 @@
+{
+  "extends": "./tsconfig.json",
+  "include": ["src", "__tests__"],
+  "exclude": ["node_modules"]
+}


Test patch:
diff --git a/__tests__/constants/default-processor-options.ts b/__tests__/constants/default-processor-options.ts
new file mode 100644
index 0000000..941fac4
--- /dev/null
+++ b/__tests__/constants/default-processor-options.ts
@@ -0,0 +1,36 @@
+import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options';
+
+export const DefaultProcessorOptions: IIssuesProcessorOptions = Object.freeze({
+  repoToken: 'none',
+  staleIssueMessage: 'This issue is stale',
+  stalePrMessage: 'This PR is stale',
+  closeIssueMessage: 'This issue is being closed',
+  closePrMessage: 'This PR is being closed',
+  daysBeforeStale: 1,
+  daysBeforeIssueStale: NaN,
+  daysBeforePrStale: NaN,
+  daysBeforeClose: 30,
+  daysBeforeIssueClose: NaN,
+  daysBeforePrClose: NaN,
+  staleIssueLabel: 'Stale',
+  closeIssueLabel: '',
+  exemptIssueLabels: '',
+  stalePrLabel: 'Stale',
+  closePrLabel: '',
+  exemptPrLabels: '',
+  onlyLabels: '',
+  operationsPerRun: 100,
+  debugOnly: true,
+  removeStaleWhenUpdated: false,
+  ascending: false,
+  skipStaleIssueMessage: false,
+  skipStalePrMessage: false,
+  deleteBranch: false,
+  startDate: '',
+  exemptMilestones: '',
+  exemptIssueMilestones: '',
+  exemptPrMilestones: '',
+  exemptAllMilestones: false,
+  exemptAllIssueMilestones: undefined,
+  exemptAllPrMilestones: undefined
+});
diff --git a/__tests__/functions/generate-issue.ts b/__tests__/functions/generate-issue.ts
new file mode 100644
index 0000000..90aabc0
--- /dev/null
+++ b/__tests__/functions/generate-issue.ts
@@ -0,0 +1,34 @@
+import {Issue} from '../../src/classes/issue';
+import {IIssuesProcessorOptions} from '../../src/interfaces/issues-processor-options';
+import {IsoDateString} from '../../src/types/iso-date-string';
+
+export function generateIssue(
+  options: IIssuesProcessorOptions,
+  id: number,
+  title: string,
+  updatedAt: IsoDateString,
+  createdAt: IsoDateString = updatedAt,
+  isPullRequest = false,
+  labels: string[] = [],
+  isClosed = false,
+  isLocked = false,
+  milestone: string | undefined = undefined
+): Issue {
+  return new Issue(options, {
+    number: id,
+    labels: labels.map(l => {
+      return {name: l};
+    }),
+    title,
+    created_at: createdAt,
+    updated_at: updatedAt,
+    pull_request: isPullRequest ? {} : null,
+    state: isClosed ? 'closed' : 'open',
+    locked: isLocked,
+    milestone: milestone
+      ? {
+          title: milestone
+        }
+      : undefined
+  });
+}
diff --git a/__tests__/main.test.ts b/__tests__/main.spec.ts
similarity index 86%
rename from __tests__/main.test.ts
rename to __tests__/main.spec.ts
index 2d38793..46ea62f 100644
--- a/__tests__/main.test.ts
+++ b/__tests__/main.spec.ts
@@ -1,70 +1,9 @@
 import * as github from '@actions/github';
 import {Issue} from '../src/classes/issue';
-
 import {IssuesProcessor} from '../src/classes/issues-processor';
 import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options';
-import {IsoDateString} from '../src/types/iso-date-string';
-
-function generateIssue(
-  options: IIssuesProcessorOptions,
-  id: number,
-  title: string,
-  updatedAt: IsoDateString,
-  createdAt: IsoDateString = updatedAt,
-  isPullRequest = false,
-  labels: string[] = [],
-  isClosed = false,
-  isLocked = false,
-  milestone = ''
-): Issue {
-  return new Issue(options, {
-    number: id,
-    labels: labels.map(l => {
-      return {name: l};
-    }),
-    title,
-    created_at: createdAt,
-    updated_at: updatedAt,
-    pull_request: isPullRequest ? {} : null,
-    state: isClosed ? 'closed' : 'open',
-    locked: isLocked,
-    milestone: {
-      title: milestone
-    }
-  });
-}
-
-const DefaultProcessorOptions: IIssuesProcessorOptions = Object.freeze({
-  repoToken: 'none',
-  staleIssueMessage: 'This issue is stale',
-  stalePrMessage: 'This PR is stale',
-  closeIssueMessage: 'This issue is being closed',
-  closePrMessage: 'This PR is being closed',
-  daysBeforeStale: 1,
-  daysBeforeIssueStale: NaN,
-  daysBeforePrStale: NaN,
-  daysBeforeClose: 30,
-  daysBeforeIssueClose: NaN,
-  daysBeforePrClose: NaN,
-  staleIssueLabel: 'Stale',
-  closeIssueLabel: '',
-  exemptIssueLabels: '',
-  stalePrLabel: 'Stale',
-  closePrLabel: '',
-  exemptPrLabels: '',
-  onlyLabels: '',
-  operationsPerRun: 100,
-  debugOnly: true,
-  removeStaleWhenUpdated: false,
-  ascending: false,
-  skipStaleIssueMessage: false,
-  skipStalePrMessage: false,
-  deleteBranch: false,
-  startDate: '',
-  exemptMilestones: '',
-  exemptIssueMilestones: '',
-  exemptPrMilestones: ''
-});
+import {DefaultProcessorOptions} from './constants/default-processor-options';
+import {generateIssue} from './functions/generate-issue';
 
 test('empty issue list results in 1 operation', async () => {
   const processor = new IssuesProcessor(
@@ -1991,279 +1930,6 @@ test('an issue with an exempted milestone and with an exempted issue milestone w
   expect(processor.removedLabelIssues.length).toStrictEqual(0);
 });
 
-test('a PR without a milestone will be marked as stale', async () => {
-  expect.assertions(3);
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      DefaultProcessorOptions,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      ''
-    )
-  ];
-  const processor = new IssuesProcessor(
-    DefaultProcessorOptions,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(1);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR without an exempted milestone will be marked as stale', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(1);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone will not be marked as stale', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone1'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(0);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone will not be marked as stale (multi milestones with spaces)', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1, Milestone2';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone2'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(0);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone will not be marked as stale (multi milestones without spaces)', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1,Milestone2';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone2'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(0);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone but without an exempted issue milestone will not be marked as stale', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1';
-  opts.exemptPrMilestones = '';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone1'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(0);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone but with another exempted issue milestone will be marked as stale', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1';
-  opts.exemptPrMilestones = 'Milestone2';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone1'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(1);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
-test('a PR with an exempted milestone and with an exempted issue milestone will not be marked as stale', async () => {
-  expect.assertions(3);
-  const opts = {...DefaultProcessorOptions};
-  opts.exemptMilestones = 'Milestone1';
-  opts.exemptPrMilestones = 'Milestone1';
-  const TestIssueList: Issue[] = [
-    generateIssue(
-      opts,
-      1,
-      'My first issue',
-      '2020-01-01T17:00:00Z',
-      '2020-01-01T17:00:00Z',
-      true,
-      undefined,
-      undefined,
-      undefined,
-      'Milestone1'
-    )
-  ];
-  const processor = new IssuesProcessor(
-    opts,
-    async () => 'abot',
-    async p => (p == 1 ? TestIssueList : []),
-    async (num: number, dt: string) => [],
-    async (issue: Issue, label: string) => new Date().toDateString()
-  );
-
-  // process our fake issue list
-  await processor.processIssues(1);
-
-  expect(processor.staleIssues.length).toStrictEqual(0);
-  expect(processor.closedIssues.length).toStrictEqual(0);
-  expect(processor.removedLabelIssues.length).toStrictEqual(0);
-});
-
 test('processing an issue opened since 2 days and with the option "daysBeforeIssueStale" at 3 will not make it stale', async () => {
   expect.assertions(2);
   const opts: IIssuesProcessorOptions = {
diff --git a/__tests__/milestones.spec.ts b/__tests__/milestones.spec.ts
new file mode 100644
index 0000000..d19412d
--- /dev/null
+++ b/__tests__/milestones.spec.ts
@@ -0,0 +1,3413 @@
+import {Issue} from '../src/classes/issue';
+import {IssuesProcessor} from '../src/classes/issues-processor';
+import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options';
+import {DefaultProcessorOptions} from './constants/default-processor-options';
+import {generateIssue} from './functions/generate-issue';
+
+interface ITestData {
+  isPullRequest: boolean;
+  milestone: string;
+  name: string;
+  shouldStale: boolean;
+  exemptAllMilestones: boolean;
+}
+
+describe('milestones options', (): void => {
+  let opts: IIssuesProcessorOptions;
+  let testIssueList: Issue[];
+  let processor: IssuesProcessor;
+
+  const setTestIssueList = (
+    isPullRequest: boolean,
+    milestone: string | undefined
+  ) => {
+    testIssueList = [
+      generateIssue(
+        opts,
+        1,
+        'My first issue',
+        '2020-01-01T17:00:00Z',
+        '2020-01-01T17:00:00Z',
+        isPullRequest,
+        undefined,
+        undefined,
+        undefined,
+        milestone
+      )
+    ];
+  };
+
+  const setProcessor = () => {
+    processor = new IssuesProcessor(
+      opts,
+      async () => 'abot',
+      async p => (p === 1 ? testIssueList : []),
+      async () => [],
+      async () => new Date().toDateString()
+    );
+  };
+
+  beforeEach((): void => {
+    opts = {...DefaultProcessorOptions};
+  });
+
+  describe('when all the issues and pull requests milestones should not exempt', (): void => {
+    beforeEach((): void => {
+      opts.exemptAllMilestones = false;
+    });
+
+    describe.each`
+      isPullRequest | milestone            | name                                     | shouldStale
+      ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+      ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+      ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+      ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+    `(
+      'when $name',
+      ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+        beforeEach((): void => {
+          setTestIssueList(isPullRequest, milestone);
+          setProcessor();
+        });
+
+        test(`should${
+          shouldStale ? '' : ' not'
+        } be marked as stale`, async () => {
+          expect.assertions(3);
+
+          await processor.processIssues(1);
+
+          expect(processor.staleIssues.length).toStrictEqual(
+            shouldStale ? 1 : 0
+          );
+          expect(processor.closedIssues.length).toStrictEqual(0);
+          expect(processor.removedLabelIssues.length).toStrictEqual(0);
+        });
+      }
+    );
+
+    describe('when all the issues milestones are not configured to exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = undefined;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the issues milestones should not exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = false;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the issues milestones should exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = true;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones are not configured to exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = undefined;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones should not exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = false;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones should exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = true;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+  });
+
+  describe('when all the issues and pull requests milestones should exempt', (): void => {
+    beforeEach((): void => {
+      opts.exemptAllMilestones = true;
+    });
+
+    describe.each`
+      isPullRequest | milestone            | name                                     | shouldStale
+      ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+      ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+      ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+      ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+    `(
+      'when $name',
+      ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+        beforeEach((): void => {
+          setTestIssueList(isPullRequest, milestone);
+          setProcessor();
+        });
+
+        test(`should${
+          shouldStale ? '' : ' not'
+        } be marked as stale`, async () => {
+          expect.assertions(3);
+
+          await processor.processIssues(1);
+
+          expect(processor.staleIssues.length).toStrictEqual(
+            shouldStale ? 1 : 0
+          );
+          expect(processor.closedIssues.length).toStrictEqual(0);
+          expect(processor.removedLabelIssues.length).toStrictEqual(0);
+        });
+      }
+    );
+
+    describe('when all the issues milestones are not configured to exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = undefined;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the issues milestones should not exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = false;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${true}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${true}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${true}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${true}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${true}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${true}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the issues milestones should exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllIssueMilestones = true;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones are not configured to exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = undefined;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones should not exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = false;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${true}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${true}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${true}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${true}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${true}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${true}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+
+    describe('when all the pull requests milestones should exempt', (): void => {
+      beforeEach((): void => {
+        opts.exemptAllPrMilestones = true;
+      });
+
+      describe.each`
+        isPullRequest | milestone            | name                                     | shouldStale
+        ${false}      | ${''}                | ${'the issue does not have a milestone'} | ${true}
+        ${false}      | ${'dummy-milestone'} | ${'the issue does have a milestone'}     | ${false}
+        ${true}       | ${''}                | ${'the PR does not have a milestone'}    | ${true}
+        ${true}       | ${'dummy-milestone'} | ${'the PR does have a milestone'}        | ${false}
+      `(
+        'when $name',
+        ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+          beforeEach((): void => {
+            setTestIssueList(isPullRequest, milestone);
+            setProcessor();
+          });
+
+          test(`should${
+            shouldStale ? '' : ' not'
+          } be marked as stale`, async () => {
+            expect.assertions(3);
+
+            await processor.processIssues(1);
+
+            expect(processor.staleIssues.length).toStrictEqual(
+              shouldStale ? 1 : 0
+            );
+            expect(processor.closedIssues.length).toStrictEqual(0);
+            expect(processor.removedLabelIssues.length).toStrictEqual(0);
+          });
+        }
+      );
+
+      describe('when all the issues and pull requests milestones should exempt a specific milestone', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones = 'dummy-issue-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone'}        | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone'}        | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones = 'dummy-pull-request-milestone';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                         | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+
+      describe('when all the issues and pull requests milestones should exempt some milestones', (): void => {
+        beforeEach((): void => {
+          opts.exemptMilestones = 'dummy-milestone1, dummy-milestone2';
+        });
+
+        describe.each`
+          isPullRequest | milestone                         | name                                                                            | shouldStale
+          ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                        | ${true}
+          ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific exempted one'} | ${false}
+          ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}         | ${false}
+          ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                           | ${true}
+          ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific exempted one'}    | ${false}
+          ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}            | ${false}
+        `(
+          'when $name',
+          ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+            beforeEach((): void => {
+              setTestIssueList(isPullRequest, milestone);
+              setProcessor();
+            });
+
+            test(`should${
+              shouldStale ? '' : ' not'
+            } be marked as stale`, async () => {
+              expect.assertions(3);
+
+              await processor.processIssues(1);
+
+              expect(processor.staleIssues.length).toStrictEqual(
+                shouldStale ? 1 : 0
+              );
+              expect(processor.closedIssues.length).toStrictEqual(0);
+              expect(processor.removedLabelIssues.length).toStrictEqual(0);
+            });
+          }
+        );
+
+        describe('when all the issues milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptIssueMilestones =
+              'dummy-issue-milestone1, dummy-issue-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                         | name                                                                                  | shouldStale
+            ${false}      | ${''}                             | ${'the issue does not have a milestone'}                                              | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'} | ${'the issue does have a milestone but not matching the specific issue exempted one'} | ${false}
+            ${false}      | ${'dummy-issue-milestone2'}       | ${'the issue does have a milestone matching the specific issue exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}             | ${'the issue does have a milestone matching the specific exempted one'}               | ${false}
+            ${true}       | ${''}                             | ${'the PR does not have a milestone'}                                                 | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'} | ${'the PR does have a milestone but not matching the specific issue exempted one'}    | ${false}
+            ${true}       | ${'dummy-issue-milestone2'}       | ${'the PR does have a milestone matching the specific issue exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}             | ${'the PR does have a milestone matching the specific exempted one'}                  | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+
+        describe('when all the pull requests milestones should exempt a specific milestone', (): void => {
+          beforeEach((): void => {
+            opts.exemptPrMilestones =
+              'dummy-pull-request-milestone1, dummy-pull-request-milestone2';
+          });
+
+          describe.each`
+            isPullRequest | milestone                          | name                                                                                         | shouldStale
+            ${false}      | ${''}                              | ${'the issue does not have a milestone'}                                                     | ${true}
+            ${false}      | ${'dummy-milestone-not-exempted'}  | ${'the issue does have a milestone but not matching the specific pull request exempted one'} | ${false}
+            ${false}      | ${'dummy-pull-request-milestone2'} | ${'the issue does have a milestone matching the specific pull request exempted one'}         | ${false}
+            ${false}      | ${'dummy-milestone2'}              | ${'the issue does have a milestone matching the specific exempted one'}                      | ${false}
+            ${true}       | ${''}                              | ${'the PR does not have a milestone'}                                                        | ${true}
+            ${true}       | ${'dummy-milestone-not-exempted'}  | ${'the PR does have a milestone but not matching the specific pull request exempted one'}    | ${false}
+            ${true}       | ${'dummy-pull-request-milestone2'} | ${'the PR does have a milestone matching the specific pull request exempted one'}            | ${false}
+            ${true}       | ${'dummy-milestone2'}              | ${'the PR does have a milestone matching the specific exempted one'}                         | ${false}
+          `(
+            'when $name',
+            ({isPullRequest, milestone, shouldStale}: ITestData): void => {
+              beforeEach((): void => {
+                setTestIssueList(isPullRequest, milestone);
+                setProcessor();
+              });
+
+              test(`should${
+                shouldStale ? '' : ' not'
+              } be marked as stale`, async () => {
+                expect.assertions(3);
+
+                await processor.processIssues(1);
+
+                expect(processor.staleIssues.length).toStrictEqual(
+                  shouldStale ? 1 : 0
+                );
+                expect(processor.closedIssues.length).toStrictEqual(0);
+                expect(processor.removedLabelIssues.length).toStrictEqual(0);
+              });
+            }
+          );
+        });
+      });
+    });
+  });
+});