├── .circleci └── config.yml ├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── action.yml ├── bin └── automerge.js ├── dist ├── LICENSE └── index.js ├── docs └── screenshot.svg ├── eslint.config.mjs ├── it └── it.js ├── lib ├── api.js ├── common.js ├── git.js ├── merge.js ├── update.js └── util.js ├── package.json ├── test ├── api.test.js ├── common.js ├── common.test.js ├── git.test.js ├── merge.test.js ├── update.test.js └── util.test.js └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: cimg/node:20.10.0 6 | steps: 7 | - checkout 8 | - run: 9 | name: yarn 10 | command: yarn 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2019 Pascal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # automerge-action 2 | 3 | GitHub action to automatically merge pull requests when they are ready. 4 | 5 | 6 | 7 | When added, this action will run the following tasks on pull requests with the 8 | `automerge` label: 9 | 10 | - Changes from the base branch will automatically be merged into the pull 11 | request (only when "Require branches to be up to date before merging" 12 | is enabled in the branch protection rules) 13 | - When the pull request is ready, it will automatically be merged. The action 14 | will only wait for status checks that are marked as required in the branch 15 | protection rules 16 | - Pull requests without any configured labels will be ignored 17 | 18 | Labels, merge and update strategies are configurable, see [Configuration](#configuration). 19 | 20 | A pull request is considered ready when: 21 | 22 | 1. the required number of review approvals has been given (if enabled in the 23 | branch protection rules) and 24 | 2. the required checks have passed (if enabled in the branch protection rules) 25 | and 26 | 3. the pull request is up to date (if enabled in the branch protection rules) 27 | 28 | After the pull request has been merged successfully, the branch will _not_ be 29 | deleted. To delete branches after they are merged, 30 | see [automatic deletion of branches](https://help.github.com/en/articles/managing-the-automatic-deletion-of-branches). 31 | 32 | ---- 33 | 34 | **This functionality is now available directly in GitHub as [auto-merge](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/automatically-merging-a-pull-request).** Note that GitHub does not currently support auto-rebasing pull requests. The automerge-action project will still be maintained, but users are encouraged to switch to auto-merge for simple workflows, as it offers a faster and more stable experience. 35 | 36 | ## Usage 37 | 38 | Create a new `.github/workflows/automerge.yml` file: 39 | 40 | ```yaml 41 | name: automerge 42 | on: 43 | pull_request: 44 | types: 45 | - labeled 46 | - unlabeled 47 | - synchronize 48 | - opened 49 | - edited 50 | - ready_for_review 51 | - reopened 52 | - unlocked 53 | pull_request_review: 54 | types: 55 | - submitted 56 | check_suite: 57 | types: 58 | - completed 59 | status: {} 60 | jobs: 61 | automerge: 62 | runs-on: ubuntu-latest 63 | permissions: 64 | contents: write 65 | pull-requests: write 66 | steps: 67 | - id: automerge 68 | name: automerge 69 | uses: "pascalgn/automerge-action@v0.16.4" 70 | env: 71 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 72 | ``` 73 | 74 | For the latest version, see the [list of releases](https://github.com/pascalgn/automerge-action/releases). 75 | 76 | ## Configuration 77 | 78 | The following merge options are supported: 79 | 80 | - `MERGE_LABELS`: The labels that need to be present for a pull request to be 81 | merged (using `MERGE_METHOD`). The default value is `automerge`. 82 | 83 | This option can be a comma-separated list of labels that will be checked. All 84 | labels in the list need to be present, otherwise the pull request will be 85 | skipped (until all labels are present). Labels prefixed with an exclamation 86 | mark (`!`) will block a pull request from being merged, when present. 87 | 88 | For example, when `automerge,!wip,!work in progress` is given, 89 | any pull requests with the labels `wip` or `work in progress` and any pull 90 | requests _without_ the label `automerge` will not be merged. 91 | Blocking labels take precedence, so if a pull request has both labels 92 | `wip` and `automerge`, it will not be merged. 93 | 94 | When an empty string (`""`) is given, all pull requests will be merged. 95 | 96 | - `MERGE_REMOVE_LABELS`: The labels to automatically remove from a pull request 97 | once it has been merged by the action. The default value is `""`. 98 | 99 | This option can be a comma-separated list of labels that will be removed. 100 | 101 | When an empty string (`""`) is given, no labels will be removed. 102 | 103 | - `MERGE_METHOD`: Which method to use when merging the pull request into 104 | the base branch. Possible values are 105 | [`merge`](https://help.github.com/en/articles/about-pull-request-merges) (create a merge commit), 106 | [`rebase`](https://help.github.com/en/articles/about-pull-request-merges#rebase-and-merge-your-pull-request-commits) 107 | (rebase all commits of the branch onto the base branch) 108 | or [`squash`](https://help.github.com/en/articles/about-pull-request-merges#squash-and-merge-your-pull-request-commits) 109 | (squash all commits into a single commit). The default option is `merge`. 110 | 111 | - `MERGE_METHOD_LABELS`: Set to allow labels to determine the merge method 112 | (see `MERGE_METHOD` for possible values). 113 | For example, `automerge=merge,autosquash=squash`. If no such label is present, 114 | the method set by `MERGE_METHOD` will be used. The default value is `""`. 115 | 116 | - `MERGE_METHOD_LABEL_REQUIRED`: Set to `"true"` to require one of the 117 | `MERGE_METHOD_LABELS` to be set. The default value is `"false"`. 118 | 119 | - `MERGE_COMMIT_MESSAGE`: The commit message to use when merging the pull 120 | request into the base branch. Possible values are `automatic` (use GitHub's 121 | default message), `pull-request-title` (use the pull request's title), 122 | `pull-request-description` (use the pull request's description), 123 | `pull-request-title-and-description` or a literal 124 | value with optional placeholders (for example `Auto merge {pullRequest.number}`). 125 | The default value is `automatic`. 126 | 127 | - `MERGE_COMMIT_MESSAGE_REGEX`: When using a commit message containing the 128 | PR's body, use the first capturing subgroup from this regex as the commit 129 | message. Can be used to separate content that should go with the commit into 130 | the code base's history from boilerplate associated with the PR (licensing 131 | notices, check lists, etc). For example, `(.*)^---` would keep everything up 132 | until the first 3-dash line (horizontal rule in MarkDown) from the commit 133 | message. The default value is empty, which disables this feature. 134 | 135 | - `MERGE_FILTER_AUTHOR`: When set, only pull requests raised by this author 136 | will be merged automatically. 137 | 138 | - `MERGE_FORKS`: Whether merging from external repositories is enabled 139 | or not. By default, pull requests with branches from forked repositories will 140 | be merged the same way as pull requests with branches from the main 141 | repository. Set this option to `"false"` to disable merging of pull requests 142 | from forked repositories. The default value is `"true"`. 143 | 144 | - `MERGE_RETRIES` and `MERGE_RETRY_SLEEP`: Sometimes, the pull request check 145 | runs haven't finished yet, so the action will retry the merge after some time. 146 | The number of retries can be set with `MERGE_RETRIES`. 147 | The default number of retries is `6` and setting it to `0` disables the retry logic. 148 | `MERGE_RETRY_SLEEP` sets the time to sleep between retries, in milliseconds. 149 | The default is `5000` (5 seconds) and setting it to `0` disables sleeping 150 | between retries. 151 | 152 | - `MERGE_REQUIRED_APPROVALS`: Count of required approvals. The default is `0`. 153 | 154 | - `MERGE_DELETE_BRANCH`: Automatic deletion of branches does not work for all 155 | repositories. Set this option to `"true"` to automatically delete branches 156 | after they have been merged. The default value is `"false"`. 157 | 158 | - `MERGE_DELETE_BRANCH_FILTER`: A comma-separated list of branches that will not 159 | be deleted. This is not the list of GitHub's protected branches, which are never 160 | deleted, but an additional list of branches to protect. The default value is `""`. 161 | 162 | - `MERGE_ERROR_FAIL`: Set this to `"true"` to have the action exit with error code `1` 163 | when the pull request could not be merged successfully during a run. 164 | 165 | - `MERGE_READY_STATE`: The state(s) of a pull request for which to attempt a 166 | merge. This option can be a comma-separated list of states that will be considered mergeable. 167 | The default value is `clean,has_hooks,unknown,unstable`. 168 | 169 | The following update options are supported: 170 | 171 | - `UPDATE_LABELS`: The labels that need to be present for a pull request to be 172 | updated (using `UPDATE_METHOD`). The default value is `automerge`. 173 | 174 | Note that updating will only happen when the option "Require branches to be 175 | up to date before merging" is enabled in the branch protection rules. 176 | 177 | This option can be a comma-separated list of labels, see the `MERGE_LABELS` 178 | option for more information. 179 | 180 | - `UPDATE_METHOD`: Which method to use when updating the pull request 181 | to the base branch. Possible values are `merge` (create a merge commit) or 182 | `rebase` (rebase the branch onto the head of the base branch). The default 183 | option is `merge`. 184 | 185 | When the option is `rebase` and the [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) 186 | failed, the action will exit with error code 1. This will also be visible 187 | in the pull request page, with a message like "this branch has conflicts 188 | that must be resolved" and a list of conflicting files. 189 | 190 | - `UPDATE_RETRIES` and `UPDATE_RETRY_SLEEP`: Sometimes, the pull request check 191 | runs haven't finished yet and the action doesn't know if an update is 192 | necessary. To query the pull request state multiple times, the number of 193 | retries can be set with `UPDATE_RETRIES`. The default number of retries is `1` 194 | and setting it to `0` disables the retry logic. 195 | `UPDATE_RETRY_SLEEP` sets the time to sleep between retries, in milliseconds. 196 | The default is `5000` (5 seconds) and setting it to `0` disables sleeping 197 | between retries. 198 | 199 | Also, the following general options are supported: 200 | 201 | - `GITHUB_TOKEN`: This should always be `"${{ secrets.GITHUB_TOKEN }}"`. 202 | However, in some cases it can be useful to run this action as a certain user 203 | (by default, it will run as `github-actions`). This can be useful if you want 204 | to use the "Restrict who can push to matching branches" option in the branch 205 | protection rules, for example. 206 | 207 | To use this setting for manually providing a token, you need to create a 208 | [personal access token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) 209 | for the user (make sure to check `public_repo` when it's a public repository 210 | or `repo` when it's a private repository). All API requests (merge/rebase) 211 | will then be executed as the specified user. The token should be kept secret, 212 | so make sure to add it as secret, not as environment variable, in the GitHub 213 | workflow file! 214 | 215 | - `PULL_REQUEST`: If provided, this action will attempt to merge the specified pull request. By default, it will attempt to use the pull request specified in the GitHub context. If a pull request number is provided via this input, this action will search in the current repo for the provided pull request number. If you want to merge a pull request in another repo, just provide the repo slug before the pull request number, like `Some-Org/Some-Repo/1234` 216 | 217 | - `BASE_BRANCHES`: If provided, the action will be restricted in terms of base branches. Can be comma-separated list of simple branch names (i.e `main,dev`). 218 | 219 | - `MAX_PR_COUNT`: If provided, will control how many GitHub pull requests are considered in a single run. The default is `10`. 220 | 221 | You can configure the environment variables in the workflow file like this: 222 | 223 | ```yaml 224 | env: 225 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 226 | MERGE_LABELS: "automerge,!work in progress" 227 | MERGE_REMOVE_LABELS: "automerge" 228 | MERGE_METHOD: "squash" 229 | MERGE_COMMIT_MESSAGE: "pull-request-description" 230 | MERGE_FORKS: "false" 231 | MERGE_RETRIES: "6" 232 | MERGE_RETRY_SLEEP: "10000" 233 | MERGE_REQUIRED_APPROVALS: "0" 234 | UPDATE_LABELS: "" 235 | UPDATE_METHOD: "rebase" 236 | PULL_REQUEST: "1234" 237 | MAX_PR_COUNT: "25" 238 | ``` 239 | 240 | ## Supported Events 241 | 242 | Automerge can be configured to run for these events: 243 | 244 | * `check_run` 245 | * `check_suite` 246 | * `issue_comment` 247 | * `pull_request_review` 248 | * `pull_request_target` 249 | * `pull_request` 250 | * `push` 251 | * `repository_dispatch` 252 | * `schedule` 253 | * `status` 254 | * `workflow_dispatch` 255 | * `workflow_run` 256 | 257 | For more information on when these occur, see the Github documentation on [events that trigger workflows](https://docs.github.com/en/actions/reference/events-that-trigger-workflows) and [their payloads](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads). 258 | 259 | ## Outputs 260 | 261 | The action will provide two [outputs](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs): 262 | 263 | * `mergeResult` - The result from the action run, one of `skipped`, `not_ready`, `author_filtered`, `merge_failed`, `merged` 264 | * `pullRequestNumber` - The pull request number (or `0`, if no pull request was affected) 265 | 266 | Please note: 267 | 268 | 1. When there are multiple pull requests affected, only the first one will be available in the output 269 | 2. To access these outputs, your workflow configuration must define an `id` for the automerge-action step 270 | 3. Unless a personal access token is used, this action will not trigger other actions, see [Limitations](#limitations) 271 | 272 | Example usage: 273 | 274 | ```yaml 275 | steps: 276 | - id: automerge 277 | name: automerge 278 | uses: "pascalgn/automerge-action@v0.15.6" 279 | env: 280 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 281 | - name: feedback 282 | if: ${{ steps.automerge.outputs.mergeResult == 'merged' }} 283 | run: | 284 | echo "Pull request ${{ steps.automerge.outputs.pullRequestNumber }} merged!" 285 | ``` 286 | 287 | ## Limitations 288 | 289 | - When a pull request is merged by this action, the merge will not trigger other GitHub workflows. 290 | Similarly, when another GitHub workflow creates a pull request, this action will not be triggered. 291 | This is because [an action in a workflow run can't trigger a new workflow run](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows). However, the [`workflow_run`](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_run) event is triggered as expected. 292 | - When [using a personal access token (PAT) to work around the above limitation](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token), note that when the user issuing the PAT is an administrator and [branch restrictions do not include administrators](https://help.github.com/en/github/administering-a-repository/enabling-branch-restrictions), pull requests may be merged even if they are not mergeable for non-administrators (see [#65](https://github.com/pascalgn/automerge-action/issues/65)). 293 | - Currently, there is no way to trigger workflows when the pull request branch 294 | becomes out of date with the base branch. There is a request in the 295 | [GitHub community forum](https://github.community/t5/GitHub-Actions/New-Trigger-is-mergable-state/m-p/36908). 296 | 297 | ## Debugging 298 | 299 | To run the action with full debug logging, update your workflow file as follows: 300 | 301 | ```yaml 302 | - name: automerge 303 | uses: pascalgn/automerge-action@... 304 | env: 305 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 306 | LOG: "TRACE" # or "DEBUG" 307 | ``` 308 | 309 | If you need to further debug the action, you can run it locally. 310 | 311 | You will need a [personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). 312 | 313 | Then clone this repository, create a file `.env` in the repository, such as: 314 | 315 | ``` 316 | GITHUB_TOKEN="123abc..." 317 | URL="https://github.com/pascalgn/repository-name/pull/123" 318 | ``` 319 | 320 | Install dependencies with `yarn`, and finally run `yarn it` (or `npm run it`). 321 | 322 | ## License 323 | 324 | [MIT](./LICENSE) 325 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "Merge pull requests (automerge-action)" 2 | description: "Automatically merge pull requests that are ready" 3 | runs: 4 | using: "node20" 5 | main: "dist/index.js" 6 | branding: 7 | icon: "git-pull-request" 8 | color: "blue" 9 | -------------------------------------------------------------------------------- /bin/automerge.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const process = require("process"); 4 | 5 | const fse = require("fs-extra"); 6 | const { ArgumentParser } = require("argparse"); 7 | const { Octokit } = require("@octokit/rest"); 8 | 9 | const { ClientError, logger, createConfig } = require("../lib/common"); 10 | const { executeLocally, executeGitHubAction } = require("../lib/api"); 11 | 12 | const pkg = require("../package.json"); 13 | 14 | const OLD_CONFIG = [ 15 | "MERGE_LABEL", 16 | "UPDATE_LABEL", 17 | "LABELS", 18 | "AUTOMERGE", 19 | "AUTOREBASE", 20 | "COMMIT_MESSAGE_TEMPLATE", 21 | "TOKEN" 22 | ]; 23 | 24 | const GITHUB_API_URL = process.env.GITHUB_API_URL || "https://api.github.com"; 25 | 26 | async function main() { 27 | const parser = new ArgumentParser({ 28 | prog: pkg.name, 29 | add_help: true, 30 | description: pkg.description 31 | }); 32 | parser.add_argument("-v", "--version", { 33 | action: "version", 34 | version: pkg.version, 35 | help: "Show version number and exit" 36 | }); 37 | parser.add_argument("url", { 38 | metavar: "", 39 | nargs: "?", 40 | help: "GitHub URL to process instead of environment variables" 41 | }); 42 | 43 | const args = parser.parse_args(); 44 | 45 | if (process.env.LOG === "TRACE") { 46 | logger.level = "trace"; 47 | } else if (process.env.LOG === "DEBUG") { 48 | logger.level = "debug"; 49 | } else if (process.env.LOG && process.env.LOG.length > 0) { 50 | logger.error("Invalid log level:", process.env.LOG); 51 | } 52 | 53 | checkOldConfig(); 54 | 55 | const token = env("GITHUB_TOKEN"); 56 | 57 | const octokit = new Octokit({ 58 | baseUrl: GITHUB_API_URL, 59 | auth: `token ${token}`, 60 | userAgent: "pascalgn/automerge-action" 61 | }); 62 | 63 | const config = createConfig(process.env); 64 | logger.debug("Configuration:", config); 65 | 66 | const context = { token, octokit, config }; 67 | 68 | if (args.url) { 69 | await executeLocally(context, args.url); 70 | } else { 71 | const eventPath = env("GITHUB_EVENT_PATH"); 72 | const eventName = env("GITHUB_EVENT_NAME"); 73 | 74 | const eventDataStr = await fse.readFile(eventPath, "utf8"); 75 | const eventData = JSON.parse(eventDataStr); 76 | 77 | await executeGitHubAction(context, eventName, eventData); 78 | } 79 | } 80 | 81 | function checkOldConfig() { 82 | let error = false; 83 | for (const old of OLD_CONFIG) { 84 | if (process.env[old] != null) { 85 | logger.error("Old configuration option present:", old); 86 | error = true; 87 | } 88 | } 89 | if (error) { 90 | logger.error( 91 | "You have passed configuration options that were used by an old " + 92 | "version of this action. Please see " + 93 | "https://github.com/pascalgn/automerge-action for the latest " + 94 | "documentation of the configuration options!" 95 | ); 96 | throw new Error(`old configuration present!`); 97 | } 98 | } 99 | 100 | function env(name) { 101 | const val = process.env[name]; 102 | if (!val || !val.length) { 103 | throw new ClientError(`environment variable ${name} not set!`); 104 | } 105 | return val; 106 | } 107 | 108 | if (require.main === module) { 109 | main().catch(e => { 110 | if (e instanceof ClientError) { 111 | process.exitCode = 2; 112 | logger.error(e); 113 | } else { 114 | process.exitCode = 1; 115 | logger.error(e); 116 | } 117 | }); 118 | } 119 | -------------------------------------------------------------------------------- /dist/LICENSE: -------------------------------------------------------------------------------- 1 | @actions/core 2 | MIT 3 | The MIT License (MIT) 4 | 5 | Copyright 2019 GitHub 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | 13 | @actions/http-client 14 | MIT 15 | Actions Http Client for Node.js 16 | 17 | Copyright (c) GitHub, Inc. 18 | 19 | All rights reserved. 20 | 21 | MIT License 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 24 | associated documentation files (the "Software"), to deal in the Software without restriction, 25 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 26 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 27 | subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 32 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 33 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 34 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 35 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | 38 | @fastify/busboy 39 | MIT 40 | Copyright Brian White. All rights reserved. 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to 44 | deal in the Software without restriction, including without limitation the 45 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 46 | sell copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in 50 | all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 57 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 58 | IN THE SOFTWARE. 59 | 60 | @octokit/auth-token 61 | MIT 62 | The MIT License 63 | 64 | Copyright (c) 2019 Octokit contributors 65 | 66 | Permission is hereby granted, free of charge, to any person obtaining a copy 67 | of this software and associated documentation files (the "Software"), to deal 68 | in the Software without restriction, including without limitation the rights 69 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 70 | copies of the Software, and to permit persons to whom the Software is 71 | furnished to do so, subject to the following conditions: 72 | 73 | The above copyright notice and this permission notice shall be included in 74 | all copies or substantial portions of the Software. 75 | 76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 77 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 78 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 79 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 80 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 81 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 82 | THE SOFTWARE. 83 | 84 | 85 | @octokit/core 86 | MIT 87 | The MIT License 88 | 89 | Copyright (c) 2019 Octokit contributors 90 | 91 | Permission is hereby granted, free of charge, to any person obtaining a copy 92 | of this software and associated documentation files (the "Software"), to deal 93 | in the Software without restriction, including without limitation the rights 94 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 95 | copies of the Software, and to permit persons to whom the Software is 96 | furnished to do so, subject to the following conditions: 97 | 98 | The above copyright notice and this permission notice shall be included in 99 | all copies or substantial portions of the Software. 100 | 101 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 102 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 103 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 104 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 105 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 106 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 107 | THE SOFTWARE. 108 | 109 | 110 | @octokit/endpoint 111 | MIT 112 | The MIT License 113 | 114 | Copyright (c) 2018 Octokit contributors 115 | 116 | Permission is hereby granted, free of charge, to any person obtaining a copy 117 | of this software and associated documentation files (the "Software"), to deal 118 | in the Software without restriction, including without limitation the rights 119 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 120 | copies of the Software, and to permit persons to whom the Software is 121 | furnished to do so, subject to the following conditions: 122 | 123 | The above copyright notice and this permission notice shall be included in 124 | all copies or substantial portions of the Software. 125 | 126 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 127 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 128 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 129 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 130 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 131 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 132 | THE SOFTWARE. 133 | 134 | 135 | @octokit/graphql 136 | MIT 137 | The MIT License 138 | 139 | Copyright (c) 2018 Octokit contributors 140 | 141 | Permission is hereby granted, free of charge, to any person obtaining a copy 142 | of this software and associated documentation files (the "Software"), to deal 143 | in the Software without restriction, including without limitation the rights 144 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 145 | copies of the Software, and to permit persons to whom the Software is 146 | furnished to do so, subject to the following conditions: 147 | 148 | The above copyright notice and this permission notice shall be included in 149 | all copies or substantial portions of the Software. 150 | 151 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 152 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 153 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 154 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 155 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 156 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 157 | THE SOFTWARE. 158 | 159 | 160 | @octokit/plugin-paginate-rest 161 | MIT 162 | MIT License Copyright (c) 2019 Octokit contributors 163 | 164 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 165 | 166 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 167 | 168 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 169 | 170 | 171 | @octokit/plugin-request-log 172 | MIT 173 | MIT License Copyright (c) 2020 Octokit contributors 174 | 175 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 176 | 177 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 178 | 179 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 180 | 181 | 182 | @octokit/plugin-rest-endpoint-methods 183 | MIT 184 | MIT License Copyright (c) 2019 Octokit contributors 185 | 186 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 187 | 188 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 189 | 190 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 191 | 192 | 193 | @octokit/request 194 | MIT 195 | The MIT License 196 | 197 | Copyright (c) 2018 Octokit contributors 198 | 199 | Permission is hereby granted, free of charge, to any person obtaining a copy 200 | of this software and associated documentation files (the "Software"), to deal 201 | in the Software without restriction, including without limitation the rights 202 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 203 | copies of the Software, and to permit persons to whom the Software is 204 | furnished to do so, subject to the following conditions: 205 | 206 | The above copyright notice and this permission notice shall be included in 207 | all copies or substantial portions of the Software. 208 | 209 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 210 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 211 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 212 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 213 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 214 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 215 | THE SOFTWARE. 216 | 217 | 218 | @octokit/request-error 219 | MIT 220 | The MIT License 221 | 222 | Copyright (c) 2019 Octokit contributors 223 | 224 | Permission is hereby granted, free of charge, to any person obtaining a copy 225 | of this software and associated documentation files (the "Software"), to deal 226 | in the Software without restriction, including without limitation the rights 227 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 228 | copies of the Software, and to permit persons to whom the Software is 229 | furnished to do so, subject to the following conditions: 230 | 231 | The above copyright notice and this permission notice shall be included in 232 | all copies or substantial portions of the Software. 233 | 234 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 235 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 236 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 237 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 238 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 239 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 240 | THE SOFTWARE. 241 | 242 | 243 | @octokit/rest 244 | MIT 245 | The MIT License 246 | 247 | Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer) 248 | Copyright (c) 2017-2018 Octokit contributors 249 | 250 | Permission is hereby granted, free of charge, to any person obtaining a copy 251 | of this software and associated documentation files (the "Software"), to deal 252 | in the Software without restriction, including without limitation the rights 253 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 254 | copies of the Software, and to permit persons to whom the Software is 255 | furnished to do so, subject to the following conditions: 256 | 257 | The above copyright notice and this permission notice shall be included in 258 | all copies or substantial portions of the Software. 259 | 260 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 261 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 262 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 263 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 264 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 265 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 266 | THE SOFTWARE. 267 | 268 | 269 | argparse 270 | Python-2.0 271 | A. HISTORY OF THE SOFTWARE 272 | ========================== 273 | 274 | Python was created in the early 1990s by Guido van Rossum at Stichting 275 | Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands 276 | as a successor of a language called ABC. Guido remains Python's 277 | principal author, although it includes many contributions from others. 278 | 279 | In 1995, Guido continued his work on Python at the Corporation for 280 | National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) 281 | in Reston, Virginia where he released several versions of the 282 | software. 283 | 284 | In May 2000, Guido and the Python core development team moved to 285 | BeOpen.com to form the BeOpen PythonLabs team. In October of the same 286 | year, the PythonLabs team moved to Digital Creations, which became 287 | Zope Corporation. In 2001, the Python Software Foundation (PSF, see 288 | https://www.python.org/psf/) was formed, a non-profit organization 289 | created specifically to own Python-related Intellectual Property. 290 | Zope Corporation was a sponsoring member of the PSF. 291 | 292 | All Python releases are Open Source (see http://www.opensource.org for 293 | the Open Source Definition). Historically, most, but not all, Python 294 | releases have also been GPL-compatible; the table below summarizes 295 | the various releases. 296 | 297 | Release Derived Year Owner GPL- 298 | from compatible? (1) 299 | 300 | 0.9.0 thru 1.2 1991-1995 CWI yes 301 | 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes 302 | 1.6 1.5.2 2000 CNRI no 303 | 2.0 1.6 2000 BeOpen.com no 304 | 1.6.1 1.6 2001 CNRI yes (2) 305 | 2.1 2.0+1.6.1 2001 PSF no 306 | 2.0.1 2.0+1.6.1 2001 PSF yes 307 | 2.1.1 2.1+2.0.1 2001 PSF yes 308 | 2.1.2 2.1.1 2002 PSF yes 309 | 2.1.3 2.1.2 2002 PSF yes 310 | 2.2 and above 2.1.1 2001-now PSF yes 311 | 312 | Footnotes: 313 | 314 | (1) GPL-compatible doesn't mean that we're distributing Python under 315 | the GPL. All Python licenses, unlike the GPL, let you distribute 316 | a modified version without making your changes open source. The 317 | GPL-compatible licenses make it possible to combine Python with 318 | other software that is released under the GPL; the others don't. 319 | 320 | (2) According to Richard Stallman, 1.6.1 is not GPL-compatible, 321 | because its license has a choice of law clause. According to 322 | CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 323 | is "not incompatible" with the GPL. 324 | 325 | Thanks to the many outside volunteers who have worked under Guido's 326 | direction to make these releases possible. 327 | 328 | 329 | B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON 330 | =============================================================== 331 | 332 | PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 333 | -------------------------------------------- 334 | 335 | 1. This LICENSE AGREEMENT is between the Python Software Foundation 336 | ("PSF"), and the Individual or Organization ("Licensee") accessing and 337 | otherwise using this software ("Python") in source or binary form and 338 | its associated documentation. 339 | 340 | 2. Subject to the terms and conditions of this License Agreement, PSF hereby 341 | grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, 342 | analyze, test, perform and/or display publicly, prepare derivative works, 343 | distribute, and otherwise use Python alone or in any derivative version, 344 | provided, however, that PSF's License Agreement and PSF's notice of copyright, 345 | i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 346 | 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation; 347 | All Rights Reserved" are retained in Python alone or in any derivative version 348 | prepared by Licensee. 349 | 350 | 3. In the event Licensee prepares a derivative work that is based on 351 | or incorporates Python or any part thereof, and wants to make 352 | the derivative work available to others as provided herein, then 353 | Licensee hereby agrees to include in any such work a brief summary of 354 | the changes made to Python. 355 | 356 | 4. PSF is making Python available to Licensee on an "AS IS" 357 | basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 358 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND 359 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 360 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT 361 | INFRINGE ANY THIRD PARTY RIGHTS. 362 | 363 | 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 364 | FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 365 | A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, 366 | OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 367 | 368 | 6. This License Agreement will automatically terminate upon a material 369 | breach of its terms and conditions. 370 | 371 | 7. Nothing in this License Agreement shall be deemed to create any 372 | relationship of agency, partnership, or joint venture between PSF and 373 | Licensee. This License Agreement does not grant permission to use PSF 374 | trademarks or trade name in a trademark sense to endorse or promote 375 | products or services of Licensee, or any third party. 376 | 377 | 8. By copying, installing or otherwise using Python, Licensee 378 | agrees to be bound by the terms and conditions of this License 379 | Agreement. 380 | 381 | 382 | BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 383 | ------------------------------------------- 384 | 385 | BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 386 | 387 | 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an 388 | office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the 389 | Individual or Organization ("Licensee") accessing and otherwise using 390 | this software in source or binary form and its associated 391 | documentation ("the Software"). 392 | 393 | 2. Subject to the terms and conditions of this BeOpen Python License 394 | Agreement, BeOpen hereby grants Licensee a non-exclusive, 395 | royalty-free, world-wide license to reproduce, analyze, test, perform 396 | and/or display publicly, prepare derivative works, distribute, and 397 | otherwise use the Software alone or in any derivative version, 398 | provided, however, that the BeOpen Python License is retained in the 399 | Software, alone or in any derivative version prepared by Licensee. 400 | 401 | 3. BeOpen is making the Software available to Licensee on an "AS IS" 402 | basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 403 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND 404 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 405 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT 406 | INFRINGE ANY THIRD PARTY RIGHTS. 407 | 408 | 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE 409 | SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS 410 | AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY 411 | DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 412 | 413 | 5. This License Agreement will automatically terminate upon a material 414 | breach of its terms and conditions. 415 | 416 | 6. This License Agreement shall be governed by and interpreted in all 417 | respects by the law of the State of California, excluding conflict of 418 | law provisions. Nothing in this License Agreement shall be deemed to 419 | create any relationship of agency, partnership, or joint venture 420 | between BeOpen and Licensee. This License Agreement does not grant 421 | permission to use BeOpen trademarks or trade names in a trademark 422 | sense to endorse or promote products or services of Licensee, or any 423 | third party. As an exception, the "BeOpen Python" logos available at 424 | http://www.pythonlabs.com/logos.html may be used according to the 425 | permissions granted on that web page. 426 | 427 | 7. By copying, installing or otherwise using the software, Licensee 428 | agrees to be bound by the terms and conditions of this License 429 | Agreement. 430 | 431 | 432 | CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 433 | --------------------------------------- 434 | 435 | 1. This LICENSE AGREEMENT is between the Corporation for National 436 | Research Initiatives, having an office at 1895 Preston White Drive, 437 | Reston, VA 20191 ("CNRI"), and the Individual or Organization 438 | ("Licensee") accessing and otherwise using Python 1.6.1 software in 439 | source or binary form and its associated documentation. 440 | 441 | 2. Subject to the terms and conditions of this License Agreement, CNRI 442 | hereby grants Licensee a nonexclusive, royalty-free, world-wide 443 | license to reproduce, analyze, test, perform and/or display publicly, 444 | prepare derivative works, distribute, and otherwise use Python 1.6.1 445 | alone or in any derivative version, provided, however, that CNRI's 446 | License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 447 | 1995-2001 Corporation for National Research Initiatives; All Rights 448 | Reserved" are retained in Python 1.6.1 alone or in any derivative 449 | version prepared by Licensee. Alternately, in lieu of CNRI's License 450 | Agreement, Licensee may substitute the following text (omitting the 451 | quotes): "Python 1.6.1 is made available subject to the terms and 452 | conditions in CNRI's License Agreement. This Agreement together with 453 | Python 1.6.1 may be located on the Internet using the following 454 | unique, persistent identifier (known as a handle): 1895.22/1013. This 455 | Agreement may also be obtained from a proxy server on the Internet 456 | using the following URL: http://hdl.handle.net/1895.22/1013". 457 | 458 | 3. In the event Licensee prepares a derivative work that is based on 459 | or incorporates Python 1.6.1 or any part thereof, and wants to make 460 | the derivative work available to others as provided herein, then 461 | Licensee hereby agrees to include in any such work a brief summary of 462 | the changes made to Python 1.6.1. 463 | 464 | 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" 465 | basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 466 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND 467 | DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 468 | FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT 469 | INFRINGE ANY THIRD PARTY RIGHTS. 470 | 471 | 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 472 | 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 473 | A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, 474 | OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 475 | 476 | 6. This License Agreement will automatically terminate upon a material 477 | breach of its terms and conditions. 478 | 479 | 7. This License Agreement shall be governed by the federal 480 | intellectual property law of the United States, including without 481 | limitation the federal copyright law, and, to the extent such 482 | U.S. federal law does not apply, by the law of the Commonwealth of 483 | Virginia, excluding Virginia's conflict of law provisions. 484 | Notwithstanding the foregoing, with regard to derivative works based 485 | on Python 1.6.1 that incorporate non-separable material that was 486 | previously distributed under the GNU General Public License (GPL), the 487 | law of the Commonwealth of Virginia shall govern this License 488 | Agreement only as to issues arising under or with respect to 489 | Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this 490 | License Agreement shall be deemed to create any relationship of 491 | agency, partnership, or joint venture between CNRI and Licensee. This 492 | License Agreement does not grant permission to use CNRI trademarks or 493 | trade name in a trademark sense to endorse or promote products or 494 | services of Licensee, or any third party. 495 | 496 | 8. By clicking on the "ACCEPT" button where indicated, or by copying, 497 | installing or otherwise using Python 1.6.1, Licensee agrees to be 498 | bound by the terms and conditions of this License Agreement. 499 | 500 | ACCEPT 501 | 502 | 503 | CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 504 | -------------------------------------------------- 505 | 506 | Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, 507 | The Netherlands. All rights reserved. 508 | 509 | Permission to use, copy, modify, and distribute this software and its 510 | documentation for any purpose and without fee is hereby granted, 511 | provided that the above copyright notice appear in all copies and that 512 | both that copyright notice and this permission notice appear in 513 | supporting documentation, and that the name of Stichting Mathematisch 514 | Centrum or CWI not be used in advertising or publicity pertaining to 515 | distribution of the software without specific, written prior 516 | permission. 517 | 518 | STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO 519 | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 520 | FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE 521 | FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 522 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 523 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 524 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 525 | 526 | 527 | before-after-hook 528 | Apache-2.0 529 | Apache License 530 | Version 2.0, January 2004 531 | http://www.apache.org/licenses/ 532 | 533 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 534 | 535 | 1. Definitions. 536 | 537 | "License" shall mean the terms and conditions for use, reproduction, 538 | and distribution as defined by Sections 1 through 9 of this document. 539 | 540 | "Licensor" shall mean the copyright owner or entity authorized by 541 | the copyright owner that is granting the License. 542 | 543 | "Legal Entity" shall mean the union of the acting entity and all 544 | other entities that control, are controlled by, or are under common 545 | control with that entity. For the purposes of this definition, 546 | "control" means (i) the power, direct or indirect, to cause the 547 | direction or management of such entity, whether by contract or 548 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 549 | outstanding shares, or (iii) beneficial ownership of such entity. 550 | 551 | "You" (or "Your") shall mean an individual or Legal Entity 552 | exercising permissions granted by this License. 553 | 554 | "Source" form shall mean the preferred form for making modifications, 555 | including but not limited to software source code, documentation 556 | source, and configuration files. 557 | 558 | "Object" form shall mean any form resulting from mechanical 559 | transformation or translation of a Source form, including but 560 | not limited to compiled object code, generated documentation, 561 | and conversions to other media types. 562 | 563 | "Work" shall mean the work of authorship, whether in Source or 564 | Object form, made available under the License, as indicated by a 565 | copyright notice that is included in or attached to the work 566 | (an example is provided in the Appendix below). 567 | 568 | "Derivative Works" shall mean any work, whether in Source or Object 569 | form, that is based on (or derived from) the Work and for which the 570 | editorial revisions, annotations, elaborations, or other modifications 571 | represent, as a whole, an original work of authorship. For the purposes 572 | of this License, Derivative Works shall not include works that remain 573 | separable from, or merely link (or bind by name) to the interfaces of, 574 | the Work and Derivative Works thereof. 575 | 576 | "Contribution" shall mean any work of authorship, including 577 | the original version of the Work and any modifications or additions 578 | to that Work or Derivative Works thereof, that is intentionally 579 | submitted to Licensor for inclusion in the Work by the copyright owner 580 | or by an individual or Legal Entity authorized to submit on behalf of 581 | the copyright owner. For the purposes of this definition, "submitted" 582 | means any form of electronic, verbal, or written communication sent 583 | to the Licensor or its representatives, including but not limited to 584 | communication on electronic mailing lists, source code control systems, 585 | and issue tracking systems that are managed by, or on behalf of, the 586 | Licensor for the purpose of discussing and improving the Work, but 587 | excluding communication that is conspicuously marked or otherwise 588 | designated in writing by the copyright owner as "Not a Contribution." 589 | 590 | "Contributor" shall mean Licensor and any individual or Legal Entity 591 | on behalf of whom a Contribution has been received by Licensor and 592 | subsequently incorporated within the Work. 593 | 594 | 2. Grant of Copyright License. Subject to the terms and conditions of 595 | this License, each Contributor hereby grants to You a perpetual, 596 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 597 | copyright license to reproduce, prepare Derivative Works of, 598 | publicly display, publicly perform, sublicense, and distribute the 599 | Work and such Derivative Works in Source or Object form. 600 | 601 | 3. Grant of Patent License. Subject to the terms and conditions of 602 | this License, each Contributor hereby grants to You a perpetual, 603 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 604 | (except as stated in this section) patent license to make, have made, 605 | use, offer to sell, sell, import, and otherwise transfer the Work, 606 | where such license applies only to those patent claims licensable 607 | by such Contributor that are necessarily infringed by their 608 | Contribution(s) alone or by combination of their Contribution(s) 609 | with the Work to which such Contribution(s) was submitted. If You 610 | institute patent litigation against any entity (including a 611 | cross-claim or counterclaim in a lawsuit) alleging that the Work 612 | or a Contribution incorporated within the Work constitutes direct 613 | or contributory patent infringement, then any patent licenses 614 | granted to You under this License for that Work shall terminate 615 | as of the date such litigation is filed. 616 | 617 | 4. Redistribution. You may reproduce and distribute copies of the 618 | Work or Derivative Works thereof in any medium, with or without 619 | modifications, and in Source or Object form, provided that You 620 | meet the following conditions: 621 | 622 | (a) You must give any other recipients of the Work or 623 | Derivative Works a copy of this License; and 624 | 625 | (b) You must cause any modified files to carry prominent notices 626 | stating that You changed the files; and 627 | 628 | (c) You must retain, in the Source form of any Derivative Works 629 | that You distribute, all copyright, patent, trademark, and 630 | attribution notices from the Source form of the Work, 631 | excluding those notices that do not pertain to any part of 632 | the Derivative Works; and 633 | 634 | (d) If the Work includes a "NOTICE" text file as part of its 635 | distribution, then any Derivative Works that You distribute must 636 | include a readable copy of the attribution notices contained 637 | within such NOTICE file, excluding those notices that do not 638 | pertain to any part of the Derivative Works, in at least one 639 | of the following places: within a NOTICE text file distributed 640 | as part of the Derivative Works; within the Source form or 641 | documentation, if provided along with the Derivative Works; or, 642 | within a display generated by the Derivative Works, if and 643 | wherever such third-party notices normally appear. The contents 644 | of the NOTICE file are for informational purposes only and 645 | do not modify the License. You may add Your own attribution 646 | notices within Derivative Works that You distribute, alongside 647 | or as an addendum to the NOTICE text from the Work, provided 648 | that such additional attribution notices cannot be construed 649 | as modifying the License. 650 | 651 | You may add Your own copyright statement to Your modifications and 652 | may provide additional or different license terms and conditions 653 | for use, reproduction, or distribution of Your modifications, or 654 | for any such Derivative Works as a whole, provided Your use, 655 | reproduction, and distribution of the Work otherwise complies with 656 | the conditions stated in this License. 657 | 658 | 5. Submission of Contributions. Unless You explicitly state otherwise, 659 | any Contribution intentionally submitted for inclusion in the Work 660 | by You to the Licensor shall be under the terms and conditions of 661 | this License, without any additional terms or conditions. 662 | Notwithstanding the above, nothing herein shall supersede or modify 663 | the terms of any separate license agreement you may have executed 664 | with Licensor regarding such Contributions. 665 | 666 | 6. Trademarks. This License does not grant permission to use the trade 667 | names, trademarks, service marks, or product names of the Licensor, 668 | except as required for reasonable and customary use in describing the 669 | origin of the Work and reproducing the content of the NOTICE file. 670 | 671 | 7. Disclaimer of Warranty. Unless required by applicable law or 672 | agreed to in writing, Licensor provides the Work (and each 673 | Contributor provides its Contributions) on an "AS IS" BASIS, 674 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 675 | implied, including, without limitation, any warranties or conditions 676 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 677 | PARTICULAR PURPOSE. You are solely responsible for determining the 678 | appropriateness of using or redistributing the Work and assume any 679 | risks associated with Your exercise of permissions under this License. 680 | 681 | 8. Limitation of Liability. In no event and under no legal theory, 682 | whether in tort (including negligence), contract, or otherwise, 683 | unless required by applicable law (such as deliberate and grossly 684 | negligent acts) or agreed to in writing, shall any Contributor be 685 | liable to You for damages, including any direct, indirect, special, 686 | incidental, or consequential damages of any character arising as a 687 | result of this License or out of the use or inability to use the 688 | Work (including but not limited to damages for loss of goodwill, 689 | work stoppage, computer failure or malfunction, or any and all 690 | other commercial damages or losses), even if such Contributor 691 | has been advised of the possibility of such damages. 692 | 693 | 9. Accepting Warranty or Additional Liability. While redistributing 694 | the Work or Derivative Works thereof, You may choose to offer, 695 | and charge a fee for, acceptance of support, warranty, indemnity, 696 | or other liability obligations and/or rights consistent with this 697 | License. However, in accepting such obligations, You may act only 698 | on Your own behalf and on Your sole responsibility, not on behalf 699 | of any other Contributor, and only if You agree to indemnify, 700 | defend, and hold each Contributor harmless for any liability 701 | incurred by, or claims asserted against, such Contributor by reason 702 | of your accepting any such warranty or additional liability. 703 | 704 | END OF TERMS AND CONDITIONS 705 | 706 | APPENDIX: How to apply the Apache License to your work. 707 | 708 | To apply the Apache License to your work, attach the following 709 | boilerplate notice, with the fields enclosed by brackets "{}" 710 | replaced with your own identifying information. (Don't include 711 | the brackets!) The text should be enclosed in the appropriate 712 | comment syntax for the file format. We also recommend that a 713 | file or class name and description of purpose be included on the 714 | same "printed page" as the copyright notice for easier 715 | identification within third-party archives. 716 | 717 | Copyright 2018 Gregor Martynus and other contributors. 718 | 719 | Licensed under the Apache License, Version 2.0 (the "License"); 720 | you may not use this file except in compliance with the License. 721 | You may obtain a copy of the License at 722 | 723 | http://www.apache.org/licenses/LICENSE-2.0 724 | 725 | Unless required by applicable law or agreed to in writing, software 726 | distributed under the License is distributed on an "AS IS" BASIS, 727 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 728 | See the License for the specific language governing permissions and 729 | limitations under the License. 730 | 731 | 732 | deprecation 733 | ISC 734 | The ISC License 735 | 736 | Copyright (c) Gregor Martynus and contributors 737 | 738 | Permission to use, copy, modify, and/or distribute this software for any 739 | purpose with or without fee is hereby granted, provided that the above 740 | copyright notice and this permission notice appear in all copies. 741 | 742 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 743 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 744 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 745 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 746 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 747 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 748 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 749 | 750 | 751 | fs-extra 752 | MIT 753 | (The MIT License) 754 | 755 | Copyright (c) 2011-2017 JP Richardson 756 | 757 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 758 | (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, 759 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 760 | furnished to do so, subject to the following conditions: 761 | 762 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 763 | 764 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 765 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 766 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 767 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 768 | 769 | 770 | graceful-fs 771 | ISC 772 | The ISC License 773 | 774 | Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors 775 | 776 | Permission to use, copy, modify, and/or distribute this software for any 777 | purpose with or without fee is hereby granted, provided that the above 778 | copyright notice and this permission notice appear in all copies. 779 | 780 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 781 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 782 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 783 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 784 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 785 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 786 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 787 | 788 | 789 | jsonfile 790 | MIT 791 | (The MIT License) 792 | 793 | Copyright (c) 2012-2015, JP Richardson 794 | 795 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 796 | (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, 797 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 798 | furnished to do so, subject to the following conditions: 799 | 800 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 801 | 802 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 803 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 804 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 805 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 806 | 807 | 808 | object-resolve-path 809 | MIT 810 | The MIT License (MIT) 811 | 812 | Copyright (c) 2015 Jiri Spac 813 | 814 | Permission is hereby granted, free of charge, to any person obtaining a copy 815 | of this software and associated documentation files (the "Software"), to deal 816 | in the Software without restriction, including without limitation the rights 817 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 818 | copies of the Software, and to permit persons to whom the Software is 819 | furnished to do so, subject to the following conditions: 820 | 821 | The above copyright notice and this permission notice shall be included in all 822 | copies or substantial portions of the Software. 823 | 824 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 825 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 826 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 827 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 828 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 829 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 830 | SOFTWARE. 831 | 832 | 833 | 834 | once 835 | ISC 836 | The ISC License 837 | 838 | Copyright (c) Isaac Z. Schlueter and Contributors 839 | 840 | Permission to use, copy, modify, and/or distribute this software for any 841 | purpose with or without fee is hereby granted, provided that the above 842 | copyright notice and this permission notice appear in all copies. 843 | 844 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 845 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 846 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 847 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 848 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 849 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 850 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 851 | 852 | 853 | tmp 854 | MIT 855 | The MIT License (MIT) 856 | 857 | Copyright (c) 2014 KARASZI István 858 | 859 | Permission is hereby granted, free of charge, to any person obtaining a copy 860 | of this software and associated documentation files (the "Software"), to deal 861 | in the Software without restriction, including without limitation the rights 862 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 863 | copies of the Software, and to permit persons to whom the Software is 864 | furnished to do so, subject to the following conditions: 865 | 866 | The above copyright notice and this permission notice shall be included in all 867 | copies or substantial portions of the Software. 868 | 869 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 870 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 871 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 872 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 873 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 874 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 875 | SOFTWARE. 876 | 877 | 878 | tunnel 879 | MIT 880 | The MIT License (MIT) 881 | 882 | Copyright (c) 2012 Koichi Kobayashi 883 | 884 | Permission is hereby granted, free of charge, to any person obtaining a copy 885 | of this software and associated documentation files (the "Software"), to deal 886 | in the Software without restriction, including without limitation the rights 887 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 888 | copies of the Software, and to permit persons to whom the Software is 889 | furnished to do so, subject to the following conditions: 890 | 891 | The above copyright notice and this permission notice shall be included in 892 | all copies or substantial portions of the Software. 893 | 894 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 895 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 896 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 897 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 898 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 899 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 900 | THE SOFTWARE. 901 | 902 | 903 | undici 904 | MIT 905 | MIT License 906 | 907 | Copyright (c) Matteo Collina and Undici contributors 908 | 909 | Permission is hereby granted, free of charge, to any person obtaining a copy 910 | of this software and associated documentation files (the "Software"), to deal 911 | in the Software without restriction, including without limitation the rights 912 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 913 | copies of the Software, and to permit persons to whom the Software is 914 | furnished to do so, subject to the following conditions: 915 | 916 | The above copyright notice and this permission notice shall be included in all 917 | copies or substantial portions of the Software. 918 | 919 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 920 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 921 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 922 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 923 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 924 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 925 | SOFTWARE. 926 | 927 | 928 | universal-user-agent 929 | ISC 930 | # [ISC License](https://spdx.org/licenses/ISC) 931 | 932 | Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m) 933 | 934 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 935 | 936 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 937 | 938 | 939 | universalify 940 | MIT 941 | (The MIT License) 942 | 943 | Copyright (c) 2017, Ryan Zimmerman 944 | 945 | Permission is hereby granted, free of charge, to any person obtaining a copy of 946 | this software and associated documentation files (the 'Software'), to deal in 947 | the Software without restriction, including without limitation the rights to 948 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 949 | the Software, and to permit persons to whom the Software is furnished to do so, 950 | subject to the following conditions: 951 | 952 | The above copyright notice and this permission notice shall be included in all 953 | copies or substantial portions of the Software. 954 | 955 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 956 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 957 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 958 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 959 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 960 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 961 | 962 | 963 | uuid 964 | MIT 965 | The MIT License (MIT) 966 | 967 | Copyright (c) 2010-2020 Robert Kieffer and other contributors 968 | 969 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 970 | 971 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 972 | 973 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 974 | 975 | 976 | wrappy 977 | ISC 978 | The ISC License 979 | 980 | Copyright (c) Isaac Z. Schlueter and Contributors 981 | 982 | Permission to use, copy, modify, and/or distribute this software for any 983 | purpose with or without fee is hereby granted, provided that the above 984 | copyright notice and this permission notice appear in all copies. 985 | 986 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 987 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 988 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 989 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 990 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 991 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 992 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 993 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import jest from "eslint-plugin-jest"; 3 | import globals from "globals"; 4 | 5 | export default [ 6 | js.configs.recommended, 7 | { 8 | languageOptions: { 9 | parserOptions: { 10 | ecmaVersion: 2017, 11 | sourceType: "module" 12 | }, 13 | globals: { 14 | ...globals.node, 15 | ...globals.es2015, 16 | ...globals.jest 17 | } 18 | }, 19 | plugins: { jest }, 20 | rules: { 21 | semi: "error", 22 | "no-tabs": "error", 23 | "no-console": "off" 24 | } 25 | }, 26 | { 27 | ignores: ["eslint.config.mjs", "dist/*"] 28 | } 29 | ]; 30 | -------------------------------------------------------------------------------- /it/it.js: -------------------------------------------------------------------------------- 1 | const { Octokit } = require("@octokit/rest"); 2 | 3 | const { executeLocally } = require("../lib/api"); 4 | const { createConfig } = require("../lib/common"); 5 | 6 | async function main() { 7 | require("dotenv").config(); 8 | 9 | const token = process.env.GITHUB_TOKEN; 10 | 11 | const octokit = new Octokit({ 12 | baseUrl: "https://api.github.com", 13 | auth: `token ${token}`, 14 | userAgent: "pascalgn/automerge-action-it" 15 | }); 16 | 17 | const config = createConfig({ 18 | UPDATE_LABELS: "it-update", 19 | MERGE_LABELS: "it-merge", 20 | MERGE_REQUIRED_APPROVALS: "0", 21 | MERGE_REMOVE_LABELS: "it-merge", 22 | MERGE_RETRIES: "3", 23 | MERGE_RETRY_SLEEP: "2000", 24 | MERGE_ERROR_FAIL: "true" 25 | }); 26 | 27 | const context = { token, octokit, config }; 28 | 29 | await executeLocally(context, process.env.URL); 30 | } 31 | 32 | main().catch(e => { 33 | process.exitCode = 1; 34 | console.error(e); 35 | }); 36 | -------------------------------------------------------------------------------- /lib/api.js: -------------------------------------------------------------------------------- 1 | const process = require("process"); 2 | 3 | const { setOutput } = require("@actions/core"); 4 | 5 | const { 6 | ClientError, 7 | logger, 8 | RESULT_NOT_READY, 9 | RESULT_SKIPPED 10 | } = require("./common"); 11 | const { update } = require("./update"); 12 | const { merge } = require("./merge"); 13 | const { branchName } = require("./util"); 14 | 15 | const GITHUB_SERVER_URL = process.env.GITHUB_SERVER_URL || "https://github.com"; 16 | 17 | const URL_REGEXP = new RegExp( 18 | `^${GITHUB_SERVER_URL}/([^/]+)/([^/]+)/(pull|tree)/([^ ]+)$` 19 | ); 20 | 21 | const RELEVANT_ACTIONS = [ 22 | "labeled", 23 | "unlabeled", 24 | "synchronize", 25 | "opened", 26 | "edited", 27 | "ready_for_review", 28 | "reopened", 29 | "unlocked" 30 | ]; 31 | 32 | // we'll only update a few PRs at once: 33 | const MAX_PR_COUNT = process.env.MAX_PR_COUNT || 10; 34 | 35 | async function executeLocally(context, url) { 36 | const { octokit } = context; 37 | 38 | const m = url.match(URL_REGEXP); 39 | if (m && m[3] === "pull") { 40 | logger.debug("Getting PR data..."); 41 | const { data: pull_request } = await octokit.pulls.get({ 42 | owner: m[1], 43 | repo: m[2], 44 | pull_number: m[4], 45 | headers: { "If-None-Match": "" } 46 | }); 47 | 48 | const event = { 49 | action: "opened", 50 | pull_request 51 | }; 52 | 53 | return executeGitHubAction(context, "pull_request", event); 54 | } else if (m && m[3] === "tree") { 55 | const event = { 56 | ref: `refs/heads/${m[4]}`, 57 | repository: { 58 | name: m[2], 59 | owner: { 60 | name: m[1] 61 | } 62 | } 63 | }; 64 | 65 | return executeGitHubAction(context, "push", event); 66 | } else { 67 | throw new ClientError(`invalid URL: ${url}`); 68 | } 69 | } 70 | 71 | async function executeGitHubAction(context, eventName, eventData) { 72 | const result = await executeGitHubActionImpl(context, eventName, eventData); 73 | logger.info("Action result:", result); 74 | 75 | let singleResult; 76 | if (Array.isArray(result)) { 77 | logger.info("More than one result, using first result for action output"); 78 | singleResult = result[0]; 79 | } else if (result != null) { 80 | singleResult = result; 81 | } else { 82 | throw new Error("invalid result!"); 83 | } 84 | 85 | const { mergeResult, pullRequestNumber } = singleResult || {}; 86 | setOutput("mergeResult", mergeResult || RESULT_SKIPPED); 87 | setOutput("pullRequestNumber", pullRequestNumber || 0); 88 | } 89 | 90 | async function executeGitHubActionImpl(context, eventName, eventData) { 91 | logger.info("Event name:", eventName); 92 | logger.trace("Event data:", eventData); 93 | 94 | if (context.config.pullRequest != null) { 95 | return await handleArbitraryPullRequestUpdate(context, eventData); 96 | } else if (["push"].includes(eventName)) { 97 | await handleBaseBranchUpdate(context, eventName, eventData); 98 | } else if (["status"].includes(eventName)) { 99 | return await handleStatusUpdate(context, eventName, eventData); 100 | } else if (["pull_request", "pull_request_target"].includes(eventName)) { 101 | return await handlePullRequestUpdate(context, eventName, eventData); 102 | } else if (["check_suite", "check_run", "workflow_run"].includes(eventName)) { 103 | return await handleCheckOrWorkflowUpdate(context, eventName, eventData); 104 | } else if (["pull_request_review"].includes(eventName)) { 105 | return await handlePullRequestReviewUpdate(context, eventName, eventData); 106 | } else if (["schedule", "repository_dispatch"].includes(eventName)) { 107 | return await handleScheduleTriggerOrRepositoryDispatch(context); 108 | } else if (["issue_comment"].includes(eventName)) { 109 | return await handleIssueComment(context, eventName, eventData); 110 | } else if (["workflow_dispatch"].includes(eventName)) { 111 | return await handleWorkflowDispatch(context, eventName, eventData); 112 | } else { 113 | throw new ClientError(`invalid event type: ${eventName}`); 114 | } 115 | } 116 | 117 | async function handlePullRequestUpdate(context, eventName, event) { 118 | const { action } = event; 119 | if (!RELEVANT_ACTIONS.includes(action)) { 120 | logger.info("Action ignored:", eventName, action); 121 | return { mergeResult: RESULT_SKIPPED }; 122 | } 123 | 124 | const pullRequest = await fetchPullRequest( 125 | context, 126 | event.pull_request.base.repo, 127 | event.pull_request 128 | ); 129 | 130 | return updateAndMerge(context, pullRequest); 131 | } 132 | 133 | async function handleArbitraryPullRequestUpdate(context, eventData) { 134 | const { config, octokit } = context; 135 | 136 | const repoOwner = 137 | config.pullRequest.repoOwner || eventData.repository.owner.login; 138 | const repoName = config.pullRequest.repoName || eventData.repository.name; 139 | const { pullRequestNumber } = config.pullRequest; 140 | 141 | logger.info(`Looking for pull request #${pullRequestNumber}...`); 142 | 143 | try { 144 | const { data: pullRequest } = await octokit.pulls.get({ 145 | owner: repoOwner, 146 | repo: repoName, 147 | pull_number: pullRequestNumber, 148 | headers: { "If-None-Match": "" } 149 | }); 150 | logger.trace("Full PR:", pullRequest); 151 | 152 | return updateAndMerge(context, pullRequest); 153 | } catch (e) { 154 | logger.error( 155 | `Error fetching pull request: ${repoOwner}/${repoName}/${pullRequestNumber}` 156 | ); 157 | throw e; 158 | } 159 | } 160 | 161 | async function handleCheckOrWorkflowUpdate(context, eventName, event) { 162 | const { action } = event; 163 | const eventType = eventName === "workflow_run" ? "workflow" : "status check"; 164 | if (action !== "completed") { 165 | logger.info(`A ${eventType} is not yet complete:`, eventName); 166 | return { mergeResult: RESULT_NOT_READY }; 167 | } 168 | 169 | const payload = event[eventName]; 170 | if (!payload) { 171 | throw new Error(`failed to find payload for event type: ${eventName}`); 172 | } 173 | if (payload.conclusion !== "success") { 174 | logger.info(`A ${eventType} completed unsuccessfully:`, eventName); 175 | return { mergeResult: RESULT_NOT_READY }; 176 | } 177 | 178 | logger.info(`${eventType} completed successfully`); 179 | 180 | const eventPullRequest = payload.pull_requests[0]; 181 | if (eventPullRequest != null) { 182 | const { octokit } = context; 183 | const { data: pullRequest } = await octokit.request(eventPullRequest.url); 184 | logger.trace("PR:", pullRequest); 185 | 186 | return updateAndMerge(context, pullRequest); 187 | } else { 188 | const branchName = payload.head_branch; 189 | if (branchName != null) { 190 | return await checkPullRequestsForBranches(context, event, branchName); 191 | } else { 192 | return await checkPullRequestsForHeadSha( 193 | context, 194 | event.repository, 195 | payload.head_sha 196 | ); 197 | } 198 | } 199 | } 200 | 201 | async function handlePullRequestReviewUpdate(context, eventName, event) { 202 | const { action, review } = event; 203 | if (action === "submitted") { 204 | if (review.state === "approved") { 205 | const pullRequest = await fetchPullRequest( 206 | context, 207 | event.pull_request.base.repo, 208 | event.pull_request 209 | ); 210 | return updateAndMerge(context, pullRequest); 211 | } else { 212 | logger.info("Review state is not approved:", review.state); 213 | logger.info("Action ignored:", eventName, action); 214 | } 215 | } else { 216 | logger.info("Action ignored:", eventName, action); 217 | } 218 | return { mergeResult: RESULT_SKIPPED }; 219 | } 220 | 221 | async function handleStatusUpdate(context, eventName, event) { 222 | const { state, branches } = event; 223 | if (state !== "success") { 224 | logger.info("Event state ignored:", eventName, state); 225 | return []; 226 | } 227 | 228 | if (!branches || branches.length === 0) { 229 | logger.info("No branches have been referenced:", eventName); 230 | return []; 231 | } 232 | 233 | let results = []; 234 | for (const branch of branches) { 235 | results = results.concat( 236 | await checkPullRequestsForBranches(context, event, branch.name) 237 | ); 238 | } 239 | return results; 240 | } 241 | 242 | async function checkPullRequestsForBranches(context, event, branchName) { 243 | const { octokit } = context; 244 | logger.debug("Listing pull requests for", branchName, "..."); 245 | const { data: pullRequests } = await octokit.pulls.list({ 246 | owner: event.repository.owner.login, 247 | repo: event.repository.name, 248 | state: "open", 249 | head: `${event.repository.owner.login}:${branchName}`, 250 | sort: "updated", 251 | direction: "desc", 252 | per_page: MAX_PR_COUNT 253 | }); 254 | 255 | logger.trace("PR list:", pullRequests); 256 | 257 | let updated = 0; 258 | let results = []; 259 | for (const pullRequest of pullRequests) { 260 | try { 261 | const result = await updateAndMerge(context, pullRequest); 262 | results.push(result); 263 | ++updated; 264 | } catch (e) { 265 | logger.error(e); 266 | } 267 | } 268 | 269 | if (updated === 0) { 270 | logger.info("No PRs have been updated/merged"); 271 | } 272 | return results; 273 | } 274 | 275 | async function checkPullRequestsForHeadSha(context, repo, head_sha) { 276 | const { octokit } = context; 277 | logger.debug("Listing pull requests to look for", head_sha, "..."); 278 | const { data: pullRequests } = await octokit.pulls.list({ 279 | owner: repo.owner.login, 280 | repo: repo.name, 281 | state: "open", 282 | sort: "updated", 283 | direction: "desc", 284 | per_page: MAX_PR_COUNT 285 | }); 286 | 287 | let updated = 0; 288 | let foundPR = false; 289 | let results = []; 290 | for (const pullRequest of pullRequests) { 291 | if (pullRequest.head.sha !== head_sha) { 292 | continue; 293 | } 294 | foundPR = true; 295 | try { 296 | const result = await updateAndMerge(context, pullRequest); 297 | results.push(result); 298 | ++updated; 299 | } catch (e) { 300 | logger.error(e); 301 | } 302 | } 303 | 304 | if (updated === 0) { 305 | logger.info("No PRs have been updated/merged"); 306 | } 307 | if (!foundPR) { 308 | logger.info( 309 | "Could not find branch name in this status check result" + 310 | " or corresponding PR from a forked repository" 311 | ); 312 | } 313 | return results; 314 | } 315 | 316 | async function handleBaseBranchUpdate(context, eventName, event) { 317 | const { ref } = event; 318 | const branch = branchName(ref); 319 | if (!branch) { 320 | logger.info("Push does not reference a branch:", ref); 321 | return; 322 | } 323 | 324 | logger.debug("Updated branch:", branch); 325 | 326 | const { octokit } = context; 327 | 328 | logger.debug("Listing pull requests..."); 329 | const { data: pullRequests } = await octokit.pulls.list({ 330 | owner: event.repository.owner.login, 331 | repo: event.repository.name, 332 | state: "open", 333 | base: branch, 334 | sort: "updated", 335 | direction: "desc", 336 | per_page: MAX_PR_COUNT 337 | }); 338 | 339 | logger.trace("PR list:", pullRequests); 340 | 341 | if (pullRequests.length > 0) { 342 | logger.info("Open PRs:", pullRequests.length); 343 | } else { 344 | logger.info("No open PRs for", branch); 345 | return; 346 | } 347 | 348 | let updated = 0; 349 | for (const pullRequest of pullRequests) { 350 | try { 351 | await update(context, pullRequest); 352 | updated++; 353 | } catch (e) { 354 | logger.error(e); 355 | } 356 | } 357 | 358 | if (updated > 0) { 359 | logger.info(updated, "PRs based on", branch, "have been updated"); 360 | } else { 361 | logger.info("No PRs based on", branch, "have been updated"); 362 | } 363 | } 364 | 365 | async function handleWorkflowDispatch(context, eventName, event) { 366 | const { ref } = event; 367 | const branch = branchName(ref); 368 | if (!branch) { 369 | logger.info("Dispatch does not reference a branch:", ref); 370 | return { mergeResult: RESULT_SKIPPED }; 371 | } 372 | 373 | return await checkPullRequestsForBranches(context, event, branch); 374 | } 375 | 376 | async function handleScheduleTriggerOrRepositoryDispatch(context) { 377 | const { octokit } = context; 378 | 379 | const { GITHUB_REPOSITORY } = process.env; 380 | const [owner, repo] = (GITHUB_REPOSITORY || "").split("/", 2); 381 | 382 | if (!owner || !repo) { 383 | throw new Error(`invalid GITHUB_REPOSITORY value: ${GITHUB_REPOSITORY}`); 384 | } 385 | 386 | logger.debug("Listing pull requests ..."); 387 | const { data: pullRequests } = await octokit.pulls.list({ 388 | owner, 389 | repo, 390 | state: "open", 391 | sort: "updated", 392 | direction: "desc", 393 | per_page: MAX_PR_COUNT 394 | }); 395 | 396 | logger.trace("PR list:", pullRequests); 397 | 398 | let updated = 0; 399 | let results = []; 400 | for (const pullRequest of pullRequests) { 401 | try { 402 | const result = await updateAndMerge(context, pullRequest); 403 | results.push(result); 404 | ++updated; 405 | } catch (e) { 406 | logger.error(e); 407 | } 408 | } 409 | 410 | if (updated === 0) { 411 | logger.info("No PRs have been updated/merged"); 412 | } 413 | return results; 414 | } 415 | 416 | async function handleIssueComment(context, eventName, event) { 417 | const { action, issue, repository } = event; 418 | if (action === "created") { 419 | if (issue.pull_request == null) { 420 | logger.info("Comment not on a PR, skipping"); 421 | } else { 422 | const pullRequest = await fetchPullRequest(context, repository, issue); 423 | return updateAndMerge(context, pullRequest); 424 | } 425 | } else { 426 | logger.info("Action ignored:", eventName, action); 427 | } 428 | return { mergeResult: RESULT_SKIPPED }; 429 | } 430 | 431 | async function fetchPullRequest(context, repository, issue) { 432 | const { octokit } = context; 433 | const { number } = issue; 434 | 435 | logger.debug("Getting pull request info for", number, "..."); 436 | let { data: pullRequest } = await octokit.pulls.get({ 437 | owner: repository.owner.login, 438 | repo: repository.name, 439 | pull_number: number, 440 | headers: { "If-None-Match": "" } 441 | }); 442 | 443 | logger.trace("Full PR:", pullRequest); 444 | return pullRequest; 445 | } 446 | 447 | async function updateAndMerge(context, pullRequest) { 448 | const approvalCount = await fetchApprovalReviewCount(context, pullRequest); 449 | await update(context, pullRequest); 450 | const mergeResult = await merge(context, pullRequest, approvalCount); 451 | return { mergeResult, pullRequestNumber: pullRequest.number }; 452 | } 453 | 454 | async function fetchApprovalReviewCount(context, pullRequest) { 455 | const { 456 | octokit, 457 | config: { mergeRequiredApprovals } 458 | } = context; 459 | const { number } = pullRequest; 460 | 461 | if (mergeRequiredApprovals === 0) { 462 | // If we don't care about review approvals, let's short circuit. 463 | return 0; 464 | } 465 | 466 | logger.debug("Getting reviews for", number, "..."); 467 | const reviews = await octokit.paginate(octokit.pulls.listReviews, { 468 | owner: pullRequest.base.repo.owner.login, 469 | repo: pullRequest.base.repo.name, 470 | pull_number: number 471 | }); 472 | 473 | const approvingReviewers = reviews 474 | .filter(review => review.state === "APPROVED") 475 | .map(review => review.user.login); 476 | const uniqueApprovingReviewers = [...new Set(approvingReviewers)]; 477 | 478 | logger.trace("Approval reviewers:", uniqueApprovingReviewers); 479 | return uniqueApprovingReviewers.length; 480 | } 481 | 482 | module.exports = { executeLocally, executeGitHubAction }; 483 | -------------------------------------------------------------------------------- /lib/common.js: -------------------------------------------------------------------------------- 1 | const util = require("util"); 2 | const process = require("process"); 3 | const fse = require("fs-extra"); 4 | const tmp = require("tmp"); 5 | 6 | const RESULT_SKIPPED = "skipped"; 7 | const RESULT_NOT_READY = "not_ready"; 8 | const RESULT_AUTHOR_FILTERED = "author_filtered"; 9 | const RESULT_MERGE_FAILED = "merge_failed"; 10 | const RESULT_MERGED = "merged"; 11 | 12 | class ClientError extends Error {} 13 | 14 | class TimeoutError extends Error {} 15 | 16 | function log(prefix, obj) { 17 | if (process.env.NODE_ENV !== "test") { 18 | const now = new Date().toISOString(); 19 | const str = obj.map(o => (typeof o === "object" ? inspect(o) : o)); 20 | if (prefix) { 21 | console.log.apply(console, [now, prefix, ...str]); 22 | } else { 23 | console.log.apply(console, [now, ...str]); 24 | } 25 | } 26 | } 27 | 28 | const logger = { 29 | level: "info", 30 | 31 | trace: (...str) => { 32 | if (logger.level === "trace") { 33 | log("TRACE", str); 34 | } 35 | }, 36 | 37 | debug: (...str) => { 38 | if (logger.level === "trace" || logger.level === "debug") { 39 | log("DEBUG", str); 40 | } 41 | }, 42 | 43 | info: (...str) => log("INFO ", str), 44 | 45 | error: (...str) => { 46 | if (str.length === 1 && str[0] instanceof Error) { 47 | if (logger.level === "trace" || logger.level === "debug") { 48 | log(null, [str[0].stack || str[0]]); 49 | } else { 50 | log("ERROR", [str[0].message || str[0]]); 51 | } 52 | } else { 53 | log("ERROR", str); 54 | } 55 | } 56 | }; 57 | 58 | function inspect(obj) { 59 | return util.inspect(obj, false, null, true); 60 | } 61 | 62 | function createConfig(env = {}) { 63 | function parseMergeLabels(str, defaultValue) { 64 | const arr = (str == null ? defaultValue : str) 65 | .split(",") 66 | .map(s => s.trim()); 67 | return { 68 | required: arr.filter(s => !s.startsWith("!") && s.length > 0), 69 | blocking: arr 70 | .filter(s => s.startsWith("!")) 71 | .map(s => s.substr(1).trim()) 72 | .filter(s => s.length > 0) 73 | }; 74 | } 75 | 76 | function parseLabelMethods(str) { 77 | return (str ? str.split(",") : []).map(lm => { 78 | const [label, method] = lm.split("="); 79 | if (!label || !method) { 80 | throw new Error( 81 | `Couldn't parse "${lm}" as "