├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ └── test.yml ├── .gitignore ├── .node-version ├── .vscode ├── launch.json └── tasks.json ├── .yaml-lint.yml ├── LICENSE ├── README.md ├── __fixtures__ └── core.js ├── action.yml ├── dist ├── 228.index.js ├── 367.index.js ├── 596.index.js ├── 844.index.js ├── LICENSE ├── build │ └── Release │ │ └── zlib_sync.node ├── index.js └── package.json ├── eslint.config.mjs ├── img ├── custom_appearance.jpg └── default_appearance.jpg ├── index.js ├── jest.config.js ├── package-lock.json ├── package.json └── test.env /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | groups: 8 | actions-minor: 9 | update-types: 10 | - minor 11 | - patch 12 | 13 | - package-ecosystem: npm 14 | directory: / 15 | schedule: 16 | interval: weekly 17 | groups: 18 | npm-development: 19 | dependency-type: development 20 | update-types: 21 | - minor 22 | - patch 23 | npm-production: 24 | dependency-type: production 25 | update-types: 26 | - patch -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - v2 8 | push: 9 | branches: 10 | - main 11 | - v2 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | test-javascript: 18 | name: JavaScript Tests 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout 23 | id: checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup Node.js 27 | id: setup-node 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version-file: .node-version 31 | cache: npm 32 | 33 | - name: Install Dependencies 34 | id: npm-ci 35 | run: npm ci 36 | 37 | - name: Lint 38 | id: npm-lint 39 | run: npm run lint 40 | 41 | - name: Test 42 | id: npm-ci-test 43 | run: npm run ci-test 44 | 45 | test-action: 46 | name: GitHub Actions Test 47 | runs-on: ubuntu-latest 48 | 49 | steps: 50 | - name: Checkout 51 | id: checkout 52 | uses: actions/checkout@v4 53 | 54 | - name: Test Local Action 55 | id: test-action 56 | uses: ./ 57 | with: 58 | webhookUrl: "foobar" 59 | 60 | - name: Print Output 61 | id: output 62 | run: echo "${{ steps.test-action.outputs.time }}" -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test Action 2 | on: [ push ] 3 | jobs: 4 | windows_test: 5 | runs-on: windows-latest 6 | name: Windows Test Job 7 | steps: 8 | - name: Windows Test Info 9 | uses: rjstone/discord-webhook-notify@v2 10 | with: 11 | severity: info 12 | details: Test succeeded. 13 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 14 | - name: Windows Test Warn 15 | uses: rjstone/discord-webhook-notify@v2 16 | with: 17 | severity: warn 18 | details: Test warning. 19 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 20 | - name: Windows Test Error 21 | uses: rjstone/discord-webhook-notify@v2 22 | with: 23 | severity: error 24 | details: Test error. 25 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 26 | - name: Windows Test Custom 27 | uses: rjstone/discord-webhook-notify@v2 28 | with: 29 | severity: info 30 | username: CustomUsername 31 | color: '#ff00aa' 32 | avatarUrl: https://github.githubassets.com/images/modules/logos_page/Octocat.png 33 | description: This is a custom description. 34 | details: 'Custom details: Somebody set up us the bomb.' 35 | footer: This is a footer. 36 | text: This is where text goes. 37 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 38 | - name: Windows Test Success 39 | uses: rjstone/discord-webhook-notify@v2 40 | if: success() 41 | with: 42 | severity: info 43 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 44 | - name: Windows Test Failure 45 | uses: rjstone/discord-webhook-notify@v2 46 | if: failure() 47 | with: 48 | severity: error 49 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 50 | - name: Windows Test Cancelled 51 | uses: rjstone/discord-webhook-notify@v2 52 | if: cancelled() 53 | with: 54 | severity: warn 55 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 56 | linux_test: 57 | runs-on: ubuntu-latest 58 | name: Linux Test Job 59 | steps: 60 | - name: Linux Test Info 61 | uses: rjstone/discord-webhook-notify@v2 62 | with: 63 | severity: info 64 | details: Test succeeded. 65 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 66 | - name: Linux Test Warn 67 | uses: rjstone/discord-webhook-notify@v2 68 | with: 69 | severity: warn 70 | details: Test warning. 71 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 72 | - name: Linux Test Error 73 | uses: rjstone/discord-webhook-notify@v2 74 | with: 75 | severity: error 76 | details: Test error. 77 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 78 | - name: Linux Test Custom 79 | uses: rjstone/discord-webhook-notify@v2 80 | with: 81 | severity: info 82 | username: CustomUsername 83 | color: '#ff00aa' 84 | avatarUrl: https://github.githubassets.com/images/modules/logos_page/Octocat.png 85 | description: This is a custom description. 86 | details: 'Custom details: Somebody set up us the bomb.' 87 | footer: This is a footer. 88 | text: This is where text goes. 89 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 90 | - name: Linux Test Success 91 | uses: rjstone/discord-webhook-notify@v2 92 | if: success() 93 | with: 94 | severity: info 95 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 96 | - name: Linux Test Failure 97 | uses: rjstone/discord-webhook-notify@v2 98 | if: failure() 99 | with: 100 | severity: error 101 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 102 | - name: Linux Test Cancelled 103 | uses: rjstone/discord-webhook-notify@v2 104 | if: cancelled() 105 | with: 106 | severity: warn 107 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 108 | macos_test: 109 | runs-on: macos-latest 110 | name: MacOS Test Job 111 | steps: 112 | - name: MacOS Test Info 113 | uses: rjstone/discord-webhook-notify@v2 114 | with: 115 | severity: info 116 | details: Test succeeded. 117 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 118 | - name: MacOS Test Warn 119 | uses: rjstone/discord-webhook-notify@v2 120 | with: 121 | severity: warn 122 | details: Test warning. 123 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 124 | - name: MacOS Test Error 125 | uses: rjstone/discord-webhook-notify@v2 126 | with: 127 | severity: error 128 | details: Test error. 129 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 130 | - name: MacOS Test Custom 131 | uses: rjstone/discord-webhook-notify@v2 132 | with: 133 | severity: info 134 | username: CustomUsername 135 | color: '#ff00aa' 136 | avatarUrl: https://github.githubassets.com/images/modules/logos_page/Octocat.png 137 | description: This is a custom description. 138 | details: 'Custom details: Somebody set up us the bomb.' 139 | footer: This is a footer. 140 | text: This is where text goes. 141 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 142 | - name: MacOS Test Success 143 | uses: rjstone/discord-webhook-notify@v2 144 | if: success() 145 | with: 146 | severity: info 147 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 148 | - name: MacOS Test Failure 149 | uses: rjstone/discord-webhook-notify@v2 150 | if: failure() 151 | with: 152 | severity: error 153 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 154 | - name: MacOS Test Cancelled 155 | uses: rjstone/discord-webhook-notify@v2 156 | if: cancelled() 157 | with: 158 | severity: warn 159 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 160 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | # OS metadata 94 | .DS_Store 95 | Thumbs.db 96 | 97 | # Ignore built ts files 98 | __tests__/runner/* 99 | 100 | # IDE files 101 | .idea 102 | *.code-workspace 103 | 104 | # Lockfile 105 | *.lock -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 20.19.2 -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Local Debug for Github Action", 6 | "type": "node", 7 | "request": "launch", 8 | "runtimeExecutable": "local-action", 9 | "cwd": "${workspaceRoot}", 10 | "args": [".", "index.js", "test.env"], 11 | "console": "integratedTerminal", 12 | "skipFiles": ["/**", "node_modules/**"] 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "shell", 6 | "command": "npm install", 7 | "group": "build", 8 | "problemMatcher": [], 9 | "label": "npm: install", 10 | "detail": "install dependencies from package" 11 | }, 12 | { 13 | "type": "shell", 14 | "command": "ncc build index.js --license LICENSE", 15 | "group": "build", 16 | "problemMatcher": [], 17 | "label": "vercel/ncc: build", 18 | "detail": "compile index.js and node_modules to avoid mess" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /.yaml-lint.yml: -------------------------------------------------------------------------------- 1 | # See: https://yamllint.readthedocs.io/en/stable/ 2 | 3 | rules: 4 | document-end: disable 5 | document-start: 6 | level: warning 7 | present: false 8 | line-length: 9 | level: warning 10 | max: 80 11 | allow-non-breakable-words: true 12 | allow-non-breakable-inline-mappings: true 13 | ignore: 14 | - .licenses/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Robert Stone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discord Webhook Notify 2 | 3 | This sends a notification to discord using a webhook URL. It is written in JavaScript so **it will work with windows, osx, and linux execution environments**. 4 | 5 | To use this, get on Discord and create a new webhook. Then get on GitHub, go into your project settings, and add a new Secret called `DISCORD_WEBHOOK`. In your workflow YAML, set `webhookUrl` as follows: `webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}`. You must set webhookUrl this way for each invocation of the action. 6 | 7 | - Use `rjstone/discord-webhook-notify@v1` if you want bugfixes but nothing backward-compatability breaking. (If anything breaks compatability it will be in v2+.) 8 | - Use `rjstone/discord-webhook-notify@v1.0.0` (or another specific tag after the @) if you want to guarantee use of a specific revision. 9 | 10 | See below for more documentation and detailed examples. 11 | 12 | ## Inputs 13 | 14 | ### `webhookUrl` 15 | 16 | The webhook URL to use. This should be in a repository secret and the secret should be included here using `${{ secrets.DISCORD_WEBHOOK }}`. For security reasons it is not possible to default this to the secret name, so it must be supplied in every action invocation. 17 | 18 | ### `severity` 19 | 20 | The severity level of the notification, either `info`, `warn`, or `error`. Default is `error`. 21 | 22 | ### `description` 23 | 24 | The top half of the event description. This defaults to showing a number of pieces of information from the environment. Only override this if you do not want the default selection of information. Note that this may contain Discord style markdown. 25 | 26 | ### `details` 27 | 28 | The bottom half of the event description. If you do want the default information in the description then just specify details to add additional information below the default set of variables that are displayed. Default to empty and may contain Discord style markdown. 29 | 30 | ### `footer` 31 | 32 | String to display in the "embed footer" section of the notification. This defaults to showing the severity level. 33 | 34 | ### `text` 35 | 36 | String to display as normal chat text above the "embed" section. This defaults to empty and may contain Discord style markdown. 37 | 38 | ### `username` 39 | 40 | Username to display in Discord for this notification. Default is "GitHub". 41 | 42 | ### `color` 43 | 44 | Color of the bar on the left side of the "embed" section in the form #rrggbb (hex). Default determined by severity. 45 | 46 | ### `avatarUrl` 47 | 48 | URL to png of discord avatar to use. The default is the GitHub monochrome "mark" logo with white background. 49 | 50 | ## Example usage 51 | 52 | ### Simple Usage Example 53 | 54 | Set up notification for whatever conditions you want. There's no built-in handling based on reading the environment so you can notify on any `if:` expression. 55 | 56 | ``` 57 | - name: Test Success 58 | uses: rjstone/discord-webhook-notify@v1 59 | if: success() 60 | with: 61 | severity: info 62 | details: Test Succeeded! 63 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 64 | - name: Test Failure 65 | uses: rjstone/discord-webhook-notify@v1 66 | if: failure() 67 | with: 68 | severity: error 69 | details: Test Failed! 70 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 71 | - name: Test Cancelled 72 | uses: rjstone/discord-webhook-notify@v1 73 | if: cancelled() 74 | with: 75 | severity: warn 76 | details: Test Cancelled! 77 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 78 | ``` 79 | 80 | ### Default Appearance Examples 81 | 82 | This shows the appearance of notifications where most of the inputs are left at the default. 83 | 84 | ![Default Appearance Screenshot](img/default_appearance.jpg) 85 | 86 | ``` 87 | - name: Test Info 88 | uses: rjstone/discord-webhook-notify@v1 89 | with: 90 | severity: info 91 | details: Test succeeded. 92 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 93 | - name: Test Warn 94 | uses: rjstone/discord-webhook-notify@v1 95 | with: 96 | severity: warn 97 | details: Test warning. 98 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 99 | - name: Test Error 100 | uses: rjstone/discord-webhook-notify@v1 101 | with: 102 | severity: error 103 | details: Test error. 104 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 105 | ``` 106 | 107 | ### Minimal Full Custom Example 108 | 109 | This shows you where each custom input shows up in the formatting of the Discord notification. 110 | 111 | ![Custom Appearance Example](img/custom_appearance.jpg) 112 | 113 | ``` 114 | - name: Test Custom 115 | uses: rjstone/discord-webhook-notify@v1 116 | with: 117 | severity: info 118 | username: CustomUsername 119 | color: '#ff00aa' 120 | avatarUrl: https://github.githubassets.com/images/modules/logos_page/Octocat.png 121 | description: This is a custom description. 122 | details: 'Custom details: Somebody set up us the bomb.' 123 | footer: This is a footer. 124 | text: This is where text goes. 125 | webhookUrl: ${{ secrets.DISCORD_WEBHOOK }} 126 | ``` -------------------------------------------------------------------------------- /__fixtures__/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used to mock the `@actions/core` module in tests. 3 | */ 4 | import { jest } from '@jest/globals' 5 | 6 | export const debug = jest.fn() 7 | export const error = jest.fn() 8 | export const info = jest.fn() 9 | export const getInput = jest.fn() 10 | export const setOutput = jest.fn() 11 | export const setFailed = jest.fn() 12 | export const warning = jest.fn() -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: Discord Webhook Notify 2 | author: rjstone 3 | description: > 4 | Send notifications to Discord using a webhook. 5 | These can be created by server admins using configuration settings for a channel.. 6 | Works with all execution environments including windows, macos, and linux. 7 | Use context expressions and environment variables in the inputs to provide information. 8 | inputs: 9 | webhookUrl: 10 | description: > 11 | Discord webhook URL. Should be stored in a repo secret (Settings>Security>Secrets) and inserted 12 | in the action call as a context expression. 13 | required: true 14 | holddownTime: 15 | description: > 16 | The minimum amount of time in ms between successive notifications to avoid triggering Discord's 17 | rate limiting. Default = 2000ms. 18 | required: false 19 | default: 2000 20 | username: 21 | description: Username to display in discord. Defaults to "GitHub". 22 | required: false 23 | default: GitHub 24 | avatarUrl: 25 | description: > 26 | URL to png of discord avatar to use. Default is the GitHub monochrome mark cat logo. 27 | May not work depending on Discord policy. 28 | required: false 29 | default: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png 30 | severity: 31 | description: Severity level - info, warn, or error. Defaults to info. 32 | required: false 33 | default: info 34 | text: 35 | description: Text to be sent as normal text above the embed. Defaults to empty string. 36 | required: false 37 | color: 38 | description: Notification embed color in the form poundsign rrggbb (hex). Default determined by severity. 39 | required: false 40 | title: 41 | description: Title for the embed. Defaults to severity long terminology. 42 | required: false 43 | description: 44 | description: Embed notification message. Default provides some minimal github.context workflow info. 45 | required: false 46 | details: 47 | description: > 48 | Additional text after the notification message in case you want to retain the default message. 49 | Defaults to empty string. 50 | required: false 51 | footer: 52 | description: Footer for the embed. Defaults to severity and timestamp. 53 | required: false 54 | runs: 55 | using: "node20" 56 | main: "dist/index.js" 57 | branding: 58 | color: orange 59 | icon: alert-triangle 60 | -------------------------------------------------------------------------------- /dist/367.index.js: -------------------------------------------------------------------------------- 1 | export const id = 367; 2 | export const ids = [367]; 3 | export const modules = { 4 | 5 | /***/ 44914: 6 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 7 | 8 | 9 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | var desc = Object.getOwnPropertyDescriptor(m, k); 12 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 13 | desc = { enumerable: true, get: function() { return m[k]; } }; 14 | } 15 | Object.defineProperty(o, k2, desc); 16 | }) : (function(o, m, k, k2) { 17 | if (k2 === undefined) k2 = k; 18 | o[k2] = m[k]; 19 | })); 20 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 21 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 22 | }) : function(o, v) { 23 | o["default"] = v; 24 | }); 25 | var __importStar = (this && this.__importStar) || function (mod) { 26 | if (mod && mod.__esModule) return mod; 27 | var result = {}; 28 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 29 | __setModuleDefault(result, mod); 30 | return result; 31 | }; 32 | Object.defineProperty(exports, "__esModule", ({ value: true })); 33 | exports.issue = exports.issueCommand = void 0; 34 | const os = __importStar(__webpack_require__(70857)); 35 | const utils_1 = __webpack_require__(30302); 36 | /** 37 | * Commands 38 | * 39 | * Command Format: 40 | * ::name key=value,key=value::message 41 | * 42 | * Examples: 43 | * ::warning::This is the message 44 | * ::set-env name=MY_VAR::some value 45 | */ 46 | function issueCommand(command, properties, message) { 47 | const cmd = new Command(command, properties, message); 48 | process.stdout.write(cmd.toString() + os.EOL); 49 | } 50 | exports.issueCommand = issueCommand; 51 | function issue(name, message = '') { 52 | issueCommand(name, {}, message); 53 | } 54 | exports.issue = issue; 55 | const CMD_STRING = '::'; 56 | class Command { 57 | constructor(command, properties, message) { 58 | if (!command) { 59 | command = 'missing.command'; 60 | } 61 | this.command = command; 62 | this.properties = properties; 63 | this.message = message; 64 | } 65 | toString() { 66 | let cmdStr = CMD_STRING + this.command; 67 | if (this.properties && Object.keys(this.properties).length > 0) { 68 | cmdStr += ' '; 69 | let first = true; 70 | for (const key in this.properties) { 71 | if (this.properties.hasOwnProperty(key)) { 72 | const val = this.properties[key]; 73 | if (val) { 74 | if (first) { 75 | first = false; 76 | } 77 | else { 78 | cmdStr += ','; 79 | } 80 | cmdStr += `${key}=${escapeProperty(val)}`; 81 | } 82 | } 83 | } 84 | } 85 | cmdStr += `${CMD_STRING}${escapeData(this.message)}`; 86 | return cmdStr; 87 | } 88 | } 89 | function escapeData(s) { 90 | return (0, utils_1.toCommandValue)(s) 91 | .replace(/%/g, '%25') 92 | .replace(/\r/g, '%0D') 93 | .replace(/\n/g, '%0A'); 94 | } 95 | function escapeProperty(s) { 96 | return (0, utils_1.toCommandValue)(s) 97 | .replace(/%/g, '%25') 98 | .replace(/\r/g, '%0D') 99 | .replace(/\n/g, '%0A') 100 | .replace(/:/g, '%3A') 101 | .replace(/,/g, '%2C'); 102 | } 103 | //# sourceMappingURL=command.js.map 104 | 105 | /***/ }), 106 | 107 | /***/ 37484: 108 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 109 | 110 | 111 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 112 | if (k2 === undefined) k2 = k; 113 | var desc = Object.getOwnPropertyDescriptor(m, k); 114 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 115 | desc = { enumerable: true, get: function() { return m[k]; } }; 116 | } 117 | Object.defineProperty(o, k2, desc); 118 | }) : (function(o, m, k, k2) { 119 | if (k2 === undefined) k2 = k; 120 | o[k2] = m[k]; 121 | })); 122 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 123 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 124 | }) : function(o, v) { 125 | o["default"] = v; 126 | }); 127 | var __importStar = (this && this.__importStar) || function (mod) { 128 | if (mod && mod.__esModule) return mod; 129 | var result = {}; 130 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 131 | __setModuleDefault(result, mod); 132 | return result; 133 | }; 134 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 135 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 136 | return new (P || (P = Promise))(function (resolve, reject) { 137 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 138 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 139 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 140 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 141 | }); 142 | }; 143 | Object.defineProperty(exports, "__esModule", ({ value: true })); 144 | exports.platform = exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = exports.markdownSummary = exports.summary = exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; 145 | const command_1 = __webpack_require__(44914); 146 | const file_command_1 = __webpack_require__(24753); 147 | const utils_1 = __webpack_require__(30302); 148 | const os = __importStar(__webpack_require__(70857)); 149 | const path = __importStar(__webpack_require__(16928)); 150 | const oidc_utils_1 = __webpack_require__(35306); 151 | /** 152 | * The code to exit an action 153 | */ 154 | var ExitCode; 155 | (function (ExitCode) { 156 | /** 157 | * A code indicating that the action was successful 158 | */ 159 | ExitCode[ExitCode["Success"] = 0] = "Success"; 160 | /** 161 | * A code indicating that the action was a failure 162 | */ 163 | ExitCode[ExitCode["Failure"] = 1] = "Failure"; 164 | })(ExitCode || (exports.ExitCode = ExitCode = {})); 165 | //----------------------------------------------------------------------- 166 | // Variables 167 | //----------------------------------------------------------------------- 168 | /** 169 | * Sets env variable for this action and future actions in the job 170 | * @param name the name of the variable to set 171 | * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify 172 | */ 173 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 174 | function exportVariable(name, val) { 175 | const convertedVal = (0, utils_1.toCommandValue)(val); 176 | process.env[name] = convertedVal; 177 | const filePath = process.env['GITHUB_ENV'] || ''; 178 | if (filePath) { 179 | return (0, file_command_1.issueFileCommand)('ENV', (0, file_command_1.prepareKeyValueMessage)(name, val)); 180 | } 181 | (0, command_1.issueCommand)('set-env', { name }, convertedVal); 182 | } 183 | exports.exportVariable = exportVariable; 184 | /** 185 | * Registers a secret which will get masked from logs 186 | * @param secret value of the secret 187 | */ 188 | function setSecret(secret) { 189 | (0, command_1.issueCommand)('add-mask', {}, secret); 190 | } 191 | exports.setSecret = setSecret; 192 | /** 193 | * Prepends inputPath to the PATH (for this action and future actions) 194 | * @param inputPath 195 | */ 196 | function addPath(inputPath) { 197 | const filePath = process.env['GITHUB_PATH'] || ''; 198 | if (filePath) { 199 | (0, file_command_1.issueFileCommand)('PATH', inputPath); 200 | } 201 | else { 202 | (0, command_1.issueCommand)('add-path', {}, inputPath); 203 | } 204 | process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; 205 | } 206 | exports.addPath = addPath; 207 | /** 208 | * Gets the value of an input. 209 | * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. 210 | * Returns an empty string if the value is not defined. 211 | * 212 | * @param name name of the input to get 213 | * @param options optional. See InputOptions. 214 | * @returns string 215 | */ 216 | function getInput(name, options) { 217 | const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; 218 | if (options && options.required && !val) { 219 | throw new Error(`Input required and not supplied: ${name}`); 220 | } 221 | if (options && options.trimWhitespace === false) { 222 | return val; 223 | } 224 | return val.trim(); 225 | } 226 | exports.getInput = getInput; 227 | /** 228 | * Gets the values of an multiline input. Each value is also trimmed. 229 | * 230 | * @param name name of the input to get 231 | * @param options optional. See InputOptions. 232 | * @returns string[] 233 | * 234 | */ 235 | function getMultilineInput(name, options) { 236 | const inputs = getInput(name, options) 237 | .split('\n') 238 | .filter(x => x !== ''); 239 | if (options && options.trimWhitespace === false) { 240 | return inputs; 241 | } 242 | return inputs.map(input => input.trim()); 243 | } 244 | exports.getMultilineInput = getMultilineInput; 245 | /** 246 | * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. 247 | * Support boolean input list: `true | True | TRUE | false | False | FALSE` . 248 | * The return value is also in boolean type. 249 | * ref: https://yaml.org/spec/1.2/spec.html#id2804923 250 | * 251 | * @param name name of the input to get 252 | * @param options optional. See InputOptions. 253 | * @returns boolean 254 | */ 255 | function getBooleanInput(name, options) { 256 | const trueValue = ['true', 'True', 'TRUE']; 257 | const falseValue = ['false', 'False', 'FALSE']; 258 | const val = getInput(name, options); 259 | if (trueValue.includes(val)) 260 | return true; 261 | if (falseValue.includes(val)) 262 | return false; 263 | throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + 264 | `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); 265 | } 266 | exports.getBooleanInput = getBooleanInput; 267 | /** 268 | * Sets the value of an output. 269 | * 270 | * @param name name of the output to set 271 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify 272 | */ 273 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 274 | function setOutput(name, value) { 275 | const filePath = process.env['GITHUB_OUTPUT'] || ''; 276 | if (filePath) { 277 | return (0, file_command_1.issueFileCommand)('OUTPUT', (0, file_command_1.prepareKeyValueMessage)(name, value)); 278 | } 279 | process.stdout.write(os.EOL); 280 | (0, command_1.issueCommand)('set-output', { name }, (0, utils_1.toCommandValue)(value)); 281 | } 282 | exports.setOutput = setOutput; 283 | /** 284 | * Enables or disables the echoing of commands into stdout for the rest of the step. 285 | * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. 286 | * 287 | */ 288 | function setCommandEcho(enabled) { 289 | (0, command_1.issue)('echo', enabled ? 'on' : 'off'); 290 | } 291 | exports.setCommandEcho = setCommandEcho; 292 | //----------------------------------------------------------------------- 293 | // Results 294 | //----------------------------------------------------------------------- 295 | /** 296 | * Sets the action status to failed. 297 | * When the action exits it will be with an exit code of 1 298 | * @param message add error issue message 299 | */ 300 | function setFailed(message) { 301 | process.exitCode = ExitCode.Failure; 302 | error(message); 303 | } 304 | exports.setFailed = setFailed; 305 | //----------------------------------------------------------------------- 306 | // Logging Commands 307 | //----------------------------------------------------------------------- 308 | /** 309 | * Gets whether Actions Step Debug is on or not 310 | */ 311 | function isDebug() { 312 | return process.env['RUNNER_DEBUG'] === '1'; 313 | } 314 | exports.isDebug = isDebug; 315 | /** 316 | * Writes debug message to user log 317 | * @param message debug message 318 | */ 319 | function debug(message) { 320 | (0, command_1.issueCommand)('debug', {}, message); 321 | } 322 | exports.debug = debug; 323 | /** 324 | * Adds an error issue 325 | * @param message error issue message. Errors will be converted to string via toString() 326 | * @param properties optional properties to add to the annotation. 327 | */ 328 | function error(message, properties = {}) { 329 | (0, command_1.issueCommand)('error', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); 330 | } 331 | exports.error = error; 332 | /** 333 | * Adds a warning issue 334 | * @param message warning issue message. Errors will be converted to string via toString() 335 | * @param properties optional properties to add to the annotation. 336 | */ 337 | function warning(message, properties = {}) { 338 | (0, command_1.issueCommand)('warning', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); 339 | } 340 | exports.warning = warning; 341 | /** 342 | * Adds a notice issue 343 | * @param message notice issue message. Errors will be converted to string via toString() 344 | * @param properties optional properties to add to the annotation. 345 | */ 346 | function notice(message, properties = {}) { 347 | (0, command_1.issueCommand)('notice', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); 348 | } 349 | exports.notice = notice; 350 | /** 351 | * Writes info to log with console.log. 352 | * @param message info message 353 | */ 354 | function info(message) { 355 | process.stdout.write(message + os.EOL); 356 | } 357 | exports.info = info; 358 | /** 359 | * Begin an output group. 360 | * 361 | * Output until the next `groupEnd` will be foldable in this group 362 | * 363 | * @param name The name of the output group 364 | */ 365 | function startGroup(name) { 366 | (0, command_1.issue)('group', name); 367 | } 368 | exports.startGroup = startGroup; 369 | /** 370 | * End an output group. 371 | */ 372 | function endGroup() { 373 | (0, command_1.issue)('endgroup'); 374 | } 375 | exports.endGroup = endGroup; 376 | /** 377 | * Wrap an asynchronous function call in a group. 378 | * 379 | * Returns the same type as the function itself. 380 | * 381 | * @param name The name of the group 382 | * @param fn The function to wrap in the group 383 | */ 384 | function group(name, fn) { 385 | return __awaiter(this, void 0, void 0, function* () { 386 | startGroup(name); 387 | let result; 388 | try { 389 | result = yield fn(); 390 | } 391 | finally { 392 | endGroup(); 393 | } 394 | return result; 395 | }); 396 | } 397 | exports.group = group; 398 | //----------------------------------------------------------------------- 399 | // Wrapper action state 400 | //----------------------------------------------------------------------- 401 | /** 402 | * Saves state for current action, the state can only be retrieved by this action's post job execution. 403 | * 404 | * @param name name of the state to store 405 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify 406 | */ 407 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 408 | function saveState(name, value) { 409 | const filePath = process.env['GITHUB_STATE'] || ''; 410 | if (filePath) { 411 | return (0, file_command_1.issueFileCommand)('STATE', (0, file_command_1.prepareKeyValueMessage)(name, value)); 412 | } 413 | (0, command_1.issueCommand)('save-state', { name }, (0, utils_1.toCommandValue)(value)); 414 | } 415 | exports.saveState = saveState; 416 | /** 417 | * Gets the value of an state set by this action's main execution. 418 | * 419 | * @param name name of the state to get 420 | * @returns string 421 | */ 422 | function getState(name) { 423 | return process.env[`STATE_${name}`] || ''; 424 | } 425 | exports.getState = getState; 426 | function getIDToken(aud) { 427 | return __awaiter(this, void 0, void 0, function* () { 428 | return yield oidc_utils_1.OidcClient.getIDToken(aud); 429 | }); 430 | } 431 | exports.getIDToken = getIDToken; 432 | /** 433 | * Summary exports 434 | */ 435 | var summary_1 = __webpack_require__(71847); 436 | Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); 437 | /** 438 | * @deprecated use core.summary 439 | */ 440 | var summary_2 = __webpack_require__(71847); 441 | Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); 442 | /** 443 | * Path exports 444 | */ 445 | var path_utils_1 = __webpack_require__(31976); 446 | Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); 447 | Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); 448 | Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); 449 | /** 450 | * Platform utilities exports 451 | */ 452 | exports.platform = __importStar(__webpack_require__(18968)); 453 | //# sourceMappingURL=core.js.map 454 | 455 | /***/ }), 456 | 457 | /***/ 24753: 458 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 459 | 460 | 461 | // For internal use, subject to change. 462 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 463 | if (k2 === undefined) k2 = k; 464 | var desc = Object.getOwnPropertyDescriptor(m, k); 465 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 466 | desc = { enumerable: true, get: function() { return m[k]; } }; 467 | } 468 | Object.defineProperty(o, k2, desc); 469 | }) : (function(o, m, k, k2) { 470 | if (k2 === undefined) k2 = k; 471 | o[k2] = m[k]; 472 | })); 473 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 474 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 475 | }) : function(o, v) { 476 | o["default"] = v; 477 | }); 478 | var __importStar = (this && this.__importStar) || function (mod) { 479 | if (mod && mod.__esModule) return mod; 480 | var result = {}; 481 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 482 | __setModuleDefault(result, mod); 483 | return result; 484 | }; 485 | Object.defineProperty(exports, "__esModule", ({ value: true })); 486 | exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; 487 | // We use any as a valid input type 488 | /* eslint-disable @typescript-eslint/no-explicit-any */ 489 | const crypto = __importStar(__webpack_require__(76982)); 490 | const fs = __importStar(__webpack_require__(79896)); 491 | const os = __importStar(__webpack_require__(70857)); 492 | const utils_1 = __webpack_require__(30302); 493 | function issueFileCommand(command, message) { 494 | const filePath = process.env[`GITHUB_${command}`]; 495 | if (!filePath) { 496 | throw new Error(`Unable to find environment variable for file command ${command}`); 497 | } 498 | if (!fs.existsSync(filePath)) { 499 | throw new Error(`Missing file at path: ${filePath}`); 500 | } 501 | fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, { 502 | encoding: 'utf8' 503 | }); 504 | } 505 | exports.issueFileCommand = issueFileCommand; 506 | function prepareKeyValueMessage(key, value) { 507 | const delimiter = `ghadelimiter_${crypto.randomUUID()}`; 508 | const convertedValue = (0, utils_1.toCommandValue)(value); 509 | // These should realistically never happen, but just in case someone finds a 510 | // way to exploit uuid generation let's not allow keys or values that contain 511 | // the delimiter. 512 | if (key.includes(delimiter)) { 513 | throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); 514 | } 515 | if (convertedValue.includes(delimiter)) { 516 | throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); 517 | } 518 | return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; 519 | } 520 | exports.prepareKeyValueMessage = prepareKeyValueMessage; 521 | //# sourceMappingURL=file-command.js.map 522 | 523 | /***/ }), 524 | 525 | /***/ 35306: 526 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 527 | 528 | 529 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 530 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 531 | return new (P || (P = Promise))(function (resolve, reject) { 532 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 533 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 534 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 535 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 536 | }); 537 | }; 538 | Object.defineProperty(exports, "__esModule", ({ value: true })); 539 | exports.OidcClient = void 0; 540 | const http_client_1 = __webpack_require__(54844); 541 | const auth_1 = __webpack_require__(44552); 542 | const core_1 = __webpack_require__(37484); 543 | class OidcClient { 544 | static createHttpClient(allowRetry = true, maxRetry = 10) { 545 | const requestOptions = { 546 | allowRetries: allowRetry, 547 | maxRetries: maxRetry 548 | }; 549 | return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); 550 | } 551 | static getRequestToken() { 552 | const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; 553 | if (!token) { 554 | throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); 555 | } 556 | return token; 557 | } 558 | static getIDTokenUrl() { 559 | const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; 560 | if (!runtimeUrl) { 561 | throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); 562 | } 563 | return runtimeUrl; 564 | } 565 | static getCall(id_token_url) { 566 | var _a; 567 | return __awaiter(this, void 0, void 0, function* () { 568 | const httpclient = OidcClient.createHttpClient(); 569 | const res = yield httpclient 570 | .getJson(id_token_url) 571 | .catch(error => { 572 | throw new Error(`Failed to get ID Token. \n 573 | Error Code : ${error.statusCode}\n 574 | Error Message: ${error.message}`); 575 | }); 576 | const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; 577 | if (!id_token) { 578 | throw new Error('Response json body do not have ID Token field'); 579 | } 580 | return id_token; 581 | }); 582 | } 583 | static getIDToken(audience) { 584 | return __awaiter(this, void 0, void 0, function* () { 585 | try { 586 | // New ID Token is requested from action service 587 | let id_token_url = OidcClient.getIDTokenUrl(); 588 | if (audience) { 589 | const encodedAudience = encodeURIComponent(audience); 590 | id_token_url = `${id_token_url}&audience=${encodedAudience}`; 591 | } 592 | (0, core_1.debug)(`ID token url is ${id_token_url}`); 593 | const id_token = yield OidcClient.getCall(id_token_url); 594 | (0, core_1.setSecret)(id_token); 595 | return id_token; 596 | } 597 | catch (error) { 598 | throw new Error(`Error message: ${error.message}`); 599 | } 600 | }); 601 | } 602 | } 603 | exports.OidcClient = OidcClient; 604 | //# sourceMappingURL=oidc-utils.js.map 605 | 606 | /***/ }), 607 | 608 | /***/ 31976: 609 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 610 | 611 | 612 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 613 | if (k2 === undefined) k2 = k; 614 | var desc = Object.getOwnPropertyDescriptor(m, k); 615 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 616 | desc = { enumerable: true, get: function() { return m[k]; } }; 617 | } 618 | Object.defineProperty(o, k2, desc); 619 | }) : (function(o, m, k, k2) { 620 | if (k2 === undefined) k2 = k; 621 | o[k2] = m[k]; 622 | })); 623 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 624 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 625 | }) : function(o, v) { 626 | o["default"] = v; 627 | }); 628 | var __importStar = (this && this.__importStar) || function (mod) { 629 | if (mod && mod.__esModule) return mod; 630 | var result = {}; 631 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 632 | __setModuleDefault(result, mod); 633 | return result; 634 | }; 635 | Object.defineProperty(exports, "__esModule", ({ value: true })); 636 | exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; 637 | const path = __importStar(__webpack_require__(16928)); 638 | /** 639 | * toPosixPath converts the given path to the posix form. On Windows, \\ will be 640 | * replaced with /. 641 | * 642 | * @param pth. Path to transform. 643 | * @return string Posix path. 644 | */ 645 | function toPosixPath(pth) { 646 | return pth.replace(/[\\]/g, '/'); 647 | } 648 | exports.toPosixPath = toPosixPath; 649 | /** 650 | * toWin32Path converts the given path to the win32 form. On Linux, / will be 651 | * replaced with \\. 652 | * 653 | * @param pth. Path to transform. 654 | * @return string Win32 path. 655 | */ 656 | function toWin32Path(pth) { 657 | return pth.replace(/[/]/g, '\\'); 658 | } 659 | exports.toWin32Path = toWin32Path; 660 | /** 661 | * toPlatformPath converts the given path to a platform-specific path. It does 662 | * this by replacing instances of / and \ with the platform-specific path 663 | * separator. 664 | * 665 | * @param pth The path to platformize. 666 | * @return string The platform-specific path. 667 | */ 668 | function toPlatformPath(pth) { 669 | return pth.replace(/[/\\]/g, path.sep); 670 | } 671 | exports.toPlatformPath = toPlatformPath; 672 | //# sourceMappingURL=path-utils.js.map 673 | 674 | /***/ }), 675 | 676 | /***/ 18968: 677 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 678 | 679 | 680 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 681 | if (k2 === undefined) k2 = k; 682 | var desc = Object.getOwnPropertyDescriptor(m, k); 683 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 684 | desc = { enumerable: true, get: function() { return m[k]; } }; 685 | } 686 | Object.defineProperty(o, k2, desc); 687 | }) : (function(o, m, k, k2) { 688 | if (k2 === undefined) k2 = k; 689 | o[k2] = m[k]; 690 | })); 691 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 692 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 693 | }) : function(o, v) { 694 | o["default"] = v; 695 | }); 696 | var __importStar = (this && this.__importStar) || function (mod) { 697 | if (mod && mod.__esModule) return mod; 698 | var result = {}; 699 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 700 | __setModuleDefault(result, mod); 701 | return result; 702 | }; 703 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 704 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 705 | return new (P || (P = Promise))(function (resolve, reject) { 706 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 707 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 708 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 709 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 710 | }); 711 | }; 712 | var __importDefault = (this && this.__importDefault) || function (mod) { 713 | return (mod && mod.__esModule) ? mod : { "default": mod }; 714 | }; 715 | Object.defineProperty(exports, "__esModule", ({ value: true })); 716 | exports.getDetails = exports.isLinux = exports.isMacOS = exports.isWindows = exports.arch = exports.platform = void 0; 717 | const os_1 = __importDefault(__webpack_require__(70857)); 718 | const exec = __importStar(__webpack_require__(95236)); 719 | const getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () { 720 | const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, { 721 | silent: true 722 | }); 723 | const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, { 724 | silent: true 725 | }); 726 | return { 727 | name: name.trim(), 728 | version: version.trim() 729 | }; 730 | }); 731 | const getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () { 732 | var _a, _b, _c, _d; 733 | const { stdout } = yield exec.getExecOutput('sw_vers', undefined, { 734 | silent: true 735 | }); 736 | const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; 737 | const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; 738 | return { 739 | name, 740 | version 741 | }; 742 | }); 743 | const getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () { 744 | const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { 745 | silent: true 746 | }); 747 | const [name, version] = stdout.trim().split('\n'); 748 | return { 749 | name, 750 | version 751 | }; 752 | }); 753 | exports.platform = os_1.default.platform(); 754 | exports.arch = os_1.default.arch(); 755 | exports.isWindows = exports.platform === 'win32'; 756 | exports.isMacOS = exports.platform === 'darwin'; 757 | exports.isLinux = exports.platform === 'linux'; 758 | function getDetails() { 759 | return __awaiter(this, void 0, void 0, function* () { 760 | return Object.assign(Object.assign({}, (yield (exports.isWindows 761 | ? getWindowsInfo() 762 | : exports.isMacOS 763 | ? getMacOsInfo() 764 | : getLinuxInfo()))), { platform: exports.platform, 765 | arch: exports.arch, 766 | isWindows: exports.isWindows, 767 | isMacOS: exports.isMacOS, 768 | isLinux: exports.isLinux }); 769 | }); 770 | } 771 | exports.getDetails = getDetails; 772 | //# sourceMappingURL=platform.js.map 773 | 774 | /***/ }), 775 | 776 | /***/ 71847: 777 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 778 | 779 | 780 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 781 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 782 | return new (P || (P = Promise))(function (resolve, reject) { 783 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 784 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 785 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 786 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 787 | }); 788 | }; 789 | Object.defineProperty(exports, "__esModule", ({ value: true })); 790 | exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; 791 | const os_1 = __webpack_require__(70857); 792 | const fs_1 = __webpack_require__(79896); 793 | const { access, appendFile, writeFile } = fs_1.promises; 794 | exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; 795 | exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; 796 | class Summary { 797 | constructor() { 798 | this._buffer = ''; 799 | } 800 | /** 801 | * Finds the summary file path from the environment, rejects if env var is not found or file does not exist 802 | * Also checks r/w permissions. 803 | * 804 | * @returns step summary file path 805 | */ 806 | filePath() { 807 | return __awaiter(this, void 0, void 0, function* () { 808 | if (this._filePath) { 809 | return this._filePath; 810 | } 811 | const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; 812 | if (!pathFromEnv) { 813 | throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); 814 | } 815 | try { 816 | yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); 817 | } 818 | catch (_a) { 819 | throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); 820 | } 821 | this._filePath = pathFromEnv; 822 | return this._filePath; 823 | }); 824 | } 825 | /** 826 | * Wraps content in an HTML tag, adding any HTML attributes 827 | * 828 | * @param {string} tag HTML tag to wrap 829 | * @param {string | null} content content within the tag 830 | * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add 831 | * 832 | * @returns {string} content wrapped in HTML element 833 | */ 834 | wrap(tag, content, attrs = {}) { 835 | const htmlAttrs = Object.entries(attrs) 836 | .map(([key, value]) => ` ${key}="${value}"`) 837 | .join(''); 838 | if (!content) { 839 | return `<${tag}${htmlAttrs}>`; 840 | } 841 | return `<${tag}${htmlAttrs}>${content}`; 842 | } 843 | /** 844 | * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. 845 | * 846 | * @param {SummaryWriteOptions} [options] (optional) options for write operation 847 | * 848 | * @returns {Promise} summary instance 849 | */ 850 | write(options) { 851 | return __awaiter(this, void 0, void 0, function* () { 852 | const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); 853 | const filePath = yield this.filePath(); 854 | const writeFunc = overwrite ? writeFile : appendFile; 855 | yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); 856 | return this.emptyBuffer(); 857 | }); 858 | } 859 | /** 860 | * Clears the summary buffer and wipes the summary file 861 | * 862 | * @returns {Summary} summary instance 863 | */ 864 | clear() { 865 | return __awaiter(this, void 0, void 0, function* () { 866 | return this.emptyBuffer().write({ overwrite: true }); 867 | }); 868 | } 869 | /** 870 | * Returns the current summary buffer as a string 871 | * 872 | * @returns {string} string of summary buffer 873 | */ 874 | stringify() { 875 | return this._buffer; 876 | } 877 | /** 878 | * If the summary buffer is empty 879 | * 880 | * @returns {boolen} true if the buffer is empty 881 | */ 882 | isEmptyBuffer() { 883 | return this._buffer.length === 0; 884 | } 885 | /** 886 | * Resets the summary buffer without writing to summary file 887 | * 888 | * @returns {Summary} summary instance 889 | */ 890 | emptyBuffer() { 891 | this._buffer = ''; 892 | return this; 893 | } 894 | /** 895 | * Adds raw text to the summary buffer 896 | * 897 | * @param {string} text content to add 898 | * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) 899 | * 900 | * @returns {Summary} summary instance 901 | */ 902 | addRaw(text, addEOL = false) { 903 | this._buffer += text; 904 | return addEOL ? this.addEOL() : this; 905 | } 906 | /** 907 | * Adds the operating system-specific end-of-line marker to the buffer 908 | * 909 | * @returns {Summary} summary instance 910 | */ 911 | addEOL() { 912 | return this.addRaw(os_1.EOL); 913 | } 914 | /** 915 | * Adds an HTML codeblock to the summary buffer 916 | * 917 | * @param {string} code content to render within fenced code block 918 | * @param {string} lang (optional) language to syntax highlight code 919 | * 920 | * @returns {Summary} summary instance 921 | */ 922 | addCodeBlock(code, lang) { 923 | const attrs = Object.assign({}, (lang && { lang })); 924 | const element = this.wrap('pre', this.wrap('code', code), attrs); 925 | return this.addRaw(element).addEOL(); 926 | } 927 | /** 928 | * Adds an HTML list to the summary buffer 929 | * 930 | * @param {string[]} items list of items to render 931 | * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) 932 | * 933 | * @returns {Summary} summary instance 934 | */ 935 | addList(items, ordered = false) { 936 | const tag = ordered ? 'ol' : 'ul'; 937 | const listItems = items.map(item => this.wrap('li', item)).join(''); 938 | const element = this.wrap(tag, listItems); 939 | return this.addRaw(element).addEOL(); 940 | } 941 | /** 942 | * Adds an HTML table to the summary buffer 943 | * 944 | * @param {SummaryTableCell[]} rows table rows 945 | * 946 | * @returns {Summary} summary instance 947 | */ 948 | addTable(rows) { 949 | const tableBody = rows 950 | .map(row => { 951 | const cells = row 952 | .map(cell => { 953 | if (typeof cell === 'string') { 954 | return this.wrap('td', cell); 955 | } 956 | const { header, data, colspan, rowspan } = cell; 957 | const tag = header ? 'th' : 'td'; 958 | const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); 959 | return this.wrap(tag, data, attrs); 960 | }) 961 | .join(''); 962 | return this.wrap('tr', cells); 963 | }) 964 | .join(''); 965 | const element = this.wrap('table', tableBody); 966 | return this.addRaw(element).addEOL(); 967 | } 968 | /** 969 | * Adds a collapsable HTML details element to the summary buffer 970 | * 971 | * @param {string} label text for the closed state 972 | * @param {string} content collapsable content 973 | * 974 | * @returns {Summary} summary instance 975 | */ 976 | addDetails(label, content) { 977 | const element = this.wrap('details', this.wrap('summary', label) + content); 978 | return this.addRaw(element).addEOL(); 979 | } 980 | /** 981 | * Adds an HTML image tag to the summary buffer 982 | * 983 | * @param {string} src path to the image you to embed 984 | * @param {string} alt text description of the image 985 | * @param {SummaryImageOptions} options (optional) addition image attributes 986 | * 987 | * @returns {Summary} summary instance 988 | */ 989 | addImage(src, alt, options) { 990 | const { width, height } = options || {}; 991 | const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); 992 | const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); 993 | return this.addRaw(element).addEOL(); 994 | } 995 | /** 996 | * Adds an HTML section heading element 997 | * 998 | * @param {string} text heading text 999 | * @param {number | string} [level=1] (optional) the heading level, default: 1 1000 | * 1001 | * @returns {Summary} summary instance 1002 | */ 1003 | addHeading(text, level) { 1004 | const tag = `h${level}`; 1005 | const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) 1006 | ? tag 1007 | : 'h1'; 1008 | const element = this.wrap(allowedTag, text); 1009 | return this.addRaw(element).addEOL(); 1010 | } 1011 | /** 1012 | * Adds an HTML thematic break (
) to the summary buffer 1013 | * 1014 | * @returns {Summary} summary instance 1015 | */ 1016 | addSeparator() { 1017 | const element = this.wrap('hr', null); 1018 | return this.addRaw(element).addEOL(); 1019 | } 1020 | /** 1021 | * Adds an HTML line break (
) to the summary buffer 1022 | * 1023 | * @returns {Summary} summary instance 1024 | */ 1025 | addBreak() { 1026 | const element = this.wrap('br', null); 1027 | return this.addRaw(element).addEOL(); 1028 | } 1029 | /** 1030 | * Adds an HTML blockquote to the summary buffer 1031 | * 1032 | * @param {string} text quote text 1033 | * @param {string} cite (optional) citation url 1034 | * 1035 | * @returns {Summary} summary instance 1036 | */ 1037 | addQuote(text, cite) { 1038 | const attrs = Object.assign({}, (cite && { cite })); 1039 | const element = this.wrap('blockquote', text, attrs); 1040 | return this.addRaw(element).addEOL(); 1041 | } 1042 | /** 1043 | * Adds an HTML anchor tag to the summary buffer 1044 | * 1045 | * @param {string} text link text/content 1046 | * @param {string} href hyperlink 1047 | * 1048 | * @returns {Summary} summary instance 1049 | */ 1050 | addLink(text, href) { 1051 | const element = this.wrap('a', text, { href }); 1052 | return this.addRaw(element).addEOL(); 1053 | } 1054 | } 1055 | const _summary = new Summary(); 1056 | /** 1057 | * @deprecated use `core.summary` 1058 | */ 1059 | exports.markdownSummary = _summary; 1060 | exports.summary = _summary; 1061 | //# sourceMappingURL=summary.js.map 1062 | 1063 | /***/ }), 1064 | 1065 | /***/ 30302: 1066 | /***/ ((__unused_webpack_module, exports) => { 1067 | 1068 | 1069 | // We use any as a valid input type 1070 | /* eslint-disable @typescript-eslint/no-explicit-any */ 1071 | Object.defineProperty(exports, "__esModule", ({ value: true })); 1072 | exports.toCommandProperties = exports.toCommandValue = void 0; 1073 | /** 1074 | * Sanitizes an input into a string so it can be passed into issueCommand safely 1075 | * @param input input to sanitize into a string 1076 | */ 1077 | function toCommandValue(input) { 1078 | if (input === null || input === undefined) { 1079 | return ''; 1080 | } 1081 | else if (typeof input === 'string' || input instanceof String) { 1082 | return input; 1083 | } 1084 | return JSON.stringify(input); 1085 | } 1086 | exports.toCommandValue = toCommandValue; 1087 | /** 1088 | * 1089 | * @param annotationProperties 1090 | * @returns The command properties to send with the actual annotation command 1091 | * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 1092 | */ 1093 | function toCommandProperties(annotationProperties) { 1094 | if (!Object.keys(annotationProperties).length) { 1095 | return {}; 1096 | } 1097 | return { 1098 | title: annotationProperties.title, 1099 | file: annotationProperties.file, 1100 | line: annotationProperties.startLine, 1101 | endLine: annotationProperties.endLine, 1102 | col: annotationProperties.startColumn, 1103 | endColumn: annotationProperties.endColumn 1104 | }; 1105 | } 1106 | exports.toCommandProperties = toCommandProperties; 1107 | //# sourceMappingURL=utils.js.map 1108 | 1109 | /***/ }), 1110 | 1111 | /***/ 95236: 1112 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 1113 | 1114 | 1115 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 1116 | if (k2 === undefined) k2 = k; 1117 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 1118 | }) : (function(o, m, k, k2) { 1119 | if (k2 === undefined) k2 = k; 1120 | o[k2] = m[k]; 1121 | })); 1122 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 1123 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 1124 | }) : function(o, v) { 1125 | o["default"] = v; 1126 | }); 1127 | var __importStar = (this && this.__importStar) || function (mod) { 1128 | if (mod && mod.__esModule) return mod; 1129 | var result = {}; 1130 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 1131 | __setModuleDefault(result, mod); 1132 | return result; 1133 | }; 1134 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1135 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1136 | return new (P || (P = Promise))(function (resolve, reject) { 1137 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1138 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1139 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1140 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1141 | }); 1142 | }; 1143 | Object.defineProperty(exports, "__esModule", ({ value: true })); 1144 | exports.getExecOutput = exports.exec = void 0; 1145 | const string_decoder_1 = __webpack_require__(13193); 1146 | const tr = __importStar(__webpack_require__(6665)); 1147 | /** 1148 | * Exec a command. 1149 | * Output will be streamed to the live console. 1150 | * Returns promise with return code 1151 | * 1152 | * @param commandLine command to execute (can include additional args). Must be correctly escaped. 1153 | * @param args optional arguments for tool. Escaping is handled by the lib. 1154 | * @param options optional exec options. See ExecOptions 1155 | * @returns Promise exit code 1156 | */ 1157 | function exec(commandLine, args, options) { 1158 | return __awaiter(this, void 0, void 0, function* () { 1159 | const commandArgs = tr.argStringToArray(commandLine); 1160 | if (commandArgs.length === 0) { 1161 | throw new Error(`Parameter 'commandLine' cannot be null or empty.`); 1162 | } 1163 | // Path to tool to execute should be first arg 1164 | const toolPath = commandArgs[0]; 1165 | args = commandArgs.slice(1).concat(args || []); 1166 | const runner = new tr.ToolRunner(toolPath, args, options); 1167 | return runner.exec(); 1168 | }); 1169 | } 1170 | exports.exec = exec; 1171 | /** 1172 | * Exec a command and get the output. 1173 | * Output will be streamed to the live console. 1174 | * Returns promise with the exit code and collected stdout and stderr 1175 | * 1176 | * @param commandLine command to execute (can include additional args). Must be correctly escaped. 1177 | * @param args optional arguments for tool. Escaping is handled by the lib. 1178 | * @param options optional exec options. See ExecOptions 1179 | * @returns Promise exit code, stdout, and stderr 1180 | */ 1181 | function getExecOutput(commandLine, args, options) { 1182 | var _a, _b; 1183 | return __awaiter(this, void 0, void 0, function* () { 1184 | let stdout = ''; 1185 | let stderr = ''; 1186 | //Using string decoder covers the case where a mult-byte character is split 1187 | const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); 1188 | const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); 1189 | const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; 1190 | const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; 1191 | const stdErrListener = (data) => { 1192 | stderr += stderrDecoder.write(data); 1193 | if (originalStdErrListener) { 1194 | originalStdErrListener(data); 1195 | } 1196 | }; 1197 | const stdOutListener = (data) => { 1198 | stdout += stdoutDecoder.write(data); 1199 | if (originalStdoutListener) { 1200 | originalStdoutListener(data); 1201 | } 1202 | }; 1203 | const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); 1204 | const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); 1205 | //flush any remaining characters 1206 | stdout += stdoutDecoder.end(); 1207 | stderr += stderrDecoder.end(); 1208 | return { 1209 | exitCode, 1210 | stdout, 1211 | stderr 1212 | }; 1213 | }); 1214 | } 1215 | exports.getExecOutput = getExecOutput; 1216 | //# sourceMappingURL=exec.js.map 1217 | 1218 | /***/ }), 1219 | 1220 | /***/ 6665: 1221 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 1222 | 1223 | 1224 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 1225 | if (k2 === undefined) k2 = k; 1226 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 1227 | }) : (function(o, m, k, k2) { 1228 | if (k2 === undefined) k2 = k; 1229 | o[k2] = m[k]; 1230 | })); 1231 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 1232 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 1233 | }) : function(o, v) { 1234 | o["default"] = v; 1235 | }); 1236 | var __importStar = (this && this.__importStar) || function (mod) { 1237 | if (mod && mod.__esModule) return mod; 1238 | var result = {}; 1239 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 1240 | __setModuleDefault(result, mod); 1241 | return result; 1242 | }; 1243 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1244 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1245 | return new (P || (P = Promise))(function (resolve, reject) { 1246 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1247 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1248 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1249 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1250 | }); 1251 | }; 1252 | Object.defineProperty(exports, "__esModule", ({ value: true })); 1253 | exports.argStringToArray = exports.ToolRunner = void 0; 1254 | const os = __importStar(__webpack_require__(70857)); 1255 | const events = __importStar(__webpack_require__(24434)); 1256 | const child = __importStar(__webpack_require__(35317)); 1257 | const path = __importStar(__webpack_require__(16928)); 1258 | const io = __importStar(__webpack_require__(94994)); 1259 | const ioUtil = __importStar(__webpack_require__(75207)); 1260 | const timers_1 = __webpack_require__(53557); 1261 | /* eslint-disable @typescript-eslint/unbound-method */ 1262 | const IS_WINDOWS = process.platform === 'win32'; 1263 | /* 1264 | * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. 1265 | */ 1266 | class ToolRunner extends events.EventEmitter { 1267 | constructor(toolPath, args, options) { 1268 | super(); 1269 | if (!toolPath) { 1270 | throw new Error("Parameter 'toolPath' cannot be null or empty."); 1271 | } 1272 | this.toolPath = toolPath; 1273 | this.args = args || []; 1274 | this.options = options || {}; 1275 | } 1276 | _debug(message) { 1277 | if (this.options.listeners && this.options.listeners.debug) { 1278 | this.options.listeners.debug(message); 1279 | } 1280 | } 1281 | _getCommandString(options, noPrefix) { 1282 | const toolPath = this._getSpawnFileName(); 1283 | const args = this._getSpawnArgs(options); 1284 | let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool 1285 | if (IS_WINDOWS) { 1286 | // Windows + cmd file 1287 | if (this._isCmdFile()) { 1288 | cmd += toolPath; 1289 | for (const a of args) { 1290 | cmd += ` ${a}`; 1291 | } 1292 | } 1293 | // Windows + verbatim 1294 | else if (options.windowsVerbatimArguments) { 1295 | cmd += `"${toolPath}"`; 1296 | for (const a of args) { 1297 | cmd += ` ${a}`; 1298 | } 1299 | } 1300 | // Windows (regular) 1301 | else { 1302 | cmd += this._windowsQuoteCmdArg(toolPath); 1303 | for (const a of args) { 1304 | cmd += ` ${this._windowsQuoteCmdArg(a)}`; 1305 | } 1306 | } 1307 | } 1308 | else { 1309 | // OSX/Linux - this can likely be improved with some form of quoting. 1310 | // creating processes on Unix is fundamentally different than Windows. 1311 | // on Unix, execvp() takes an arg array. 1312 | cmd += toolPath; 1313 | for (const a of args) { 1314 | cmd += ` ${a}`; 1315 | } 1316 | } 1317 | return cmd; 1318 | } 1319 | _processLineBuffer(data, strBuffer, onLine) { 1320 | try { 1321 | let s = strBuffer + data.toString(); 1322 | let n = s.indexOf(os.EOL); 1323 | while (n > -1) { 1324 | const line = s.substring(0, n); 1325 | onLine(line); 1326 | // the rest of the string ... 1327 | s = s.substring(n + os.EOL.length); 1328 | n = s.indexOf(os.EOL); 1329 | } 1330 | return s; 1331 | } 1332 | catch (err) { 1333 | // streaming lines to console is best effort. Don't fail a build. 1334 | this._debug(`error processing line. Failed with error ${err}`); 1335 | return ''; 1336 | } 1337 | } 1338 | _getSpawnFileName() { 1339 | if (IS_WINDOWS) { 1340 | if (this._isCmdFile()) { 1341 | return process.env['COMSPEC'] || 'cmd.exe'; 1342 | } 1343 | } 1344 | return this.toolPath; 1345 | } 1346 | _getSpawnArgs(options) { 1347 | if (IS_WINDOWS) { 1348 | if (this._isCmdFile()) { 1349 | let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; 1350 | for (const a of this.args) { 1351 | argline += ' '; 1352 | argline += options.windowsVerbatimArguments 1353 | ? a 1354 | : this._windowsQuoteCmdArg(a); 1355 | } 1356 | argline += '"'; 1357 | return [argline]; 1358 | } 1359 | } 1360 | return this.args; 1361 | } 1362 | _endsWith(str, end) { 1363 | return str.endsWith(end); 1364 | } 1365 | _isCmdFile() { 1366 | const upperToolPath = this.toolPath.toUpperCase(); 1367 | return (this._endsWith(upperToolPath, '.CMD') || 1368 | this._endsWith(upperToolPath, '.BAT')); 1369 | } 1370 | _windowsQuoteCmdArg(arg) { 1371 | // for .exe, apply the normal quoting rules that libuv applies 1372 | if (!this._isCmdFile()) { 1373 | return this._uvQuoteCmdArg(arg); 1374 | } 1375 | // otherwise apply quoting rules specific to the cmd.exe command line parser. 1376 | // the libuv rules are generic and are not designed specifically for cmd.exe 1377 | // command line parser. 1378 | // 1379 | // for a detailed description of the cmd.exe command line parser, refer to 1380 | // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 1381 | // need quotes for empty arg 1382 | if (!arg) { 1383 | return '""'; 1384 | } 1385 | // determine whether the arg needs to be quoted 1386 | const cmdSpecialChars = [ 1387 | ' ', 1388 | '\t', 1389 | '&', 1390 | '(', 1391 | ')', 1392 | '[', 1393 | ']', 1394 | '{', 1395 | '}', 1396 | '^', 1397 | '=', 1398 | ';', 1399 | '!', 1400 | "'", 1401 | '+', 1402 | ',', 1403 | '`', 1404 | '~', 1405 | '|', 1406 | '<', 1407 | '>', 1408 | '"' 1409 | ]; 1410 | let needsQuotes = false; 1411 | for (const char of arg) { 1412 | if (cmdSpecialChars.some(x => x === char)) { 1413 | needsQuotes = true; 1414 | break; 1415 | } 1416 | } 1417 | // short-circuit if quotes not needed 1418 | if (!needsQuotes) { 1419 | return arg; 1420 | } 1421 | // the following quoting rules are very similar to the rules that by libuv applies. 1422 | // 1423 | // 1) wrap the string in quotes 1424 | // 1425 | // 2) double-up quotes - i.e. " => "" 1426 | // 1427 | // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately 1428 | // doesn't work well with a cmd.exe command line. 1429 | // 1430 | // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. 1431 | // for example, the command line: 1432 | // foo.exe "myarg:""my val""" 1433 | // is parsed by a .NET console app into an arg array: 1434 | // [ "myarg:\"my val\"" ] 1435 | // which is the same end result when applying libuv quoting rules. although the actual 1436 | // command line from libuv quoting rules would look like: 1437 | // foo.exe "myarg:\"my val\"" 1438 | // 1439 | // 3) double-up slashes that precede a quote, 1440 | // e.g. hello \world => "hello \world" 1441 | // hello\"world => "hello\\""world" 1442 | // hello\\"world => "hello\\\\""world" 1443 | // hello world\ => "hello world\\" 1444 | // 1445 | // technically this is not required for a cmd.exe command line, or the batch argument parser. 1446 | // the reasons for including this as a .cmd quoting rule are: 1447 | // 1448 | // a) this is optimized for the scenario where the argument is passed from the .cmd file to an 1449 | // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. 1450 | // 1451 | // b) it's what we've been doing previously (by deferring to node default behavior) and we 1452 | // haven't heard any complaints about that aspect. 1453 | // 1454 | // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be 1455 | // escaped when used on the command line directly - even though within a .cmd file % can be escaped 1456 | // by using %%. 1457 | // 1458 | // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts 1459 | // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. 1460 | // 1461 | // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would 1462 | // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the 1463 | // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args 1464 | // to an external program. 1465 | // 1466 | // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. 1467 | // % can be escaped within a .cmd file. 1468 | let reverse = '"'; 1469 | let quoteHit = true; 1470 | for (let i = arg.length; i > 0; i--) { 1471 | // walk the string in reverse 1472 | reverse += arg[i - 1]; 1473 | if (quoteHit && arg[i - 1] === '\\') { 1474 | reverse += '\\'; // double the slash 1475 | } 1476 | else if (arg[i - 1] === '"') { 1477 | quoteHit = true; 1478 | reverse += '"'; // double the quote 1479 | } 1480 | else { 1481 | quoteHit = false; 1482 | } 1483 | } 1484 | reverse += '"'; 1485 | return reverse 1486 | .split('') 1487 | .reverse() 1488 | .join(''); 1489 | } 1490 | _uvQuoteCmdArg(arg) { 1491 | // Tool runner wraps child_process.spawn() and needs to apply the same quoting as 1492 | // Node in certain cases where the undocumented spawn option windowsVerbatimArguments 1493 | // is used. 1494 | // 1495 | // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, 1496 | // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), 1497 | // pasting copyright notice from Node within this function: 1498 | // 1499 | // Copyright Joyent, Inc. and other Node contributors. All rights reserved. 1500 | // 1501 | // Permission is hereby granted, free of charge, to any person obtaining a copy 1502 | // of this software and associated documentation files (the "Software"), to 1503 | // deal in the Software without restriction, including without limitation the 1504 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1505 | // sell copies of the Software, and to permit persons to whom the Software is 1506 | // furnished to do so, subject to the following conditions: 1507 | // 1508 | // The above copyright notice and this permission notice shall be included in 1509 | // all copies or substantial portions of the Software. 1510 | // 1511 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1512 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1513 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1514 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1515 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1516 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 1517 | // IN THE SOFTWARE. 1518 | if (!arg) { 1519 | // Need double quotation for empty argument 1520 | return '""'; 1521 | } 1522 | if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { 1523 | // No quotation needed 1524 | return arg; 1525 | } 1526 | if (!arg.includes('"') && !arg.includes('\\')) { 1527 | // No embedded double quotes or backslashes, so I can just wrap 1528 | // quote marks around the whole thing. 1529 | return `"${arg}"`; 1530 | } 1531 | // Expected input/output: 1532 | // input : hello"world 1533 | // output: "hello\"world" 1534 | // input : hello""world 1535 | // output: "hello\"\"world" 1536 | // input : hello\world 1537 | // output: hello\world 1538 | // input : hello\\world 1539 | // output: hello\\world 1540 | // input : hello\"world 1541 | // output: "hello\\\"world" 1542 | // input : hello\\"world 1543 | // output: "hello\\\\\"world" 1544 | // input : hello world\ 1545 | // output: "hello world\\" - note the comment in libuv actually reads "hello world\" 1546 | // but it appears the comment is wrong, it should be "hello world\\" 1547 | let reverse = '"'; 1548 | let quoteHit = true; 1549 | for (let i = arg.length; i > 0; i--) { 1550 | // walk the string in reverse 1551 | reverse += arg[i - 1]; 1552 | if (quoteHit && arg[i - 1] === '\\') { 1553 | reverse += '\\'; 1554 | } 1555 | else if (arg[i - 1] === '"') { 1556 | quoteHit = true; 1557 | reverse += '\\'; 1558 | } 1559 | else { 1560 | quoteHit = false; 1561 | } 1562 | } 1563 | reverse += '"'; 1564 | return reverse 1565 | .split('') 1566 | .reverse() 1567 | .join(''); 1568 | } 1569 | _cloneExecOptions(options) { 1570 | options = options || {}; 1571 | const result = { 1572 | cwd: options.cwd || process.cwd(), 1573 | env: options.env || process.env, 1574 | silent: options.silent || false, 1575 | windowsVerbatimArguments: options.windowsVerbatimArguments || false, 1576 | failOnStdErr: options.failOnStdErr || false, 1577 | ignoreReturnCode: options.ignoreReturnCode || false, 1578 | delay: options.delay || 10000 1579 | }; 1580 | result.outStream = options.outStream || process.stdout; 1581 | result.errStream = options.errStream || process.stderr; 1582 | return result; 1583 | } 1584 | _getSpawnOptions(options, toolPath) { 1585 | options = options || {}; 1586 | const result = {}; 1587 | result.cwd = options.cwd; 1588 | result.env = options.env; 1589 | result['windowsVerbatimArguments'] = 1590 | options.windowsVerbatimArguments || this._isCmdFile(); 1591 | if (options.windowsVerbatimArguments) { 1592 | result.argv0 = `"${toolPath}"`; 1593 | } 1594 | return result; 1595 | } 1596 | /** 1597 | * Exec a tool. 1598 | * Output will be streamed to the live console. 1599 | * Returns promise with return code 1600 | * 1601 | * @param tool path to tool to exec 1602 | * @param options optional exec options. See ExecOptions 1603 | * @returns number 1604 | */ 1605 | exec() { 1606 | return __awaiter(this, void 0, void 0, function* () { 1607 | // root the tool path if it is unrooted and contains relative pathing 1608 | if (!ioUtil.isRooted(this.toolPath) && 1609 | (this.toolPath.includes('/') || 1610 | (IS_WINDOWS && this.toolPath.includes('\\')))) { 1611 | // prefer options.cwd if it is specified, however options.cwd may also need to be rooted 1612 | this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); 1613 | } 1614 | // if the tool is only a file name, then resolve it from the PATH 1615 | // otherwise verify it exists (add extension on Windows if necessary) 1616 | this.toolPath = yield io.which(this.toolPath, true); 1617 | return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { 1618 | this._debug(`exec tool: ${this.toolPath}`); 1619 | this._debug('arguments:'); 1620 | for (const arg of this.args) { 1621 | this._debug(` ${arg}`); 1622 | } 1623 | const optionsNonNull = this._cloneExecOptions(this.options); 1624 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 1625 | optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); 1626 | } 1627 | const state = new ExecState(optionsNonNull, this.toolPath); 1628 | state.on('debug', (message) => { 1629 | this._debug(message); 1630 | }); 1631 | if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { 1632 | return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); 1633 | } 1634 | const fileName = this._getSpawnFileName(); 1635 | const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); 1636 | let stdbuffer = ''; 1637 | if (cp.stdout) { 1638 | cp.stdout.on('data', (data) => { 1639 | if (this.options.listeners && this.options.listeners.stdout) { 1640 | this.options.listeners.stdout(data); 1641 | } 1642 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 1643 | optionsNonNull.outStream.write(data); 1644 | } 1645 | stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { 1646 | if (this.options.listeners && this.options.listeners.stdline) { 1647 | this.options.listeners.stdline(line); 1648 | } 1649 | }); 1650 | }); 1651 | } 1652 | let errbuffer = ''; 1653 | if (cp.stderr) { 1654 | cp.stderr.on('data', (data) => { 1655 | state.processStderr = true; 1656 | if (this.options.listeners && this.options.listeners.stderr) { 1657 | this.options.listeners.stderr(data); 1658 | } 1659 | if (!optionsNonNull.silent && 1660 | optionsNonNull.errStream && 1661 | optionsNonNull.outStream) { 1662 | const s = optionsNonNull.failOnStdErr 1663 | ? optionsNonNull.errStream 1664 | : optionsNonNull.outStream; 1665 | s.write(data); 1666 | } 1667 | errbuffer = this._processLineBuffer(data, errbuffer, (line) => { 1668 | if (this.options.listeners && this.options.listeners.errline) { 1669 | this.options.listeners.errline(line); 1670 | } 1671 | }); 1672 | }); 1673 | } 1674 | cp.on('error', (err) => { 1675 | state.processError = err.message; 1676 | state.processExited = true; 1677 | state.processClosed = true; 1678 | state.CheckComplete(); 1679 | }); 1680 | cp.on('exit', (code) => { 1681 | state.processExitCode = code; 1682 | state.processExited = true; 1683 | this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); 1684 | state.CheckComplete(); 1685 | }); 1686 | cp.on('close', (code) => { 1687 | state.processExitCode = code; 1688 | state.processExited = true; 1689 | state.processClosed = true; 1690 | this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); 1691 | state.CheckComplete(); 1692 | }); 1693 | state.on('done', (error, exitCode) => { 1694 | if (stdbuffer.length > 0) { 1695 | this.emit('stdline', stdbuffer); 1696 | } 1697 | if (errbuffer.length > 0) { 1698 | this.emit('errline', errbuffer); 1699 | } 1700 | cp.removeAllListeners(); 1701 | if (error) { 1702 | reject(error); 1703 | } 1704 | else { 1705 | resolve(exitCode); 1706 | } 1707 | }); 1708 | if (this.options.input) { 1709 | if (!cp.stdin) { 1710 | throw new Error('child process missing stdin'); 1711 | } 1712 | cp.stdin.end(this.options.input); 1713 | } 1714 | })); 1715 | }); 1716 | } 1717 | } 1718 | exports.ToolRunner = ToolRunner; 1719 | /** 1720 | * Convert an arg string to an array of args. Handles escaping 1721 | * 1722 | * @param argString string of arguments 1723 | * @returns string[] array of arguments 1724 | */ 1725 | function argStringToArray(argString) { 1726 | const args = []; 1727 | let inQuotes = false; 1728 | let escaped = false; 1729 | let arg = ''; 1730 | function append(c) { 1731 | // we only escape double quotes. 1732 | if (escaped && c !== '"') { 1733 | arg += '\\'; 1734 | } 1735 | arg += c; 1736 | escaped = false; 1737 | } 1738 | for (let i = 0; i < argString.length; i++) { 1739 | const c = argString.charAt(i); 1740 | if (c === '"') { 1741 | if (!escaped) { 1742 | inQuotes = !inQuotes; 1743 | } 1744 | else { 1745 | append(c); 1746 | } 1747 | continue; 1748 | } 1749 | if (c === '\\' && escaped) { 1750 | append(c); 1751 | continue; 1752 | } 1753 | if (c === '\\' && inQuotes) { 1754 | escaped = true; 1755 | continue; 1756 | } 1757 | if (c === ' ' && !inQuotes) { 1758 | if (arg.length > 0) { 1759 | args.push(arg); 1760 | arg = ''; 1761 | } 1762 | continue; 1763 | } 1764 | append(c); 1765 | } 1766 | if (arg.length > 0) { 1767 | args.push(arg.trim()); 1768 | } 1769 | return args; 1770 | } 1771 | exports.argStringToArray = argStringToArray; 1772 | class ExecState extends events.EventEmitter { 1773 | constructor(options, toolPath) { 1774 | super(); 1775 | this.processClosed = false; // tracks whether the process has exited and stdio is closed 1776 | this.processError = ''; 1777 | this.processExitCode = 0; 1778 | this.processExited = false; // tracks whether the process has exited 1779 | this.processStderr = false; // tracks whether stderr was written to 1780 | this.delay = 10000; // 10 seconds 1781 | this.done = false; 1782 | this.timeout = null; 1783 | if (!toolPath) { 1784 | throw new Error('toolPath must not be empty'); 1785 | } 1786 | this.options = options; 1787 | this.toolPath = toolPath; 1788 | if (options.delay) { 1789 | this.delay = options.delay; 1790 | } 1791 | } 1792 | CheckComplete() { 1793 | if (this.done) { 1794 | return; 1795 | } 1796 | if (this.processClosed) { 1797 | this._setResult(); 1798 | } 1799 | else if (this.processExited) { 1800 | this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); 1801 | } 1802 | } 1803 | _debug(message) { 1804 | this.emit('debug', message); 1805 | } 1806 | _setResult() { 1807 | // determine whether there is an error 1808 | let error; 1809 | if (this.processExited) { 1810 | if (this.processError) { 1811 | error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); 1812 | } 1813 | else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { 1814 | error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); 1815 | } 1816 | else if (this.processStderr && this.options.failOnStdErr) { 1817 | error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); 1818 | } 1819 | } 1820 | // clear the timeout 1821 | if (this.timeout) { 1822 | clearTimeout(this.timeout); 1823 | this.timeout = null; 1824 | } 1825 | this.done = true; 1826 | this.emit('done', error, this.processExitCode); 1827 | } 1828 | static HandleTimeout(state) { 1829 | if (state.done) { 1830 | return; 1831 | } 1832 | if (!state.processClosed && state.processExited) { 1833 | const message = `The STDIO streams did not close within ${state.delay / 1834 | 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; 1835 | state._debug(message); 1836 | } 1837 | state._setResult(); 1838 | } 1839 | } 1840 | //# sourceMappingURL=toolrunner.js.map 1841 | 1842 | /***/ }), 1843 | 1844 | /***/ 44552: 1845 | /***/ (function(__unused_webpack_module, exports) { 1846 | 1847 | 1848 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1849 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1850 | return new (P || (P = Promise))(function (resolve, reject) { 1851 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1852 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1853 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1854 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1855 | }); 1856 | }; 1857 | Object.defineProperty(exports, "__esModule", ({ value: true })); 1858 | exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; 1859 | class BasicCredentialHandler { 1860 | constructor(username, password) { 1861 | this.username = username; 1862 | this.password = password; 1863 | } 1864 | prepareRequest(options) { 1865 | if (!options.headers) { 1866 | throw Error('The request has no headers'); 1867 | } 1868 | options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; 1869 | } 1870 | // This handler cannot handle 401 1871 | canHandleAuthentication() { 1872 | return false; 1873 | } 1874 | handleAuthentication() { 1875 | return __awaiter(this, void 0, void 0, function* () { 1876 | throw new Error('not implemented'); 1877 | }); 1878 | } 1879 | } 1880 | exports.BasicCredentialHandler = BasicCredentialHandler; 1881 | class BearerCredentialHandler { 1882 | constructor(token) { 1883 | this.token = token; 1884 | } 1885 | // currently implements pre-authorization 1886 | // TODO: support preAuth = false where it hooks on 401 1887 | prepareRequest(options) { 1888 | if (!options.headers) { 1889 | throw Error('The request has no headers'); 1890 | } 1891 | options.headers['Authorization'] = `Bearer ${this.token}`; 1892 | } 1893 | // This handler cannot handle 401 1894 | canHandleAuthentication() { 1895 | return false; 1896 | } 1897 | handleAuthentication() { 1898 | return __awaiter(this, void 0, void 0, function* () { 1899 | throw new Error('not implemented'); 1900 | }); 1901 | } 1902 | } 1903 | exports.BearerCredentialHandler = BearerCredentialHandler; 1904 | class PersonalAccessTokenCredentialHandler { 1905 | constructor(token) { 1906 | this.token = token; 1907 | } 1908 | // currently implements pre-authorization 1909 | // TODO: support preAuth = false where it hooks on 401 1910 | prepareRequest(options) { 1911 | if (!options.headers) { 1912 | throw Error('The request has no headers'); 1913 | } 1914 | options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; 1915 | } 1916 | // This handler cannot handle 401 1917 | canHandleAuthentication() { 1918 | return false; 1919 | } 1920 | handleAuthentication() { 1921 | return __awaiter(this, void 0, void 0, function* () { 1922 | throw new Error('not implemented'); 1923 | }); 1924 | } 1925 | } 1926 | exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; 1927 | //# sourceMappingURL=auth.js.map 1928 | 1929 | /***/ }), 1930 | 1931 | /***/ 75207: 1932 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 1933 | 1934 | 1935 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 1936 | if (k2 === undefined) k2 = k; 1937 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 1938 | }) : (function(o, m, k, k2) { 1939 | if (k2 === undefined) k2 = k; 1940 | o[k2] = m[k]; 1941 | })); 1942 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 1943 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 1944 | }) : function(o, v) { 1945 | o["default"] = v; 1946 | }); 1947 | var __importStar = (this && this.__importStar) || function (mod) { 1948 | if (mod && mod.__esModule) return mod; 1949 | var result = {}; 1950 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 1951 | __setModuleDefault(result, mod); 1952 | return result; 1953 | }; 1954 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1955 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1956 | return new (P || (P = Promise))(function (resolve, reject) { 1957 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1958 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1959 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1960 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1961 | }); 1962 | }; 1963 | var _a; 1964 | Object.defineProperty(exports, "__esModule", ({ value: true })); 1965 | exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; 1966 | const fs = __importStar(__webpack_require__(79896)); 1967 | const path = __importStar(__webpack_require__(16928)); 1968 | _a = fs.promises 1969 | // export const {open} = 'fs' 1970 | , exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; 1971 | // export const {open} = 'fs' 1972 | exports.IS_WINDOWS = process.platform === 'win32'; 1973 | // See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 1974 | exports.UV_FS_O_EXLOCK = 0x10000000; 1975 | exports.READONLY = fs.constants.O_RDONLY; 1976 | function exists(fsPath) { 1977 | return __awaiter(this, void 0, void 0, function* () { 1978 | try { 1979 | yield exports.stat(fsPath); 1980 | } 1981 | catch (err) { 1982 | if (err.code === 'ENOENT') { 1983 | return false; 1984 | } 1985 | throw err; 1986 | } 1987 | return true; 1988 | }); 1989 | } 1990 | exports.exists = exists; 1991 | function isDirectory(fsPath, useStat = false) { 1992 | return __awaiter(this, void 0, void 0, function* () { 1993 | const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); 1994 | return stats.isDirectory(); 1995 | }); 1996 | } 1997 | exports.isDirectory = isDirectory; 1998 | /** 1999 | * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: 2000 | * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). 2001 | */ 2002 | function isRooted(p) { 2003 | p = normalizeSeparators(p); 2004 | if (!p) { 2005 | throw new Error('isRooted() parameter "p" cannot be empty'); 2006 | } 2007 | if (exports.IS_WINDOWS) { 2008 | return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello 2009 | ); // e.g. C: or C:\hello 2010 | } 2011 | return p.startsWith('/'); 2012 | } 2013 | exports.isRooted = isRooted; 2014 | /** 2015 | * Best effort attempt to determine whether a file exists and is executable. 2016 | * @param filePath file path to check 2017 | * @param extensions additional file extensions to try 2018 | * @return if file exists and is executable, returns the file path. otherwise empty string. 2019 | */ 2020 | function tryGetExecutablePath(filePath, extensions) { 2021 | return __awaiter(this, void 0, void 0, function* () { 2022 | let stats = undefined; 2023 | try { 2024 | // test file exists 2025 | stats = yield exports.stat(filePath); 2026 | } 2027 | catch (err) { 2028 | if (err.code !== 'ENOENT') { 2029 | // eslint-disable-next-line no-console 2030 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 2031 | } 2032 | } 2033 | if (stats && stats.isFile()) { 2034 | if (exports.IS_WINDOWS) { 2035 | // on Windows, test for valid extension 2036 | const upperExt = path.extname(filePath).toUpperCase(); 2037 | if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { 2038 | return filePath; 2039 | } 2040 | } 2041 | else { 2042 | if (isUnixExecutable(stats)) { 2043 | return filePath; 2044 | } 2045 | } 2046 | } 2047 | // try each extension 2048 | const originalFilePath = filePath; 2049 | for (const extension of extensions) { 2050 | filePath = originalFilePath + extension; 2051 | stats = undefined; 2052 | try { 2053 | stats = yield exports.stat(filePath); 2054 | } 2055 | catch (err) { 2056 | if (err.code !== 'ENOENT') { 2057 | // eslint-disable-next-line no-console 2058 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 2059 | } 2060 | } 2061 | if (stats && stats.isFile()) { 2062 | if (exports.IS_WINDOWS) { 2063 | // preserve the case of the actual file (since an extension was appended) 2064 | try { 2065 | const directory = path.dirname(filePath); 2066 | const upperName = path.basename(filePath).toUpperCase(); 2067 | for (const actualName of yield exports.readdir(directory)) { 2068 | if (upperName === actualName.toUpperCase()) { 2069 | filePath = path.join(directory, actualName); 2070 | break; 2071 | } 2072 | } 2073 | } 2074 | catch (err) { 2075 | // eslint-disable-next-line no-console 2076 | console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); 2077 | } 2078 | return filePath; 2079 | } 2080 | else { 2081 | if (isUnixExecutable(stats)) { 2082 | return filePath; 2083 | } 2084 | } 2085 | } 2086 | } 2087 | return ''; 2088 | }); 2089 | } 2090 | exports.tryGetExecutablePath = tryGetExecutablePath; 2091 | function normalizeSeparators(p) { 2092 | p = p || ''; 2093 | if (exports.IS_WINDOWS) { 2094 | // convert slashes on Windows 2095 | p = p.replace(/\//g, '\\'); 2096 | // remove redundant slashes 2097 | return p.replace(/\\\\+/g, '\\'); 2098 | } 2099 | // remove redundant slashes 2100 | return p.replace(/\/\/+/g, '/'); 2101 | } 2102 | // on Mac/Linux, test the execute bit 2103 | // R W X R W X R W X 2104 | // 256 128 64 32 16 8 4 2 1 2105 | function isUnixExecutable(stats) { 2106 | return ((stats.mode & 1) > 0 || 2107 | ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || 2108 | ((stats.mode & 64) > 0 && stats.uid === process.getuid())); 2109 | } 2110 | // Get the path of cmd.exe in windows 2111 | function getCmdPath() { 2112 | var _a; 2113 | return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; 2114 | } 2115 | exports.getCmdPath = getCmdPath; 2116 | //# sourceMappingURL=io-util.js.map 2117 | 2118 | /***/ }), 2119 | 2120 | /***/ 94994: 2121 | /***/ (function(__unused_webpack_module, exports, __webpack_require__) { 2122 | 2123 | 2124 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 2125 | if (k2 === undefined) k2 = k; 2126 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 2127 | }) : (function(o, m, k, k2) { 2128 | if (k2 === undefined) k2 = k; 2129 | o[k2] = m[k]; 2130 | })); 2131 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 2132 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 2133 | }) : function(o, v) { 2134 | o["default"] = v; 2135 | }); 2136 | var __importStar = (this && this.__importStar) || function (mod) { 2137 | if (mod && mod.__esModule) return mod; 2138 | var result = {}; 2139 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 2140 | __setModuleDefault(result, mod); 2141 | return result; 2142 | }; 2143 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2144 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 2145 | return new (P || (P = Promise))(function (resolve, reject) { 2146 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 2147 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 2148 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 2149 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 2150 | }); 2151 | }; 2152 | Object.defineProperty(exports, "__esModule", ({ value: true })); 2153 | exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; 2154 | const assert_1 = __webpack_require__(42613); 2155 | const path = __importStar(__webpack_require__(16928)); 2156 | const ioUtil = __importStar(__webpack_require__(75207)); 2157 | /** 2158 | * Copies a file or folder. 2159 | * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js 2160 | * 2161 | * @param source source path 2162 | * @param dest destination path 2163 | * @param options optional. See CopyOptions. 2164 | */ 2165 | function cp(source, dest, options = {}) { 2166 | return __awaiter(this, void 0, void 0, function* () { 2167 | const { force, recursive, copySourceDirectory } = readCopyOptions(options); 2168 | const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; 2169 | // Dest is an existing file, but not forcing 2170 | if (destStat && destStat.isFile() && !force) { 2171 | return; 2172 | } 2173 | // If dest is an existing directory, should copy inside. 2174 | const newDest = destStat && destStat.isDirectory() && copySourceDirectory 2175 | ? path.join(dest, path.basename(source)) 2176 | : dest; 2177 | if (!(yield ioUtil.exists(source))) { 2178 | throw new Error(`no such file or directory: ${source}`); 2179 | } 2180 | const sourceStat = yield ioUtil.stat(source); 2181 | if (sourceStat.isDirectory()) { 2182 | if (!recursive) { 2183 | throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); 2184 | } 2185 | else { 2186 | yield cpDirRecursive(source, newDest, 0, force); 2187 | } 2188 | } 2189 | else { 2190 | if (path.relative(source, newDest) === '') { 2191 | // a file cannot be copied to itself 2192 | throw new Error(`'${newDest}' and '${source}' are the same file`); 2193 | } 2194 | yield copyFile(source, newDest, force); 2195 | } 2196 | }); 2197 | } 2198 | exports.cp = cp; 2199 | /** 2200 | * Moves a path. 2201 | * 2202 | * @param source source path 2203 | * @param dest destination path 2204 | * @param options optional. See MoveOptions. 2205 | */ 2206 | function mv(source, dest, options = {}) { 2207 | return __awaiter(this, void 0, void 0, function* () { 2208 | if (yield ioUtil.exists(dest)) { 2209 | let destExists = true; 2210 | if (yield ioUtil.isDirectory(dest)) { 2211 | // If dest is directory copy src into dest 2212 | dest = path.join(dest, path.basename(source)); 2213 | destExists = yield ioUtil.exists(dest); 2214 | } 2215 | if (destExists) { 2216 | if (options.force == null || options.force) { 2217 | yield rmRF(dest); 2218 | } 2219 | else { 2220 | throw new Error('Destination already exists'); 2221 | } 2222 | } 2223 | } 2224 | yield mkdirP(path.dirname(dest)); 2225 | yield ioUtil.rename(source, dest); 2226 | }); 2227 | } 2228 | exports.mv = mv; 2229 | /** 2230 | * Remove a path recursively with force 2231 | * 2232 | * @param inputPath path to remove 2233 | */ 2234 | function rmRF(inputPath) { 2235 | return __awaiter(this, void 0, void 0, function* () { 2236 | if (ioUtil.IS_WINDOWS) { 2237 | // Check for invalid characters 2238 | // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file 2239 | if (/[*"<>|]/.test(inputPath)) { 2240 | throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); 2241 | } 2242 | } 2243 | try { 2244 | // note if path does not exist, error is silent 2245 | yield ioUtil.rm(inputPath, { 2246 | force: true, 2247 | maxRetries: 3, 2248 | recursive: true, 2249 | retryDelay: 300 2250 | }); 2251 | } 2252 | catch (err) { 2253 | throw new Error(`File was unable to be removed ${err}`); 2254 | } 2255 | }); 2256 | } 2257 | exports.rmRF = rmRF; 2258 | /** 2259 | * Make a directory. Creates the full path with folders in between 2260 | * Will throw if it fails 2261 | * 2262 | * @param fsPath path to create 2263 | * @returns Promise 2264 | */ 2265 | function mkdirP(fsPath) { 2266 | return __awaiter(this, void 0, void 0, function* () { 2267 | assert_1.ok(fsPath, 'a path argument must be provided'); 2268 | yield ioUtil.mkdir(fsPath, { recursive: true }); 2269 | }); 2270 | } 2271 | exports.mkdirP = mkdirP; 2272 | /** 2273 | * Returns path of a tool had the tool actually been invoked. Resolves via paths. 2274 | * If you check and the tool does not exist, it will throw. 2275 | * 2276 | * @param tool name of the tool 2277 | * @param check whether to check if tool exists 2278 | * @returns Promise path to tool 2279 | */ 2280 | function which(tool, check) { 2281 | return __awaiter(this, void 0, void 0, function* () { 2282 | if (!tool) { 2283 | throw new Error("parameter 'tool' is required"); 2284 | } 2285 | // recursive when check=true 2286 | if (check) { 2287 | const result = yield which(tool, false); 2288 | if (!result) { 2289 | if (ioUtil.IS_WINDOWS) { 2290 | throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); 2291 | } 2292 | else { 2293 | throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); 2294 | } 2295 | } 2296 | return result; 2297 | } 2298 | const matches = yield findInPath(tool); 2299 | if (matches && matches.length > 0) { 2300 | return matches[0]; 2301 | } 2302 | return ''; 2303 | }); 2304 | } 2305 | exports.which = which; 2306 | /** 2307 | * Returns a list of all occurrences of the given tool on the system path. 2308 | * 2309 | * @returns Promise the paths of the tool 2310 | */ 2311 | function findInPath(tool) { 2312 | return __awaiter(this, void 0, void 0, function* () { 2313 | if (!tool) { 2314 | throw new Error("parameter 'tool' is required"); 2315 | } 2316 | // build the list of extensions to try 2317 | const extensions = []; 2318 | if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { 2319 | for (const extension of process.env['PATHEXT'].split(path.delimiter)) { 2320 | if (extension) { 2321 | extensions.push(extension); 2322 | } 2323 | } 2324 | } 2325 | // if it's rooted, return it if exists. otherwise return empty. 2326 | if (ioUtil.isRooted(tool)) { 2327 | const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); 2328 | if (filePath) { 2329 | return [filePath]; 2330 | } 2331 | return []; 2332 | } 2333 | // if any path separators, return empty 2334 | if (tool.includes(path.sep)) { 2335 | return []; 2336 | } 2337 | // build the list of directories 2338 | // 2339 | // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, 2340 | // it feels like we should not do this. Checking the current directory seems like more of a use 2341 | // case of a shell, and the which() function exposed by the toolkit should strive for consistency 2342 | // across platforms. 2343 | const directories = []; 2344 | if (process.env.PATH) { 2345 | for (const p of process.env.PATH.split(path.delimiter)) { 2346 | if (p) { 2347 | directories.push(p); 2348 | } 2349 | } 2350 | } 2351 | // find all matches 2352 | const matches = []; 2353 | for (const directory of directories) { 2354 | const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); 2355 | if (filePath) { 2356 | matches.push(filePath); 2357 | } 2358 | } 2359 | return matches; 2360 | }); 2361 | } 2362 | exports.findInPath = findInPath; 2363 | function readCopyOptions(options) { 2364 | const force = options.force == null ? true : options.force; 2365 | const recursive = Boolean(options.recursive); 2366 | const copySourceDirectory = options.copySourceDirectory == null 2367 | ? true 2368 | : Boolean(options.copySourceDirectory); 2369 | return { force, recursive, copySourceDirectory }; 2370 | } 2371 | function cpDirRecursive(sourceDir, destDir, currentDepth, force) { 2372 | return __awaiter(this, void 0, void 0, function* () { 2373 | // Ensure there is not a run away recursive copy 2374 | if (currentDepth >= 255) 2375 | return; 2376 | currentDepth++; 2377 | yield mkdirP(destDir); 2378 | const files = yield ioUtil.readdir(sourceDir); 2379 | for (const fileName of files) { 2380 | const srcFile = `${sourceDir}/${fileName}`; 2381 | const destFile = `${destDir}/${fileName}`; 2382 | const srcFileStat = yield ioUtil.lstat(srcFile); 2383 | if (srcFileStat.isDirectory()) { 2384 | // Recurse 2385 | yield cpDirRecursive(srcFile, destFile, currentDepth, force); 2386 | } 2387 | else { 2388 | yield copyFile(srcFile, destFile, force); 2389 | } 2390 | } 2391 | // Change the mode for the newly created directory 2392 | yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); 2393 | }); 2394 | } 2395 | // Buffered file copy 2396 | function copyFile(srcFile, destFile, force) { 2397 | return __awaiter(this, void 0, void 0, function* () { 2398 | if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { 2399 | // unlink/re-link it 2400 | try { 2401 | yield ioUtil.lstat(destFile); 2402 | yield ioUtil.unlink(destFile); 2403 | } 2404 | catch (e) { 2405 | // Try to override file permission 2406 | if (e.code === 'EPERM') { 2407 | yield ioUtil.chmod(destFile, '0666'); 2408 | yield ioUtil.unlink(destFile); 2409 | } 2410 | // other errors = it doesn't exist, no work to do 2411 | } 2412 | // Copy over symlink 2413 | const symlinkFull = yield ioUtil.readlink(srcFile); 2414 | yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); 2415 | } 2416 | else if (!(yield ioUtil.exists(destFile)) || force) { 2417 | yield ioUtil.copyFile(srcFile, destFile); 2418 | } 2419 | }); 2420 | } 2421 | //# sourceMappingURL=io.js.map 2422 | 2423 | /***/ }) 2424 | 2425 | }; 2426 | -------------------------------------------------------------------------------- /dist/596.index.js: -------------------------------------------------------------------------------- 1 | export const id = 596; 2 | export const ids = [596]; 3 | export const modules = { 4 | 5 | /***/ 43596: 6 | /***/ ((__unused_webpack_module, exports, __webpack_require__) => { 7 | 8 | var fs = __webpack_require__(79896) 9 | 10 | var wx = 'wx' 11 | if (process.version.match(/^v0\.[0-6]/)) { 12 | var c = __webpack_require__(49140) 13 | wx = c.O_TRUNC | c.O_CREAT | c.O_WRONLY | c.O_EXCL 14 | } 15 | 16 | var os = __webpack_require__(70857) 17 | exports.filetime = 'ctime' 18 | if (os.platform() == "win32") { 19 | exports.filetime = 'mtime' 20 | } 21 | 22 | var debug 23 | var util = __webpack_require__(39023) 24 | if (util.debuglog) 25 | debug = util.debuglog('LOCKFILE') 26 | else if (/\blockfile\b/i.test(process.env.NODE_DEBUG)) 27 | debug = function() { 28 | var msg = util.format.apply(util, arguments) 29 | console.error('LOCKFILE %d %s', process.pid, msg) 30 | } 31 | else 32 | debug = function() {} 33 | 34 | var locks = {} 35 | 36 | function hasOwnProperty (obj, prop) { 37 | return Object.prototype.hasOwnProperty.call(obj, prop) 38 | } 39 | 40 | var onExit = __webpack_require__(66627) 41 | onExit(function () { 42 | debug('exit listener') 43 | // cleanup 44 | Object.keys(locks).forEach(exports.unlockSync) 45 | }) 46 | 47 | // XXX https://github.com/joyent/node/issues/3555 48 | // Remove when node 0.8 is deprecated. 49 | if (/^v0\.[0-8]\./.test(process.version)) { 50 | debug('uncaughtException, version = %s', process.version) 51 | process.on('uncaughtException', function H (er) { 52 | debug('uncaughtException') 53 | var l = process.listeners('uncaughtException').filter(function (h) { 54 | return h !== H 55 | }) 56 | if (!l.length) { 57 | // cleanup 58 | try { Object.keys(locks).forEach(exports.unlockSync) } catch (e) {} 59 | process.removeListener('uncaughtException', H) 60 | throw er 61 | } 62 | }) 63 | } 64 | 65 | exports.unlock = function (path, cb) { 66 | debug('unlock', path) 67 | // best-effort. unlocking an already-unlocked lock is a noop 68 | delete locks[path] 69 | fs.unlink(path, function (unlinkEr) { cb && cb() }) 70 | } 71 | 72 | exports.unlockSync = function (path) { 73 | debug('unlockSync', path) 74 | // best-effort. unlocking an already-unlocked lock is a noop 75 | try { fs.unlinkSync(path) } catch (er) {} 76 | delete locks[path] 77 | } 78 | 79 | 80 | // if the file can be opened in readonly mode, then it's there. 81 | // if the error is something other than ENOENT, then it's not. 82 | exports.check = function (path, opts, cb) { 83 | if (typeof opts === 'function') cb = opts, opts = {} 84 | debug('check', path, opts) 85 | fs.open(path, 'r', function (er, fd) { 86 | if (er) { 87 | if (er.code !== 'ENOENT') return cb(er) 88 | return cb(null, false) 89 | } 90 | 91 | if (!opts.stale) { 92 | return fs.close(fd, function (er) { 93 | return cb(er, true) 94 | }) 95 | } 96 | 97 | fs.fstat(fd, function (er, st) { 98 | if (er) return fs.close(fd, function (er2) { 99 | return cb(er) 100 | }) 101 | 102 | fs.close(fd, function (er) { 103 | var age = Date.now() - st[exports.filetime].getTime() 104 | return cb(er, age <= opts.stale) 105 | }) 106 | }) 107 | }) 108 | } 109 | 110 | exports.checkSync = function (path, opts) { 111 | opts = opts || {} 112 | debug('checkSync', path, opts) 113 | if (opts.wait) { 114 | throw new Error('opts.wait not supported sync for obvious reasons') 115 | } 116 | 117 | try { 118 | var fd = fs.openSync(path, 'r') 119 | } catch (er) { 120 | if (er.code !== 'ENOENT') throw er 121 | return false 122 | } 123 | 124 | if (!opts.stale) { 125 | try { fs.closeSync(fd) } catch (er) {} 126 | return true 127 | } 128 | 129 | // file exists. however, might be stale 130 | if (opts.stale) { 131 | try { 132 | var st = fs.fstatSync(fd) 133 | } finally { 134 | fs.closeSync(fd) 135 | } 136 | var age = Date.now() - st[exports.filetime].getTime() 137 | return (age <= opts.stale) 138 | } 139 | } 140 | 141 | 142 | 143 | var req = 1 144 | exports.lock = function (path, opts, cb) { 145 | if (typeof opts === 'function') cb = opts, opts = {} 146 | opts.req = opts.req || req++ 147 | debug('lock', path, opts) 148 | opts.start = opts.start || Date.now() 149 | 150 | if (typeof opts.retries === 'number' && opts.retries > 0) { 151 | debug('has retries', opts.retries) 152 | var retries = opts.retries 153 | opts.retries = 0 154 | cb = (function (orig) { return function cb (er, fd) { 155 | debug('retry-mutated callback') 156 | retries -= 1 157 | if (!er || retries < 0) return orig(er, fd) 158 | 159 | debug('lock retry', path, opts) 160 | 161 | if (opts.retryWait) setTimeout(retry, opts.retryWait) 162 | else retry() 163 | 164 | function retry () { 165 | opts.start = Date.now() 166 | debug('retrying', opts.start) 167 | exports.lock(path, opts, cb) 168 | } 169 | }})(cb) 170 | } 171 | 172 | // try to engage the lock. 173 | // if this succeeds, then we're in business. 174 | fs.open(path, wx, function (er, fd) { 175 | if (!er) { 176 | debug('locked', path, fd) 177 | locks[path] = fd 178 | return fs.close(fd, function () { 179 | return cb() 180 | }) 181 | } 182 | 183 | debug('failed to acquire lock', er) 184 | 185 | // something other than "currently locked" 186 | // maybe eperm or something. 187 | if (er.code !== 'EEXIST') { 188 | debug('not EEXIST error', er) 189 | return cb(er) 190 | } 191 | 192 | // someone's got this one. see if it's valid. 193 | if (!opts.stale) return notStale(er, path, opts, cb) 194 | 195 | return maybeStale(er, path, opts, false, cb) 196 | }) 197 | debug('lock return') 198 | } 199 | 200 | 201 | // Staleness checking algorithm 202 | // 1. acquire $lock, fail 203 | // 2. stat $lock, find that it is stale 204 | // 3. acquire $lock.STALE 205 | // 4. stat $lock, assert that it is still stale 206 | // 5. unlink $lock 207 | // 6. link $lock.STALE $lock 208 | // 7. unlink $lock.STALE 209 | // On any failure, clean up whatever we've done, and raise the error. 210 | function maybeStale (originalEr, path, opts, hasStaleLock, cb) { 211 | fs.stat(path, function (statEr, st) { 212 | if (statEr) { 213 | if (statEr.code === 'ENOENT') { 214 | // expired already! 215 | opts.stale = false 216 | debug('lock stale enoent retry', path, opts) 217 | exports.lock(path, opts, cb) 218 | return 219 | } 220 | return cb(statEr) 221 | } 222 | 223 | var age = Date.now() - st[exports.filetime].getTime() 224 | if (age <= opts.stale) return notStale(originalEr, path, opts, cb) 225 | 226 | debug('lock stale', path, opts) 227 | if (hasStaleLock) { 228 | exports.unlock(path, function (er) { 229 | if (er) return cb(er) 230 | debug('lock stale retry', path, opts) 231 | fs.link(path + '.STALE', path, function (er) { 232 | fs.unlink(path + '.STALE', function () { 233 | // best effort. if the unlink fails, oh well. 234 | cb(er) 235 | }) 236 | }) 237 | }) 238 | } else { 239 | debug('acquire .STALE file lock', opts) 240 | exports.lock(path + '.STALE', opts, function (er) { 241 | if (er) return cb(er) 242 | maybeStale(originalEr, path, opts, true, cb) 243 | }) 244 | } 245 | }) 246 | } 247 | 248 | function notStale (er, path, opts, cb) { 249 | debug('notStale', path, opts) 250 | 251 | // if we can't wait, then just call it a failure 252 | if (typeof opts.wait !== 'number' || opts.wait <= 0) { 253 | debug('notStale, wait is not a number') 254 | return cb(er) 255 | } 256 | 257 | // poll for some ms for the lock to clear 258 | var now = Date.now() 259 | var start = opts.start || now 260 | var end = start + opts.wait 261 | 262 | if (end <= now) 263 | return cb(er) 264 | 265 | debug('now=%d, wait until %d (delta=%d)', start, end, end-start) 266 | var wait = Math.min(end - start, opts.pollPeriod || 100) 267 | var timer = setTimeout(poll, wait) 268 | 269 | function poll () { 270 | debug('notStale, polling', path, opts) 271 | exports.lock(path, opts, cb) 272 | } 273 | } 274 | 275 | exports.lockSync = function (path, opts) { 276 | opts = opts || {} 277 | opts.req = opts.req || req++ 278 | debug('lockSync', path, opts) 279 | if (opts.wait || opts.retryWait) { 280 | throw new Error('opts.wait not supported sync for obvious reasons') 281 | } 282 | 283 | try { 284 | var fd = fs.openSync(path, wx) 285 | locks[path] = fd 286 | try { fs.closeSync(fd) } catch (er) {} 287 | debug('locked sync!', path, fd) 288 | return 289 | } catch (er) { 290 | if (er.code !== 'EEXIST') return retryThrow(path, opts, er) 291 | 292 | if (opts.stale) { 293 | var st = fs.statSync(path) 294 | var ct = st[exports.filetime].getTime() 295 | if (!(ct % 1000) && (opts.stale % 1000)) { 296 | // probably don't have subsecond resolution. 297 | // round up the staleness indicator. 298 | // Yes, this will be wrong 1/1000 times on platforms 299 | // with subsecond stat precision, but that's acceptable 300 | // in exchange for not mistakenly removing locks on 301 | // most other systems. 302 | opts.stale = 1000 * Math.ceil(opts.stale / 1000) 303 | } 304 | var age = Date.now() - ct 305 | if (age > opts.stale) { 306 | debug('lockSync stale', path, opts, age) 307 | exports.unlockSync(path) 308 | return exports.lockSync(path, opts) 309 | } 310 | } 311 | 312 | // failed to lock! 313 | debug('failed to lock', path, opts, er) 314 | return retryThrow(path, opts, er) 315 | } 316 | } 317 | 318 | function retryThrow (path, opts, er) { 319 | if (typeof opts.retries === 'number' && opts.retries > 0) { 320 | var newRT = opts.retries - 1 321 | debug('retryThrow', path, opts, newRT) 322 | opts.retries = newRT 323 | return exports.lockSync(path, opts) 324 | } 325 | throw er 326 | } 327 | 328 | 329 | 330 | /***/ }), 331 | 332 | /***/ 66627: 333 | /***/ ((module, __unused_webpack_exports, __webpack_require__) => { 334 | 335 | // Note: since nyc uses this module to output coverage, any lines 336 | // that are in the direct sync flow of nyc's outputCoverage are 337 | // ignored, since we can never get coverage for them. 338 | // grab a reference to node's real process object right away 339 | var process = global.process 340 | 341 | const processOk = function (process) { 342 | return process && 343 | typeof process === 'object' && 344 | typeof process.removeListener === 'function' && 345 | typeof process.emit === 'function' && 346 | typeof process.reallyExit === 'function' && 347 | typeof process.listeners === 'function' && 348 | typeof process.kill === 'function' && 349 | typeof process.pid === 'number' && 350 | typeof process.on === 'function' 351 | } 352 | 353 | // some kind of non-node environment, just no-op 354 | /* istanbul ignore if */ 355 | if (!processOk(process)) { 356 | module.exports = function () { 357 | return function () {} 358 | } 359 | } else { 360 | var assert = __webpack_require__(42613) 361 | var signals = __webpack_require__(41430) 362 | var isWin = /^win/i.test(process.platform) 363 | 364 | var EE = __webpack_require__(24434) 365 | /* istanbul ignore if */ 366 | if (typeof EE !== 'function') { 367 | EE = EE.EventEmitter 368 | } 369 | 370 | var emitter 371 | if (process.__signal_exit_emitter__) { 372 | emitter = process.__signal_exit_emitter__ 373 | } else { 374 | emitter = process.__signal_exit_emitter__ = new EE() 375 | emitter.count = 0 376 | emitter.emitted = {} 377 | } 378 | 379 | // Because this emitter is a global, we have to check to see if a 380 | // previous version of this library failed to enable infinite listeners. 381 | // I know what you're about to say. But literally everything about 382 | // signal-exit is a compromise with evil. Get used to it. 383 | if (!emitter.infinite) { 384 | emitter.setMaxListeners(Infinity) 385 | emitter.infinite = true 386 | } 387 | 388 | module.exports = function (cb, opts) { 389 | /* istanbul ignore if */ 390 | if (!processOk(global.process)) { 391 | return function () {} 392 | } 393 | assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') 394 | 395 | if (loaded === false) { 396 | load() 397 | } 398 | 399 | var ev = 'exit' 400 | if (opts && opts.alwaysLast) { 401 | ev = 'afterexit' 402 | } 403 | 404 | var remove = function () { 405 | emitter.removeListener(ev, cb) 406 | if (emitter.listeners('exit').length === 0 && 407 | emitter.listeners('afterexit').length === 0) { 408 | unload() 409 | } 410 | } 411 | emitter.on(ev, cb) 412 | 413 | return remove 414 | } 415 | 416 | var unload = function unload () { 417 | if (!loaded || !processOk(global.process)) { 418 | return 419 | } 420 | loaded = false 421 | 422 | signals.forEach(function (sig) { 423 | try { 424 | process.removeListener(sig, sigListeners[sig]) 425 | } catch (er) {} 426 | }) 427 | process.emit = originalProcessEmit 428 | process.reallyExit = originalProcessReallyExit 429 | emitter.count -= 1 430 | } 431 | module.exports.unload = unload 432 | 433 | var emit = function emit (event, code, signal) { 434 | /* istanbul ignore if */ 435 | if (emitter.emitted[event]) { 436 | return 437 | } 438 | emitter.emitted[event] = true 439 | emitter.emit(event, code, signal) 440 | } 441 | 442 | // { : , ... } 443 | var sigListeners = {} 444 | signals.forEach(function (sig) { 445 | sigListeners[sig] = function listener () { 446 | /* istanbul ignore if */ 447 | if (!processOk(global.process)) { 448 | return 449 | } 450 | // If there are no other listeners, an exit is coming! 451 | // Simplest way: remove us and then re-send the signal. 452 | // We know that this will kill the process, so we can 453 | // safely emit now. 454 | var listeners = process.listeners(sig) 455 | if (listeners.length === emitter.count) { 456 | unload() 457 | emit('exit', null, sig) 458 | /* istanbul ignore next */ 459 | emit('afterexit', null, sig) 460 | /* istanbul ignore next */ 461 | if (isWin && sig === 'SIGHUP') { 462 | // "SIGHUP" throws an `ENOSYS` error on Windows, 463 | // so use a supported signal instead 464 | sig = 'SIGINT' 465 | } 466 | /* istanbul ignore next */ 467 | process.kill(process.pid, sig) 468 | } 469 | } 470 | }) 471 | 472 | module.exports.signals = function () { 473 | return signals 474 | } 475 | 476 | var loaded = false 477 | 478 | var load = function load () { 479 | if (loaded || !processOk(global.process)) { 480 | return 481 | } 482 | loaded = true 483 | 484 | // This is the number of onSignalExit's that are in play. 485 | // It's important so that we can count the correct number of 486 | // listeners on signals, and don't wait for the other one to 487 | // handle it instead of us. 488 | emitter.count += 1 489 | 490 | signals = signals.filter(function (sig) { 491 | try { 492 | process.on(sig, sigListeners[sig]) 493 | return true 494 | } catch (er) { 495 | return false 496 | } 497 | }) 498 | 499 | process.emit = processEmit 500 | process.reallyExit = processReallyExit 501 | } 502 | module.exports.load = load 503 | 504 | var originalProcessReallyExit = process.reallyExit 505 | var processReallyExit = function processReallyExit (code) { 506 | /* istanbul ignore if */ 507 | if (!processOk(global.process)) { 508 | return 509 | } 510 | process.exitCode = code || /* istanbul ignore next */ 0 511 | emit('exit', process.exitCode, null) 512 | /* istanbul ignore next */ 513 | emit('afterexit', process.exitCode, null) 514 | /* istanbul ignore next */ 515 | originalProcessReallyExit.call(process, process.exitCode) 516 | } 517 | 518 | var originalProcessEmit = process.emit 519 | var processEmit = function processEmit (ev, arg) { 520 | if (ev === 'exit' && processOk(global.process)) { 521 | /* istanbul ignore else */ 522 | if (arg !== undefined) { 523 | process.exitCode = arg 524 | } 525 | var ret = originalProcessEmit.apply(this, arguments) 526 | /* istanbul ignore next */ 527 | emit('exit', process.exitCode, null) 528 | /* istanbul ignore next */ 529 | emit('afterexit', process.exitCode, null) 530 | /* istanbul ignore next */ 531 | return ret 532 | } else { 533 | return originalProcessEmit.apply(this, arguments) 534 | } 535 | } 536 | } 537 | 538 | 539 | /***/ }), 540 | 541 | /***/ 41430: 542 | /***/ ((module) => { 543 | 544 | // This is not the set of all possible signals. 545 | // 546 | // It IS, however, the set of all signals that trigger 547 | // an exit on either Linux or BSD systems. Linux is a 548 | // superset of the signal names supported on BSD, and 549 | // the unknown signals just fail to register, so we can 550 | // catch that easily enough. 551 | // 552 | // Don't bother with SIGKILL. It's uncatchable, which 553 | // means that we can't fire any callbacks anyway. 554 | // 555 | // If a user does happen to register a handler on a non- 556 | // fatal signal like SIGWINCH or something, and then 557 | // exit, it'll end up firing `process.emit('exit')`, so 558 | // the handler will be fired anyway. 559 | // 560 | // SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised 561 | // artificially, inherently leave the process in a 562 | // state from which it is not safe to try and enter JS 563 | // listeners. 564 | module.exports = [ 565 | 'SIGABRT', 566 | 'SIGALRM', 567 | 'SIGHUP', 568 | 'SIGINT', 569 | 'SIGTERM' 570 | ] 571 | 572 | if (process.platform !== 'win32') { 573 | module.exports.push( 574 | 'SIGVTALRM', 575 | 'SIGXCPU', 576 | 'SIGXFSZ', 577 | 'SIGUSR2', 578 | 'SIGTRAP', 579 | 'SIGSYS', 580 | 'SIGQUIT', 581 | 'SIGIOT' 582 | // should detect profiler and enable/disable accordingly. 583 | // see #21 584 | // 'SIGPROF' 585 | ) 586 | } 587 | 588 | if (process.platform === 'linux') { 589 | module.exports.push( 590 | 'SIGIO', 591 | 'SIGPOLL', 592 | 'SIGPWR', 593 | 'SIGSTKFLT', 594 | 'SIGUNUSED' 595 | ) 596 | } 597 | 598 | 599 | /***/ }) 600 | 601 | }; 602 | -------------------------------------------------------------------------------- /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/exec 14 | MIT 15 | The MIT License (MIT) 16 | 17 | Copyright 2019 GitHub 18 | 19 | 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: 20 | 21 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 22 | 23 | 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. 24 | 25 | @actions/github 26 | MIT 27 | The MIT License (MIT) 28 | 29 | Copyright 2019 GitHub 30 | 31 | 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: 32 | 33 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 34 | 35 | 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. 36 | 37 | @actions/http-client 38 | MIT 39 | Actions Http Client for Node.js 40 | 41 | Copyright (c) GitHub, Inc. 42 | 43 | All rights reserved. 44 | 45 | MIT License 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 48 | associated documentation files (the "Software"), to deal in the Software without restriction, 49 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 50 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 51 | subject to the following conditions: 52 | 53 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 56 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 57 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 58 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 59 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 60 | 61 | 62 | @actions/io 63 | MIT 64 | The MIT License (MIT) 65 | 66 | Copyright 2019 GitHub 67 | 68 | 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: 69 | 70 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 71 | 72 | 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. 73 | 74 | @fastify/busboy 75 | MIT 76 | Copyright Brian White. All rights reserved. 77 | 78 | Permission is hereby granted, free of charge, to any person obtaining a copy 79 | of this software and associated documentation files (the "Software"), to 80 | deal in the Software without restriction, including without limitation the 81 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 82 | sell copies of the Software, and to permit persons to whom the Software is 83 | furnished to do so, subject to the following conditions: 84 | 85 | The above copyright notice and this permission notice shall be included in 86 | all copies or substantial portions of the Software. 87 | 88 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 89 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 90 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 91 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 92 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 94 | IN THE SOFTWARE. 95 | 96 | @octokit/auth-token 97 | MIT 98 | The MIT License 99 | 100 | Copyright (c) 2019 Octokit contributors 101 | 102 | Permission is hereby granted, free of charge, to any person obtaining a copy 103 | of this software and associated documentation files (the "Software"), to deal 104 | in the Software without restriction, including without limitation the rights 105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 106 | copies of the Software, and to permit persons to whom the Software is 107 | furnished to do so, subject to the following conditions: 108 | 109 | The above copyright notice and this permission notice shall be included in 110 | all copies or substantial portions of the Software. 111 | 112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 118 | THE SOFTWARE. 119 | 120 | 121 | @octokit/core 122 | MIT 123 | The MIT License 124 | 125 | Copyright (c) 2019 Octokit contributors 126 | 127 | Permission is hereby granted, free of charge, to any person obtaining a copy 128 | of this software and associated documentation files (the "Software"), to deal 129 | in the Software without restriction, including without limitation the rights 130 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 131 | copies of the Software, and to permit persons to whom the Software is 132 | furnished to do so, subject to the following conditions: 133 | 134 | The above copyright notice and this permission notice shall be included in 135 | all copies or substantial portions of the Software. 136 | 137 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 138 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 139 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 140 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 141 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 142 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 143 | THE SOFTWARE. 144 | 145 | 146 | @octokit/endpoint 147 | MIT 148 | The MIT License 149 | 150 | Copyright (c) 2018 Octokit contributors 151 | 152 | Permission is hereby granted, free of charge, to any person obtaining a copy 153 | of this software and associated documentation files (the "Software"), to deal 154 | in the Software without restriction, including without limitation the rights 155 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 156 | copies of the Software, and to permit persons to whom the Software is 157 | furnished to do so, subject to the following conditions: 158 | 159 | The above copyright notice and this permission notice shall be included in 160 | all copies or substantial portions of the Software. 161 | 162 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 164 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 165 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 166 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 167 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 168 | THE SOFTWARE. 169 | 170 | 171 | @octokit/graphql 172 | MIT 173 | The MIT License 174 | 175 | Copyright (c) 2018 Octokit contributors 176 | 177 | Permission is hereby granted, free of charge, to any person obtaining a copy 178 | of this software and associated documentation files (the "Software"), to deal 179 | in the Software without restriction, including without limitation the rights 180 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 181 | copies of the Software, and to permit persons to whom the Software is 182 | furnished to do so, subject to the following conditions: 183 | 184 | The above copyright notice and this permission notice shall be included in 185 | all copies or substantial portions of the Software. 186 | 187 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 188 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 189 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 190 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 192 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 193 | THE SOFTWARE. 194 | 195 | 196 | @octokit/plugin-paginate-rest 197 | MIT 198 | MIT License Copyright (c) 2019 Octokit contributors 199 | 200 | 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: 201 | 202 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 203 | 204 | 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. 205 | 206 | 207 | @octokit/plugin-rest-endpoint-methods 208 | MIT 209 | MIT License Copyright (c) 2019 Octokit contributors 210 | 211 | 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: 212 | 213 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 214 | 215 | 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. 216 | 217 | 218 | @octokit/request 219 | MIT 220 | The MIT License 221 | 222 | Copyright (c) 2018 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/request-error 244 | MIT 245 | The MIT License 246 | 247 | Copyright (c) 2019 Octokit contributors 248 | 249 | Permission is hereby granted, free of charge, to any person obtaining a copy 250 | of this software and associated documentation files (the "Software"), to deal 251 | in the Software without restriction, including without limitation the rights 252 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 253 | copies of the Software, and to permit persons to whom the Software is 254 | furnished to do so, subject to the following conditions: 255 | 256 | The above copyright notice and this permission notice shall be included in 257 | all copies or substantial portions of the Software. 258 | 259 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 260 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 261 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 262 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 263 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 264 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 265 | THE SOFTWARE. 266 | 267 | 268 | before-after-hook 269 | Apache-2.0 270 | Apache License 271 | Version 2.0, January 2004 272 | http://www.apache.org/licenses/ 273 | 274 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 275 | 276 | 1. Definitions. 277 | 278 | "License" shall mean the terms and conditions for use, reproduction, 279 | and distribution as defined by Sections 1 through 9 of this document. 280 | 281 | "Licensor" shall mean the copyright owner or entity authorized by 282 | the copyright owner that is granting the License. 283 | 284 | "Legal Entity" shall mean the union of the acting entity and all 285 | other entities that control, are controlled by, or are under common 286 | control with that entity. For the purposes of this definition, 287 | "control" means (i) the power, direct or indirect, to cause the 288 | direction or management of such entity, whether by contract or 289 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 290 | outstanding shares, or (iii) beneficial ownership of such entity. 291 | 292 | "You" (or "Your") shall mean an individual or Legal Entity 293 | exercising permissions granted by this License. 294 | 295 | "Source" form shall mean the preferred form for making modifications, 296 | including but not limited to software source code, documentation 297 | source, and configuration files. 298 | 299 | "Object" form shall mean any form resulting from mechanical 300 | transformation or translation of a Source form, including but 301 | not limited to compiled object code, generated documentation, 302 | and conversions to other media types. 303 | 304 | "Work" shall mean the work of authorship, whether in Source or 305 | Object form, made available under the License, as indicated by a 306 | copyright notice that is included in or attached to the work 307 | (an example is provided in the Appendix below). 308 | 309 | "Derivative Works" shall mean any work, whether in Source or Object 310 | form, that is based on (or derived from) the Work and for which the 311 | editorial revisions, annotations, elaborations, or other modifications 312 | represent, as a whole, an original work of authorship. For the purposes 313 | of this License, Derivative Works shall not include works that remain 314 | separable from, or merely link (or bind by name) to the interfaces of, 315 | the Work and Derivative Works thereof. 316 | 317 | "Contribution" shall mean any work of authorship, including 318 | the original version of the Work and any modifications or additions 319 | to that Work or Derivative Works thereof, that is intentionally 320 | submitted to Licensor for inclusion in the Work by the copyright owner 321 | or by an individual or Legal Entity authorized to submit on behalf of 322 | the copyright owner. For the purposes of this definition, "submitted" 323 | means any form of electronic, verbal, or written communication sent 324 | to the Licensor or its representatives, including but not limited to 325 | communication on electronic mailing lists, source code control systems, 326 | and issue tracking systems that are managed by, or on behalf of, the 327 | Licensor for the purpose of discussing and improving the Work, but 328 | excluding communication that is conspicuously marked or otherwise 329 | designated in writing by the copyright owner as "Not a Contribution." 330 | 331 | "Contributor" shall mean Licensor and any individual or Legal Entity 332 | on behalf of whom a Contribution has been received by Licensor and 333 | subsequently incorporated within the Work. 334 | 335 | 2. Grant of Copyright License. Subject to the terms and conditions of 336 | this License, each Contributor hereby grants to You a perpetual, 337 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 338 | copyright license to reproduce, prepare Derivative Works of, 339 | publicly display, publicly perform, sublicense, and distribute the 340 | Work and such Derivative Works in Source or Object form. 341 | 342 | 3. Grant of Patent License. Subject to the terms and conditions of 343 | this License, each Contributor hereby grants to You a perpetual, 344 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 345 | (except as stated in this section) patent license to make, have made, 346 | use, offer to sell, sell, import, and otherwise transfer the Work, 347 | where such license applies only to those patent claims licensable 348 | by such Contributor that are necessarily infringed by their 349 | Contribution(s) alone or by combination of their Contribution(s) 350 | with the Work to which such Contribution(s) was submitted. If You 351 | institute patent litigation against any entity (including a 352 | cross-claim or counterclaim in a lawsuit) alleging that the Work 353 | or a Contribution incorporated within the Work constitutes direct 354 | or contributory patent infringement, then any patent licenses 355 | granted to You under this License for that Work shall terminate 356 | as of the date such litigation is filed. 357 | 358 | 4. Redistribution. You may reproduce and distribute copies of the 359 | Work or Derivative Works thereof in any medium, with or without 360 | modifications, and in Source or Object form, provided that You 361 | meet the following conditions: 362 | 363 | (a) You must give any other recipients of the Work or 364 | Derivative Works a copy of this License; and 365 | 366 | (b) You must cause any modified files to carry prominent notices 367 | stating that You changed the files; and 368 | 369 | (c) You must retain, in the Source form of any Derivative Works 370 | that You distribute, all copyright, patent, trademark, and 371 | attribution notices from the Source form of the Work, 372 | excluding those notices that do not pertain to any part of 373 | the Derivative Works; and 374 | 375 | (d) If the Work includes a "NOTICE" text file as part of its 376 | distribution, then any Derivative Works that You distribute must 377 | include a readable copy of the attribution notices contained 378 | within such NOTICE file, excluding those notices that do not 379 | pertain to any part of the Derivative Works, in at least one 380 | of the following places: within a NOTICE text file distributed 381 | as part of the Derivative Works; within the Source form or 382 | documentation, if provided along with the Derivative Works; or, 383 | within a display generated by the Derivative Works, if and 384 | wherever such third-party notices normally appear. The contents 385 | of the NOTICE file are for informational purposes only and 386 | do not modify the License. You may add Your own attribution 387 | notices within Derivative Works that You distribute, alongside 388 | or as an addendum to the NOTICE text from the Work, provided 389 | that such additional attribution notices cannot be construed 390 | as modifying the License. 391 | 392 | You may add Your own copyright statement to Your modifications and 393 | may provide additional or different license terms and conditions 394 | for use, reproduction, or distribution of Your modifications, or 395 | for any such Derivative Works as a whole, provided Your use, 396 | reproduction, and distribution of the Work otherwise complies with 397 | the conditions stated in this License. 398 | 399 | 5. Submission of Contributions. Unless You explicitly state otherwise, 400 | any Contribution intentionally submitted for inclusion in the Work 401 | by You to the Licensor shall be under the terms and conditions of 402 | this License, without any additional terms or conditions. 403 | Notwithstanding the above, nothing herein shall supersede or modify 404 | the terms of any separate license agreement you may have executed 405 | with Licensor regarding such Contributions. 406 | 407 | 6. Trademarks. This License does not grant permission to use the trade 408 | names, trademarks, service marks, or product names of the Licensor, 409 | except as required for reasonable and customary use in describing the 410 | origin of the Work and reproducing the content of the NOTICE file. 411 | 412 | 7. Disclaimer of Warranty. Unless required by applicable law or 413 | agreed to in writing, Licensor provides the Work (and each 414 | Contributor provides its Contributions) on an "AS IS" BASIS, 415 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 416 | implied, including, without limitation, any warranties or conditions 417 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 418 | PARTICULAR PURPOSE. You are solely responsible for determining the 419 | appropriateness of using or redistributing the Work and assume any 420 | risks associated with Your exercise of permissions under this License. 421 | 422 | 8. Limitation of Liability. In no event and under no legal theory, 423 | whether in tort (including negligence), contract, or otherwise, 424 | unless required by applicable law (such as deliberate and grossly 425 | negligent acts) or agreed to in writing, shall any Contributor be 426 | liable to You for damages, including any direct, indirect, special, 427 | incidental, or consequential damages of any character arising as a 428 | result of this License or out of the use or inability to use the 429 | Work (including but not limited to damages for loss of goodwill, 430 | work stoppage, computer failure or malfunction, or any and all 431 | other commercial damages or losses), even if such Contributor 432 | has been advised of the possibility of such damages. 433 | 434 | 9. Accepting Warranty or Additional Liability. While redistributing 435 | the Work or Derivative Works thereof, You may choose to offer, 436 | and charge a fee for, acceptance of support, warranty, indemnity, 437 | or other liability obligations and/or rights consistent with this 438 | License. However, in accepting such obligations, You may act only 439 | on Your own behalf and on Your sole responsibility, not on behalf 440 | of any other Contributor, and only if You agree to indemnify, 441 | defend, and hold each Contributor harmless for any liability 442 | incurred by, or claims asserted against, such Contributor by reason 443 | of your accepting any such warranty or additional liability. 444 | 445 | END OF TERMS AND CONDITIONS 446 | 447 | APPENDIX: How to apply the Apache License to your work. 448 | 449 | To apply the Apache License to your work, attach the following 450 | boilerplate notice, with the fields enclosed by brackets "{}" 451 | replaced with your own identifying information. (Don't include 452 | the brackets!) The text should be enclosed in the appropriate 453 | comment syntax for the file format. We also recommend that a 454 | file or class name and description of purpose be included on the 455 | same "printed page" as the copyright notice for easier 456 | identification within third-party archives. 457 | 458 | Copyright 2018 Gregor Martynus and other contributors. 459 | 460 | Licensed under the Apache License, Version 2.0 (the "License"); 461 | you may not use this file except in compliance with the License. 462 | You may obtain a copy of the License at 463 | 464 | http://www.apache.org/licenses/LICENSE-2.0 465 | 466 | Unless required by applicable law or agreed to in writing, software 467 | distributed under the License is distributed on an "AS IS" BASIS, 468 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 469 | See the License for the specific language governing permissions and 470 | limitations under the License. 471 | 472 | 473 | deprecation 474 | ISC 475 | The ISC License 476 | 477 | Copyright (c) Gregor Martynus and contributors 478 | 479 | Permission to use, copy, modify, and/or distribute this software for any 480 | purpose with or without fee is hereby granted, provided that the above 481 | copyright notice and this permission notice appear in all copies. 482 | 483 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 484 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 485 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 486 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 487 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 488 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 489 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 490 | 491 | 492 | lockfile 493 | ISC 494 | The ISC License 495 | 496 | Copyright (c) Isaac Z. Schlueter and Contributors 497 | 498 | Permission to use, copy, modify, and/or distribute this software for any 499 | purpose with or without fee is hereby granted, provided that the above 500 | copyright notice and this permission notice appear in all copies. 501 | 502 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 503 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 504 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 505 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 506 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 507 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 508 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 509 | 510 | 511 | once 512 | ISC 513 | The ISC License 514 | 515 | Copyright (c) Isaac Z. Schlueter and Contributors 516 | 517 | Permission to use, copy, modify, and/or distribute this software for any 518 | purpose with or without fee is hereby granted, provided that the above 519 | copyright notice and this permission notice appear in all copies. 520 | 521 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 522 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 523 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 524 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 525 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 526 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 527 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 528 | 529 | 530 | signal-exit 531 | ISC 532 | The ISC License 533 | 534 | Copyright (c) 2015, Contributors 535 | 536 | Permission to use, copy, modify, and/or distribute this software 537 | for any purpose with or without fee is hereby granted, provided 538 | that the above copyright notice and this permission notice 539 | appear in all copies. 540 | 541 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 542 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 543 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE 544 | LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES 545 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 546 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 547 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 548 | 549 | 550 | tunnel 551 | MIT 552 | The MIT License (MIT) 553 | 554 | Copyright (c) 2012 Koichi Kobayashi 555 | 556 | Permission is hereby granted, free of charge, to any person obtaining a copy 557 | of this software and associated documentation files (the "Software"), to deal 558 | in the Software without restriction, including without limitation the rights 559 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 560 | copies of the Software, and to permit persons to whom the Software is 561 | furnished to do so, subject to the following conditions: 562 | 563 | The above copyright notice and this permission notice shall be included in 564 | all copies or substantial portions of the Software. 565 | 566 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 567 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 568 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 569 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 570 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 571 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 572 | THE SOFTWARE. 573 | 574 | 575 | undici 576 | MIT 577 | MIT License 578 | 579 | Copyright (c) Matteo Collina and Undici contributors 580 | 581 | Permission is hereby granted, free of charge, to any person obtaining a copy 582 | of this software and associated documentation files (the "Software"), to deal 583 | in the Software without restriction, including without limitation the rights 584 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 585 | copies of the Software, and to permit persons to whom the Software is 586 | furnished to do so, subject to the following conditions: 587 | 588 | The above copyright notice and this permission notice shall be included in all 589 | copies or substantial portions of the Software. 590 | 591 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 592 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 593 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 594 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 595 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 596 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 597 | SOFTWARE. 598 | 599 | 600 | universal-user-agent 601 | ISC 602 | # [ISC License](https://spdx.org/licenses/ISC) 603 | 604 | Copyright (c) 2018, Gregor Martynus (https://github.com/gr2m) 605 | 606 | 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. 607 | 608 | 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. 609 | 610 | 611 | wrappy 612 | ISC 613 | The ISC License 614 | 615 | Copyright (c) Isaac Z. Schlueter and Contributors 616 | 617 | Permission to use, copy, modify, and/or distribute this software for any 618 | purpose with or without fee is hereby granted, provided that the above 619 | copyright notice and this permission notice appear in all copies. 620 | 621 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 622 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 623 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 624 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 625 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 626 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 627 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 628 | -------------------------------------------------------------------------------- /dist/build/Release/zlib_sync.node: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjstone/discord-webhook-notify/5f70966d0212ce930c90ec606c6767087559d18e/dist/build/Release/zlib_sync.node -------------------------------------------------------------------------------- /dist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // See: https://eslint.org/docs/latest/use/configure/configuration-files 2 | 3 | import { fixupPluginRules } from '@eslint/compat' 4 | import { FlatCompat } from '@eslint/eslintrc' 5 | import js from '@eslint/js' 6 | import _import from 'eslint-plugin-import' 7 | import jest from 'eslint-plugin-jest' 8 | import globals from 'globals' 9 | import path from 'node:path' 10 | import { fileURLToPath } from 'node:url' 11 | 12 | const __filename = fileURLToPath(import.meta.url) 13 | const __dirname = path.dirname(__filename) 14 | const compat = new FlatCompat({ 15 | baseDirectory: __dirname, 16 | recommendedConfig: js.configs.recommended, 17 | allConfig: js.configs.all 18 | }) 19 | 20 | export default [ 21 | { 22 | ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules'] 23 | }, 24 | ...compat.extends( 25 | 'eslint:recommended', 26 | 'plugin:jest/recommended' 27 | ), 28 | { 29 | plugins: { 30 | import: fixupPluginRules(_import), 31 | jest 32 | }, 33 | 34 | languageOptions: { 35 | globals: { 36 | ...globals.node, 37 | ...globals.jest, 38 | Atomics: 'readonly', 39 | SharedArrayBuffer: 'readonly' 40 | }, 41 | 42 | ecmaVersion: 2023, 43 | sourceType: 'module' 44 | }, 45 | 46 | rules: { 47 | camelcase: 'off', 48 | 'eslint-comments/no-use': 'off', 49 | 'eslint-comments/no-unused-disable': 'off', 50 | 'i18n-text/no-en': 'off', 51 | 'import/no-namespace': 'off', 52 | 'no-console': 'off', 53 | 'no-shadow': 'off', 54 | 'no-unused-vars': 'off' 55 | } 56 | } 57 | ] -------------------------------------------------------------------------------- /img/custom_appearance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjstone/discord-webhook-notify/5f70966d0212ce930c90ec606c6767087559d18e/img/custom_appearance.jpg -------------------------------------------------------------------------------- /img/default_appearance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjstone/discord-webhook-notify/5f70966d0212ce930c90ec606c6767087559d18e/img/default_appearance.jpg -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const core = await import('@actions/core'); 2 | const github = await import('@actions/github'); 3 | 4 | import { EmbedBuilder, WebhookClient } from 'discord.js'; 5 | 6 | const lockFile = await import('lockfile'); 7 | const os = await import('os'); 8 | const path = await import('path'); 9 | 10 | 11 | const default_holddownTime = 2000; // ms 12 | const default_avatarUrl = "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"; 13 | const default_username = "GitHub"; 14 | const default_colors = { 15 | info: '#00ff00', 16 | warn: '#ff9900', 17 | error: '#ff0000' 18 | } 19 | const long_severity = { 20 | info: "Informational", 21 | warn: "Warning", 22 | error: "Error" 23 | } 24 | 25 | async function getDefaultDescription() { 26 | // This default is very minimal and its much better to construct one yourself. 27 | // See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context 28 | const context = github.context; 29 | 30 | // There are now a lot more event types than there were originally. 31 | // See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows 32 | switch(context.eventName) { 33 | case 'push': 34 | return `- **Event:** ${context.eventName}\n` 35 | + `- **Repo:** ${context.repo}\n` 36 | + `- **Ref:** ${context.ref}\n` 37 | + `- **Workflow:** ${context.workflow}\n` 38 | ; 39 | case 'release': 40 | return `- **Event:** ${context.eventName}\n` 41 | + `- **Repo:** ${context.repo}\n` 42 | ; 43 | case 'schedule': 44 | return `- **Event:** ${context.eventName}\n` 45 | + `- **Ref**: ${context.ref}\n` 46 | + `- **Workflow**: ${context.workflow}\n` 47 | + `- **Commit SHA**: ${context.sha}\n` 48 | ; 49 | default: 50 | return `- **Event:** ${context.eventName}\n` 51 | + `- **Repo:** ${context.repo}\n` 52 | ; 53 | } 54 | } 55 | 56 | // For local debugging. Lack of error checking here not such a big deal. 57 | // Normally doesn't get executed so all these imports don't happen. 58 | async function getDebugTestUrl() { 59 | const fs = await import('node:fs'); 60 | return fs.readFileSync(path.join(os.homedir(),'github_webhookUrl.txt'),'utf8'); 61 | } 62 | 63 | export async function run() { 64 | try { 65 | var webhookUrl = core.getInput('webhookUrl').replace("/github", ""); 66 | if (webhookUrl === 'useTestURL') { 67 | webhookUrl = await getDebugTestUrl(); 68 | } else if (!webhookUrl) { 69 | core.warning("The webhookUrl was not provided. For security reasons the secret URL must be provided " 70 | + "in the action yaml using a context expression and can not be read as a default."); 71 | return; 72 | } 73 | 74 | // goes in message 75 | const username = core.getInput('username') || default_username; 76 | const avatarUrl = core.getInput('avatarUrl') || default_avatarUrl; 77 | const text = core.getInput('text') || ''; 78 | 79 | // goes in embed in message 80 | const severity = core.getInput('severity') || 'info'; 81 | const title = core.getInput('title') || ''; 82 | const description = core.getInput('description') || ''; 83 | const details = core.getInput('details') || ''; 84 | const footer = core.getInput('footer') || ''; 85 | const color = core.getInput('color'); 86 | 87 | const context = github.context; 88 | const obstr = JSON.stringify(context, undefined, 2); 89 | core.debug(`The event github.context: ${obstr}`); 90 | 91 | const webhookClient = new WebhookClient({url: webhookUrl}, {rest: {globalRequestsPerSecond: 10}}); 92 | 93 | const embed = new EmbedBuilder() 94 | .setTitle(title || long_severity[severity]) 95 | .setColor(color || default_colors[severity]) 96 | .setDescription((description || await getDefaultDescription()) + "\n" + details) 97 | .setFooter({text: footer || ("Severity: " + long_severity[severity])}) 98 | .setTimestamp(); 99 | 100 | const msg = { 101 | username: username, 102 | avatarURL: avatarUrl, 103 | content: text, 104 | embeds: [ embed ] 105 | }; 106 | 107 | const holddownTime = Number.parseInt(core.getInput('holddownTime'), 10) || default_holddownTime; 108 | const lockfile_name = path.join(os.tmpdir(), 'discord-webhook-notify-rate-limiting.lock'); 109 | 110 | var promise; 111 | lockFile.lock(lockfile_name, { stale: holddownTime, wait: ( holddownTime * 1.5 ) }, function (err) { 112 | if (err) { 113 | throw new Error("Somehow failed to acquire lock file. holddownTime = ${holddownTime}"); 114 | } else { 115 | promise = webhookClient.send(msg); 116 | } 117 | }); 118 | await promise; 119 | // We intentionally don't unlock because we want any new calls to have to wait until stale. 120 | // lockFile.unlock(lockfile_name, function (err) { }) 121 | 122 | } catch (error) { 123 | // core.setFailed(error.message); 124 | core.notice(error.message); 125 | } 126 | } 127 | 128 | run(); -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // See: https://jestjs.io/docs/configuration 2 | 3 | /** @type {import('jest').Config} */ 4 | const jestConfig = { 5 | clearMocks: true, 6 | collectCoverage: true, 7 | collectCoverageFrom: ['./**'], 8 | coverageDirectory: './coverage', 9 | coveragePathIgnorePatterns: ['/node_modules/', '/dist/'], 10 | coverageReporters: ['json-summary', 'text', 'lcov'], 11 | moduleFileExtensions: ['js'], 12 | reporters: ['default'], 13 | testEnvironment: 'node', 14 | testMatch: ['**/*.test.js'], 15 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 16 | verbose: true 17 | } 18 | 19 | export default jestConfig -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-webhook-notify", 3 | "description": "GitHub Action to send notifications to Discord using a webhook.", 4 | "version": "2.1.0", 5 | "author": "rjstone@github", 6 | "type": "module", 7 | "private": false, 8 | "homepage": "https://github.com/rjstone/discord-webhook-notify", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/rjstone/discord-webhook-notify.git" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/rjstone/discord-webhook-notify/issues" 15 | }, 16 | "keywords": [ 17 | "actions", 18 | "discord", 19 | "notification" 20 | ], 21 | "exports": { 22 | ".": "./dist/index.js" 23 | }, 24 | "engines": { 25 | "node": ">=20" 26 | }, 27 | "scripts": { 28 | "ci-test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest", 29 | "test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest", 30 | "coverage": "npx make-coverage-badge --output-path ./badges/coverage.svg", 31 | "lint": "npx eslint .", 32 | "local-action": "npx @github/local-action . index.js .env", 33 | "compile": "ncc build index.js --license LICENSE" 34 | }, 35 | "license": "MIT", 36 | "dependencies": { 37 | "@actions/core": "^1.2.6", 38 | "@actions/github": "^6.0.1", 39 | "discord.js": "^14.19.3", 40 | "bufferutil": "^4.0.9", 41 | "zlib-sync": "^0.1.10", 42 | "lockfile": "^1.0.4" 43 | }, 44 | "devDependencies": { 45 | "@vercel/ncc": "^0.38.3", 46 | "@eslint/compat": "^1.3.0", 47 | "@github/local-action": "^3.2.1", 48 | "@jest/globals": "^30.0.0", 49 | "eslint": "^9.28.0", 50 | "eslint-plugin-jest": "^28.13.3", 51 | "eslint-plugin-import": "^2.31.0", 52 | "jest": "^30.0.0", 53 | "make-coverage-badge": "^1.2.0" 54 | }, 55 | "main": "index.js" 56 | } 57 | -------------------------------------------------------------------------------- /test.env: -------------------------------------------------------------------------------- 1 | ACTIONS_STEP_DEBUG=true 2 | INPUT_WEBHOOKURL="useTestURL" 3 | INPUT_HOLDDOWNTIME="1000" 4 | INPUT_DETAILS="There are many variations of passages of Lorem Ipsum available. Get yours today!" 5 | INPUT_TEXT="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book." 6 | GITHUB_ACTOR="silent_bob" 7 | GITHUB_ACTOR_ID="123456789" 8 | GITHUB_EVENT_NAME="push" 9 | GITHUB_JOB="Local Action Debug Runner" 10 | GITHUB_REF="try/to/realize/there/is/no/ref" 11 | GITHUB_REPOSITORY="someone/testing-this-junk" 12 | GITHUB_TRIGGERING_ACTOR="loud_bob" 13 | GITHUB_WORKFLOW="Offline Test Not A Workflow" 14 | GITHUB_WORKFLOW_REF="WorkflowRef" --------------------------------------------------------------------------------