├── .gitattributes ├── .github └── workflows │ ├── licensed.yml │ ├── versions.yml │ └── workflow.yml ├── .gitignore ├── .licensed.yml ├── .licenses └── npm │ ├── @actions │ ├── core.dep.yml │ ├── exec.dep.yml │ ├── http-client.dep.yml │ ├── io.dep.yml │ └── tool-cache.dep.yml │ ├── semver.dep.yml │ ├── tunnel.dep.yml │ └── uuid.dep.yml ├── .prettierrc.json ├── CONDUCT ├── LICENSE ├── README.md ├── __tests__ └── find-ruby.test.ts ├── action.yml ├── dist └── index.js ├── docs └── contributors.md ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── cache.ts ├── installer.ts ├── main.ts └── setup-ruby.ts └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | .licenses/** -diff linguist-generated=true -------------------------------------------------------------------------------- /.github/workflows/licensed.yml: -------------------------------------------------------------------------------- 1 | name: Licensed 2 | 3 | on: 4 | push: {branches: main} 5 | pull_request: {branches: main} 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | name: Check licenses 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: npm ci 14 | - name: Install licensed 15 | run: | 16 | cd $RUNNER_TEMP 17 | curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz 18 | sudo tar -xzf licensed.tar.gz 19 | sudo mv licensed /usr/local/bin/licensed 20 | - run: licensed status -------------------------------------------------------------------------------- /.github/workflows/versions.yml: -------------------------------------------------------------------------------- 1 | name: ruby-versions 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - '**.md' 8 | pull_request: 9 | paths-ignore: 10 | - '**.md' 11 | jobs: 12 | run: 13 | name: Ruby 14 | runs-on: ${{ matrix.operating-system }} 15 | strategy: 16 | matrix: 17 | operating-system: [ubuntu-latest, windows-latest, macos-latest] 18 | version: [2.5.x, 2.6, 2.7.x] 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | 23 | - name: use-ruby ${{ matrix.version }} 24 | uses: ./ 25 | with: 26 | ruby-version: ${{ matrix.version}} 27 | 28 | - name: ruby version 29 | run: ruby -v 30 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: build-test 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - '**.md' 8 | pull_request: 9 | paths-ignore: 10 | - '**.md' 11 | jobs: 12 | run: 13 | name: Run 14 | runs-on: ${{ matrix.operating-system }} 15 | strategy: 16 | matrix: 17 | operating-system: [ubuntu-latest, windows-latest] 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@master 21 | 22 | - name: Set Node.js 12.x 23 | uses: actions/setup-node@master 24 | with: 25 | node-version: 12.x 26 | 27 | - name: npm install 28 | run: npm install 29 | 30 | - name: Lint 31 | run: npm run format-check 32 | 33 | - name: npm test 34 | run: npm test 35 | 36 | - name: audit packages 37 | run: npm audit --audit-level=moderate 38 | if: matrix.operating-system == 'ubuntu-latest' 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib 3 | 4 | # Rest of the file 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 | -------------------------------------------------------------------------------- /.licensed.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | npm: true 3 | 4 | allowed: 5 | - apache-2.0 6 | - bsd-2-clause 7 | - bsd-3-clause 8 | - isc 9 | - mit 10 | - cc0-1.0 11 | - unlicense 12 | - 0bsd 13 | 14 | reviewed: 15 | npm: 16 | - sax -------------------------------------------------------------------------------- /.licenses/npm/@actions/core.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/core" 3 | version: 1.2.6 4 | type: npm 5 | summary: Actions core lib 6 | homepage: https://github.com/actions/toolkit/tree/main/packages/core 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: |- 11 | The MIT License (MIT) 12 | 13 | Copyright 2019 GitHub 14 | 15 | 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: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 18 | 19 | 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. 20 | notices: [] 21 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/exec.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/exec" 3 | version: 1.0.3 4 | type: npm 5 | summary: Actions exec lib 6 | homepage: https://github.com/actions/toolkit/tree/master/packages/exec 7 | license: mit 8 | licenses: 9 | - sources: Auto-generated MIT license text 10 | text: | 11 | MIT License 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | notices: [] 31 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/http-client.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/http-client" 3 | version: 1.0.3 4 | type: npm 5 | summary: Actions Http Client 6 | homepage: https://github.com/actions/http-client#readme 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | Actions Http Client for Node.js 12 | 13 | Copyright (c) GitHub, Inc. 14 | 15 | All rights reserved. 16 | 17 | MIT License 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 20 | associated documentation files (the "Software"), to deal in the Software without restriction, 21 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 23 | subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 28 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 29 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 30 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 31 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | notices: [] 33 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/io.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/io" 3 | version: 1.0.2 4 | type: npm 5 | summary: Actions io lib 6 | homepage: https://github.com/actions/toolkit/tree/master/packages/io 7 | license: mit 8 | licenses: 9 | - sources: Auto-generated MIT license text 10 | text: | 11 | MIT License 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | notices: [] 31 | -------------------------------------------------------------------------------- /.licenses/npm/@actions/tool-cache.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "@actions/tool-cache" 3 | version: 1.3.1 4 | type: npm 5 | summary: Actions tool-cache lib 6 | homepage: https://github.com/actions/toolkit/tree/master/packages/exec 7 | license: mit 8 | licenses: 9 | - sources: Auto-generated MIT license text 10 | text: | 11 | MIT License 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | notices: [] 31 | -------------------------------------------------------------------------------- /.licenses/npm/semver.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: semver 3 | version: 6.3.0 4 | type: npm 5 | summary: The semantic version parser used by npm. 6 | homepage: https://github.com/npm/node-semver#readme 7 | license: isc 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | The ISC License 12 | 13 | Copyright (c) Isaac Z. Schlueter and Contributors 14 | 15 | Permission to use, copy, modify, and/or distribute this software for any 16 | purpose with or without fee is hereby granted, provided that the above 17 | copyright notice and this permission notice appear in all copies. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 20 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 21 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 22 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 25 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 | notices: [] 27 | -------------------------------------------------------------------------------- /.licenses/npm/tunnel.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: tunnel 3 | version: 0.0.6 4 | type: npm 5 | summary: Node HTTP/HTTPS Agents for tunneling proxies 6 | homepage: https://github.com/koichik/node-tunnel/ 7 | license: mit 8 | licenses: 9 | - sources: LICENSE 10 | text: | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2012 Koichi Kobayashi 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in 23 | all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | THE SOFTWARE. 32 | - sources: README.md 33 | text: Licensed under the [MIT](https://github.com/koichik/node-tunnel/blob/master/LICENSE) 34 | license. 35 | notices: [] 36 | -------------------------------------------------------------------------------- /.licenses/npm/uuid.dep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: uuid 3 | version: 3.3.2 4 | type: npm 5 | summary: RFC4122 (v1, v4, and v5) UUIDs 6 | homepage: https://github.com/kelektiv/node-uuid#readme 7 | license: mit 8 | licenses: 9 | - sources: LICENSE.md 10 | text: | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2010-2016 Robert Kieffer and other contributors 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | notices: 33 | - sources: AUTHORS 34 | text: |- 35 | Robert Kieffer 36 | Christoph Tavan 37 | AJ ONeal 38 | Vincent Voyer 39 | Roman Shtylman 40 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": false, 9 | "arrowParens": "avoid", 10 | "parser": "typescript" 11 | } -------------------------------------------------------------------------------- /CONDUCT: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at opensource@github.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 GitHub, Inc. and contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # setup-ruby 2 | 3 |

4 | test status 5 | 6 | versions status 7 |

8 | 9 | **Please note: This action is deprecated and should no longer be used. The team at GitHub has ceased making and accepting code contributions or maintaining issues tracker. Please, migrate your workflows to the [ruby/setup-ruby](https://github.com/ruby/setup-ruby), which is being actively maintained by the official Ruby organization.** 10 | 11 | 12 | This action sets up a ruby environment for versions which are installed on the [Actions Virtual Environments](https://github.com/actions/virtual-environments). 13 | 14 | Virtual environments contain only one Ruby version within a 'major.minor' release, and are updated with new releases. Hence, a workflow should only be bound to minor versions. 15 | 16 | Note that a `ruby-version:` of `2.6` or `2.6.x` are equivalent. 17 | 18 | > Supports `2.4`, `2.5`, `2.6`, and `2.7`. 19 | 20 | # Usage 21 | 22 | See [action.yml](action.yml) 23 | 24 | Basic: 25 | ```yaml 26 | steps: 27 | - uses: actions/checkout@v2 28 | - uses: actions/setup-ruby@v1 29 | with: 30 | ruby-version: '2.6' # Version range or exact version of a Ruby version to use, using semvers version range syntax. 31 | - run: ruby hello.rb 32 | ``` 33 | 34 | Matrix Testing: 35 | ```yaml 36 | jobs: 37 | build: 38 | runs-on: ubuntu-16.04 39 | strategy: 40 | matrix: 41 | ruby: [ '2.5', '2.6' ] 42 | name: Ruby ${{ matrix.ruby }} sample 43 | steps: 44 | - uses: actions/checkout@v2 45 | - uses: actions/setup-ruby@v1 46 | with: 47 | ruby-version: ${{ matrix.ruby }} 48 | - run: ruby hello.rb 49 | ``` 50 | 51 | Ruby on Rails Testing: 52 | ```yaml 53 | name: Rails Unit Tests 54 | 55 | on: [push, pull_request] 56 | 57 | jobs: 58 | build: 59 | 60 | runs-on: ubuntu-latest 61 | 62 | services: 63 | db: 64 | image: postgres:11 65 | ports: ['5432:5432'] 66 | options: >- 67 | --health-cmd pg_isready 68 | --health-interval 10s 69 | --health-timeout 5s 70 | --health-retries 5 71 | 72 | steps: 73 | - uses: actions/checkout@v2 74 | - name: Set up Ruby 2.6 75 | uses: actions/setup-ruby@v1 76 | with: 77 | ruby-version: 2.6 78 | - name: Build and test with Rake 79 | env: 80 | PGHOST: 127.0.0.1 81 | PGUSER: postgres 82 | RAILS_ENV: test 83 | run: | 84 | sudo apt-get -yqq install libpq-dev 85 | gem install bundler 86 | bundle install --jobs 4 --retry 3 87 | bundle exec rails db:create 88 | bundle exec rails db:migrate 89 | bundle exec rails test 90 | ``` 91 | 92 | # Caching Dependencies 93 | 94 | See [actions/cache](https://github.com/actions/cache) and the [Ruby Gem cache example](https://github.com/actions/cache/blob/master/examples.md#ruby---gem). 95 | 96 | # License 97 | 98 | The scripts and documentation in this project are released under the [MIT License](LICENSE) 99 | 100 | # Contributions 101 | 102 | Contributions are welcome! See [Contributor's Guide](docs/contributors.md) 103 | 104 | ## Code of Conduct 105 | 106 | :wave: Be nice. See [our code of conduct](CONDUCT) 107 | -------------------------------------------------------------------------------- /__tests__/find-ruby.test.ts: -------------------------------------------------------------------------------- 1 | import * as tc from '@actions/tool-cache'; 2 | import * as core from '@actions/core'; 3 | import fs = require('fs'); 4 | import os = require('os'); 5 | import path = require('path'); 6 | import * as cache from '../src/cache'; 7 | import {run} from '../src/main'; 8 | 9 | describe('find-ruby', () => { 10 | let inSpy: jest.SpyInstance; 11 | let tcSpy: jest.SpyInstance; 12 | let cnSpy: jest.SpyInstance; 13 | 14 | beforeAll(async () => { 15 | process.env['GITHUB_PATH'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out 16 | console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions 17 | }); 18 | 19 | beforeEach(() => { 20 | tcSpy = jest.spyOn(tc, 'find'); 21 | inSpy = jest.spyOn(core, 'getInput'); 22 | cnSpy = jest.spyOn(process.stdout, 'write'); 23 | cnSpy.mockImplementation(line => { 24 | // uncomment to debug 25 | // process.stderr.write('write2:' + line + '\n'); 26 | }); 27 | }); 28 | 29 | afterEach(() => { 30 | tcSpy.mockClear(); 31 | cnSpy.mockClear(); 32 | jest.clearAllMocks(); 33 | }); 34 | 35 | afterAll(async () => { 36 | console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions 37 | }, 100000); 38 | 39 | it('finds a version of ruby already in the cache', async () => { 40 | let toolPath = path.normalize('/cache/ruby/2.7.0/x64'); 41 | tcSpy.mockImplementation(() => toolPath); 42 | 43 | let cacheDir: string = await cache.find('2.7.0'); 44 | let expPath = path.join(toolPath, 'bin'); 45 | expect(cacheDir).toBe(expPath); 46 | }); 47 | 48 | it('does not find a version of ruby not in the cache', async () => { 49 | tcSpy.mockImplementation(() => ''); 50 | 51 | let cacheDir: string = await cache.find('2.9.9'); 52 | expect(cacheDir).toBeFalsy(); 53 | }); 54 | 55 | it('finds a version in the cache and adds it to the path', async () => { 56 | let toolPath = path.normalize('/cache/ruby/2.7.0/x64'); 57 | inSpy.mockImplementation(() => '2.7.0'); 58 | tcSpy.mockImplementation(() => toolPath); 59 | await run(); 60 | 61 | let expPath = path.join(toolPath, 'bin'); 62 | expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${os.EOL}`); 63 | }); 64 | 65 | it('handles unhandled error and reports error', async () => { 66 | let errMsg = 'unhandled error message'; 67 | inSpy.mockImplementation(() => '2.7.0'); 68 | tcSpy.mockImplementation(() => { 69 | throw new Error(errMsg); 70 | }); 71 | await run(); 72 | expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + os.EOL); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup Ruby' 2 | description: 'Set up a specific version of Ruby and add the command-line tools to the PATH' 3 | author: 'GitHub' 4 | inputs: 5 | ruby-version: 6 | description: 'Version range or exact version of a Ruby version to use.' 7 | default: '>= 2.4' 8 | # Deprecated option, do not use. Will not be supported after October 1, 2019 9 | version: 10 | description: 'Deprecated. Use ruby-version instead. Will not be supported after October 1, 2019' 11 | deprecationMessage: 'The version property will not be supported after October 1, 2019. Use ruby-version instead' 12 | runs: 13 | using: 'node12' 14 | main: 'dist/index.js' 15 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | /******/ (function(modules, runtime) { // webpackBootstrap 3 | /******/ "use strict"; 4 | /******/ // The module cache 5 | /******/ var installedModules = {}; 6 | /******/ 7 | /******/ // The require function 8 | /******/ function __webpack_require__(moduleId) { 9 | /******/ 10 | /******/ // Check if module is in cache 11 | /******/ if(installedModules[moduleId]) { 12 | /******/ return installedModules[moduleId].exports; 13 | /******/ } 14 | /******/ // Create a new module (and put it into the cache) 15 | /******/ var module = installedModules[moduleId] = { 16 | /******/ i: moduleId, 17 | /******/ l: false, 18 | /******/ exports: {} 19 | /******/ }; 20 | /******/ 21 | /******/ // Execute the module function 22 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 23 | /******/ 24 | /******/ // Flag the module as loaded 25 | /******/ module.l = true; 26 | /******/ 27 | /******/ // Return the exports of the module 28 | /******/ return module.exports; 29 | /******/ } 30 | /******/ 31 | /******/ 32 | /******/ __webpack_require__.ab = __dirname + "/"; 33 | /******/ 34 | /******/ // the startup function 35 | /******/ function startup() { 36 | /******/ // Load entry module and return exports 37 | /******/ return __webpack_require__(367); 38 | /******/ }; 39 | /******/ 40 | /******/ // run startup 41 | /******/ return startup(); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ({ 45 | 46 | /***/ 1: 47 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 48 | 49 | "use strict"; 50 | 51 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 52 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 53 | return new (P || (P = Promise))(function (resolve, reject) { 54 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 55 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 56 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 57 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 58 | }); 59 | }; 60 | Object.defineProperty(exports, "__esModule", { value: true }); 61 | const childProcess = __webpack_require__(129); 62 | const path = __webpack_require__(622); 63 | const util_1 = __webpack_require__(669); 64 | const ioUtil = __webpack_require__(672); 65 | const exec = util_1.promisify(childProcess.exec); 66 | /** 67 | * Copies a file or folder. 68 | * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js 69 | * 70 | * @param source source path 71 | * @param dest destination path 72 | * @param options optional. See CopyOptions. 73 | */ 74 | function cp(source, dest, options = {}) { 75 | return __awaiter(this, void 0, void 0, function* () { 76 | const { force, recursive } = readCopyOptions(options); 77 | const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; 78 | // Dest is an existing file, but not forcing 79 | if (destStat && destStat.isFile() && !force) { 80 | return; 81 | } 82 | // If dest is an existing directory, should copy inside. 83 | const newDest = destStat && destStat.isDirectory() 84 | ? path.join(dest, path.basename(source)) 85 | : dest; 86 | if (!(yield ioUtil.exists(source))) { 87 | throw new Error(`no such file or directory: ${source}`); 88 | } 89 | const sourceStat = yield ioUtil.stat(source); 90 | if (sourceStat.isDirectory()) { 91 | if (!recursive) { 92 | throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); 93 | } 94 | else { 95 | yield cpDirRecursive(source, newDest, 0, force); 96 | } 97 | } 98 | else { 99 | if (path.relative(source, newDest) === '') { 100 | // a file cannot be copied to itself 101 | throw new Error(`'${newDest}' and '${source}' are the same file`); 102 | } 103 | yield copyFile(source, newDest, force); 104 | } 105 | }); 106 | } 107 | exports.cp = cp; 108 | /** 109 | * Moves a path. 110 | * 111 | * @param source source path 112 | * @param dest destination path 113 | * @param options optional. See MoveOptions. 114 | */ 115 | function mv(source, dest, options = {}) { 116 | return __awaiter(this, void 0, void 0, function* () { 117 | if (yield ioUtil.exists(dest)) { 118 | let destExists = true; 119 | if (yield ioUtil.isDirectory(dest)) { 120 | // If dest is directory copy src into dest 121 | dest = path.join(dest, path.basename(source)); 122 | destExists = yield ioUtil.exists(dest); 123 | } 124 | if (destExists) { 125 | if (options.force == null || options.force) { 126 | yield rmRF(dest); 127 | } 128 | else { 129 | throw new Error('Destination already exists'); 130 | } 131 | } 132 | } 133 | yield mkdirP(path.dirname(dest)); 134 | yield ioUtil.rename(source, dest); 135 | }); 136 | } 137 | exports.mv = mv; 138 | /** 139 | * Remove a path recursively with force 140 | * 141 | * @param inputPath path to remove 142 | */ 143 | function rmRF(inputPath) { 144 | return __awaiter(this, void 0, void 0, function* () { 145 | if (ioUtil.IS_WINDOWS) { 146 | // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another 147 | // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. 148 | try { 149 | if (yield ioUtil.isDirectory(inputPath, true)) { 150 | yield exec(`rd /s /q "${inputPath}"`); 151 | } 152 | else { 153 | yield exec(`del /f /a "${inputPath}"`); 154 | } 155 | } 156 | catch (err) { 157 | // if you try to delete a file that doesn't exist, desired result is achieved 158 | // other errors are valid 159 | if (err.code !== 'ENOENT') 160 | throw err; 161 | } 162 | // Shelling out fails to remove a symlink folder with missing source, this unlink catches that 163 | try { 164 | yield ioUtil.unlink(inputPath); 165 | } 166 | catch (err) { 167 | // if you try to delete a file that doesn't exist, desired result is achieved 168 | // other errors are valid 169 | if (err.code !== 'ENOENT') 170 | throw err; 171 | } 172 | } 173 | else { 174 | let isDir = false; 175 | try { 176 | isDir = yield ioUtil.isDirectory(inputPath); 177 | } 178 | catch (err) { 179 | // if you try to delete a file that doesn't exist, desired result is achieved 180 | // other errors are valid 181 | if (err.code !== 'ENOENT') 182 | throw err; 183 | return; 184 | } 185 | if (isDir) { 186 | yield exec(`rm -rf "${inputPath}"`); 187 | } 188 | else { 189 | yield ioUtil.unlink(inputPath); 190 | } 191 | } 192 | }); 193 | } 194 | exports.rmRF = rmRF; 195 | /** 196 | * Make a directory. Creates the full path with folders in between 197 | * Will throw if it fails 198 | * 199 | * @param fsPath path to create 200 | * @returns Promise 201 | */ 202 | function mkdirP(fsPath) { 203 | return __awaiter(this, void 0, void 0, function* () { 204 | yield ioUtil.mkdirP(fsPath); 205 | }); 206 | } 207 | exports.mkdirP = mkdirP; 208 | /** 209 | * Returns path of a tool had the tool actually been invoked. Resolves via paths. 210 | * If you check and the tool does not exist, it will throw. 211 | * 212 | * @param tool name of the tool 213 | * @param check whether to check if tool exists 214 | * @returns Promise path to tool 215 | */ 216 | function which(tool, check) { 217 | return __awaiter(this, void 0, void 0, function* () { 218 | if (!tool) { 219 | throw new Error("parameter 'tool' is required"); 220 | } 221 | // recursive when check=true 222 | if (check) { 223 | const result = yield which(tool, false); 224 | if (!result) { 225 | if (ioUtil.IS_WINDOWS) { 226 | 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.`); 227 | } 228 | else { 229 | 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.`); 230 | } 231 | } 232 | } 233 | try { 234 | // build the list of extensions to try 235 | const extensions = []; 236 | if (ioUtil.IS_WINDOWS && process.env.PATHEXT) { 237 | for (const extension of process.env.PATHEXT.split(path.delimiter)) { 238 | if (extension) { 239 | extensions.push(extension); 240 | } 241 | } 242 | } 243 | // if it's rooted, return it if exists. otherwise return empty. 244 | if (ioUtil.isRooted(tool)) { 245 | const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); 246 | if (filePath) { 247 | return filePath; 248 | } 249 | return ''; 250 | } 251 | // if any path separators, return empty 252 | if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) { 253 | return ''; 254 | } 255 | // build the list of directories 256 | // 257 | // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, 258 | // it feels like we should not do this. Checking the current directory seems like more of a use 259 | // case of a shell, and the which() function exposed by the toolkit should strive for consistency 260 | // across platforms. 261 | const directories = []; 262 | if (process.env.PATH) { 263 | for (const p of process.env.PATH.split(path.delimiter)) { 264 | if (p) { 265 | directories.push(p); 266 | } 267 | } 268 | } 269 | // return the first match 270 | for (const directory of directories) { 271 | const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions); 272 | if (filePath) { 273 | return filePath; 274 | } 275 | } 276 | return ''; 277 | } 278 | catch (err) { 279 | throw new Error(`which failed with message ${err.message}`); 280 | } 281 | }); 282 | } 283 | exports.which = which; 284 | function readCopyOptions(options) { 285 | const force = options.force == null ? true : options.force; 286 | const recursive = Boolean(options.recursive); 287 | return { force, recursive }; 288 | } 289 | function cpDirRecursive(sourceDir, destDir, currentDepth, force) { 290 | return __awaiter(this, void 0, void 0, function* () { 291 | // Ensure there is not a run away recursive copy 292 | if (currentDepth >= 255) 293 | return; 294 | currentDepth++; 295 | yield mkdirP(destDir); 296 | const files = yield ioUtil.readdir(sourceDir); 297 | for (const fileName of files) { 298 | const srcFile = `${sourceDir}/${fileName}`; 299 | const destFile = `${destDir}/${fileName}`; 300 | const srcFileStat = yield ioUtil.lstat(srcFile); 301 | if (srcFileStat.isDirectory()) { 302 | // Recurse 303 | yield cpDirRecursive(srcFile, destFile, currentDepth, force); 304 | } 305 | else { 306 | yield copyFile(srcFile, destFile, force); 307 | } 308 | } 309 | // Change the mode for the newly created directory 310 | yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); 311 | }); 312 | } 313 | // Buffered file copy 314 | function copyFile(srcFile, destFile, force) { 315 | return __awaiter(this, void 0, void 0, function* () { 316 | if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { 317 | // unlink/re-link it 318 | try { 319 | yield ioUtil.lstat(destFile); 320 | yield ioUtil.unlink(destFile); 321 | } 322 | catch (e) { 323 | // Try to override file permission 324 | if (e.code === 'EPERM') { 325 | yield ioUtil.chmod(destFile, '0666'); 326 | yield ioUtil.unlink(destFile); 327 | } 328 | // other errors = it doesn't exist, no work to do 329 | } 330 | // Copy over symlink 331 | const symlinkFull = yield ioUtil.readlink(srcFile); 332 | yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); 333 | } 334 | else if (!(yield ioUtil.exists(destFile)) || force) { 335 | yield ioUtil.copyFile(srcFile, destFile); 336 | } 337 | }); 338 | } 339 | //# sourceMappingURL=io.js.map 340 | 341 | /***/ }), 342 | 343 | /***/ 9: 344 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 345 | 346 | "use strict"; 347 | 348 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 349 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 350 | return new (P || (P = Promise))(function (resolve, reject) { 351 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 352 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 353 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 354 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 355 | }); 356 | }; 357 | Object.defineProperty(exports, "__esModule", { value: true }); 358 | const os = __webpack_require__(87); 359 | const events = __webpack_require__(614); 360 | const child = __webpack_require__(129); 361 | const path = __webpack_require__(622); 362 | const io = __webpack_require__(1); 363 | const ioUtil = __webpack_require__(672); 364 | /* eslint-disable @typescript-eslint/unbound-method */ 365 | const IS_WINDOWS = process.platform === 'win32'; 366 | /* 367 | * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. 368 | */ 369 | class ToolRunner extends events.EventEmitter { 370 | constructor(toolPath, args, options) { 371 | super(); 372 | if (!toolPath) { 373 | throw new Error("Parameter 'toolPath' cannot be null or empty."); 374 | } 375 | this.toolPath = toolPath; 376 | this.args = args || []; 377 | this.options = options || {}; 378 | } 379 | _debug(message) { 380 | if (this.options.listeners && this.options.listeners.debug) { 381 | this.options.listeners.debug(message); 382 | } 383 | } 384 | _getCommandString(options, noPrefix) { 385 | const toolPath = this._getSpawnFileName(); 386 | const args = this._getSpawnArgs(options); 387 | let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool 388 | if (IS_WINDOWS) { 389 | // Windows + cmd file 390 | if (this._isCmdFile()) { 391 | cmd += toolPath; 392 | for (const a of args) { 393 | cmd += ` ${a}`; 394 | } 395 | } 396 | // Windows + verbatim 397 | else if (options.windowsVerbatimArguments) { 398 | cmd += `"${toolPath}"`; 399 | for (const a of args) { 400 | cmd += ` ${a}`; 401 | } 402 | } 403 | // Windows (regular) 404 | else { 405 | cmd += this._windowsQuoteCmdArg(toolPath); 406 | for (const a of args) { 407 | cmd += ` ${this._windowsQuoteCmdArg(a)}`; 408 | } 409 | } 410 | } 411 | else { 412 | // OSX/Linux - this can likely be improved with some form of quoting. 413 | // creating processes on Unix is fundamentally different than Windows. 414 | // on Unix, execvp() takes an arg array. 415 | cmd += toolPath; 416 | for (const a of args) { 417 | cmd += ` ${a}`; 418 | } 419 | } 420 | return cmd; 421 | } 422 | _processLineBuffer(data, strBuffer, onLine) { 423 | try { 424 | let s = strBuffer + data.toString(); 425 | let n = s.indexOf(os.EOL); 426 | while (n > -1) { 427 | const line = s.substring(0, n); 428 | onLine(line); 429 | // the rest of the string ... 430 | s = s.substring(n + os.EOL.length); 431 | n = s.indexOf(os.EOL); 432 | } 433 | strBuffer = s; 434 | } 435 | catch (err) { 436 | // streaming lines to console is best effort. Don't fail a build. 437 | this._debug(`error processing line. Failed with error ${err}`); 438 | } 439 | } 440 | _getSpawnFileName() { 441 | if (IS_WINDOWS) { 442 | if (this._isCmdFile()) { 443 | return process.env['COMSPEC'] || 'cmd.exe'; 444 | } 445 | } 446 | return this.toolPath; 447 | } 448 | _getSpawnArgs(options) { 449 | if (IS_WINDOWS) { 450 | if (this._isCmdFile()) { 451 | let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; 452 | for (const a of this.args) { 453 | argline += ' '; 454 | argline += options.windowsVerbatimArguments 455 | ? a 456 | : this._windowsQuoteCmdArg(a); 457 | } 458 | argline += '"'; 459 | return [argline]; 460 | } 461 | } 462 | return this.args; 463 | } 464 | _endsWith(str, end) { 465 | return str.endsWith(end); 466 | } 467 | _isCmdFile() { 468 | const upperToolPath = this.toolPath.toUpperCase(); 469 | return (this._endsWith(upperToolPath, '.CMD') || 470 | this._endsWith(upperToolPath, '.BAT')); 471 | } 472 | _windowsQuoteCmdArg(arg) { 473 | // for .exe, apply the normal quoting rules that libuv applies 474 | if (!this._isCmdFile()) { 475 | return this._uvQuoteCmdArg(arg); 476 | } 477 | // otherwise apply quoting rules specific to the cmd.exe command line parser. 478 | // the libuv rules are generic and are not designed specifically for cmd.exe 479 | // command line parser. 480 | // 481 | // for a detailed description of the cmd.exe command line parser, refer to 482 | // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 483 | // need quotes for empty arg 484 | if (!arg) { 485 | return '""'; 486 | } 487 | // determine whether the arg needs to be quoted 488 | const cmdSpecialChars = [ 489 | ' ', 490 | '\t', 491 | '&', 492 | '(', 493 | ')', 494 | '[', 495 | ']', 496 | '{', 497 | '}', 498 | '^', 499 | '=', 500 | ';', 501 | '!', 502 | "'", 503 | '+', 504 | ',', 505 | '`', 506 | '~', 507 | '|', 508 | '<', 509 | '>', 510 | '"' 511 | ]; 512 | let needsQuotes = false; 513 | for (const char of arg) { 514 | if (cmdSpecialChars.some(x => x === char)) { 515 | needsQuotes = true; 516 | break; 517 | } 518 | } 519 | // short-circuit if quotes not needed 520 | if (!needsQuotes) { 521 | return arg; 522 | } 523 | // the following quoting rules are very similar to the rules that by libuv applies. 524 | // 525 | // 1) wrap the string in quotes 526 | // 527 | // 2) double-up quotes - i.e. " => "" 528 | // 529 | // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately 530 | // doesn't work well with a cmd.exe command line. 531 | // 532 | // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. 533 | // for example, the command line: 534 | // foo.exe "myarg:""my val""" 535 | // is parsed by a .NET console app into an arg array: 536 | // [ "myarg:\"my val\"" ] 537 | // which is the same end result when applying libuv quoting rules. although the actual 538 | // command line from libuv quoting rules would look like: 539 | // foo.exe "myarg:\"my val\"" 540 | // 541 | // 3) double-up slashes that precede a quote, 542 | // e.g. hello \world => "hello \world" 543 | // hello\"world => "hello\\""world" 544 | // hello\\"world => "hello\\\\""world" 545 | // hello world\ => "hello world\\" 546 | // 547 | // technically this is not required for a cmd.exe command line, or the batch argument parser. 548 | // the reasons for including this as a .cmd quoting rule are: 549 | // 550 | // a) this is optimized for the scenario where the argument is passed from the .cmd file to an 551 | // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. 552 | // 553 | // b) it's what we've been doing previously (by deferring to node default behavior) and we 554 | // haven't heard any complaints about that aspect. 555 | // 556 | // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be 557 | // escaped when used on the command line directly - even though within a .cmd file % can be escaped 558 | // by using %%. 559 | // 560 | // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts 561 | // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. 562 | // 563 | // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would 564 | // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the 565 | // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args 566 | // to an external program. 567 | // 568 | // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. 569 | // % can be escaped within a .cmd file. 570 | let reverse = '"'; 571 | let quoteHit = true; 572 | for (let i = arg.length; i > 0; i--) { 573 | // walk the string in reverse 574 | reverse += arg[i - 1]; 575 | if (quoteHit && arg[i - 1] === '\\') { 576 | reverse += '\\'; // double the slash 577 | } 578 | else if (arg[i - 1] === '"') { 579 | quoteHit = true; 580 | reverse += '"'; // double the quote 581 | } 582 | else { 583 | quoteHit = false; 584 | } 585 | } 586 | reverse += '"'; 587 | return reverse 588 | .split('') 589 | .reverse() 590 | .join(''); 591 | } 592 | _uvQuoteCmdArg(arg) { 593 | // Tool runner wraps child_process.spawn() and needs to apply the same quoting as 594 | // Node in certain cases where the undocumented spawn option windowsVerbatimArguments 595 | // is used. 596 | // 597 | // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, 598 | // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), 599 | // pasting copyright notice from Node within this function: 600 | // 601 | // Copyright Joyent, Inc. and other Node contributors. All rights reserved. 602 | // 603 | // Permission is hereby granted, free of charge, to any person obtaining a copy 604 | // of this software and associated documentation files (the "Software"), to 605 | // deal in the Software without restriction, including without limitation the 606 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 607 | // sell copies of the Software, and to permit persons to whom the Software is 608 | // furnished to do so, subject to the following conditions: 609 | // 610 | // The above copyright notice and this permission notice shall be included in 611 | // all copies or substantial portions of the Software. 612 | // 613 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 614 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 615 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 616 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 617 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 618 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 619 | // IN THE SOFTWARE. 620 | if (!arg) { 621 | // Need double quotation for empty argument 622 | return '""'; 623 | } 624 | if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { 625 | // No quotation needed 626 | return arg; 627 | } 628 | if (!arg.includes('"') && !arg.includes('\\')) { 629 | // No embedded double quotes or backslashes, so I can just wrap 630 | // quote marks around the whole thing. 631 | return `"${arg}"`; 632 | } 633 | // Expected input/output: 634 | // input : hello"world 635 | // output: "hello\"world" 636 | // input : hello""world 637 | // output: "hello\"\"world" 638 | // input : hello\world 639 | // output: hello\world 640 | // input : hello\\world 641 | // output: hello\\world 642 | // input : hello\"world 643 | // output: "hello\\\"world" 644 | // input : hello\\"world 645 | // output: "hello\\\\\"world" 646 | // input : hello world\ 647 | // output: "hello world\\" - note the comment in libuv actually reads "hello world\" 648 | // but it appears the comment is wrong, it should be "hello world\\" 649 | let reverse = '"'; 650 | let quoteHit = true; 651 | for (let i = arg.length; i > 0; i--) { 652 | // walk the string in reverse 653 | reverse += arg[i - 1]; 654 | if (quoteHit && arg[i - 1] === '\\') { 655 | reverse += '\\'; 656 | } 657 | else if (arg[i - 1] === '"') { 658 | quoteHit = true; 659 | reverse += '\\'; 660 | } 661 | else { 662 | quoteHit = false; 663 | } 664 | } 665 | reverse += '"'; 666 | return reverse 667 | .split('') 668 | .reverse() 669 | .join(''); 670 | } 671 | _cloneExecOptions(options) { 672 | options = options || {}; 673 | const result = { 674 | cwd: options.cwd || process.cwd(), 675 | env: options.env || process.env, 676 | silent: options.silent || false, 677 | windowsVerbatimArguments: options.windowsVerbatimArguments || false, 678 | failOnStdErr: options.failOnStdErr || false, 679 | ignoreReturnCode: options.ignoreReturnCode || false, 680 | delay: options.delay || 10000 681 | }; 682 | result.outStream = options.outStream || process.stdout; 683 | result.errStream = options.errStream || process.stderr; 684 | return result; 685 | } 686 | _getSpawnOptions(options, toolPath) { 687 | options = options || {}; 688 | const result = {}; 689 | result.cwd = options.cwd; 690 | result.env = options.env; 691 | result['windowsVerbatimArguments'] = 692 | options.windowsVerbatimArguments || this._isCmdFile(); 693 | if (options.windowsVerbatimArguments) { 694 | result.argv0 = `"${toolPath}"`; 695 | } 696 | return result; 697 | } 698 | /** 699 | * Exec a tool. 700 | * Output will be streamed to the live console. 701 | * Returns promise with return code 702 | * 703 | * @param tool path to tool to exec 704 | * @param options optional exec options. See ExecOptions 705 | * @returns number 706 | */ 707 | exec() { 708 | return __awaiter(this, void 0, void 0, function* () { 709 | // root the tool path if it is unrooted and contains relative pathing 710 | if (!ioUtil.isRooted(this.toolPath) && 711 | (this.toolPath.includes('/') || 712 | (IS_WINDOWS && this.toolPath.includes('\\')))) { 713 | // prefer options.cwd if it is specified, however options.cwd may also need to be rooted 714 | this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); 715 | } 716 | // if the tool is only a file name, then resolve it from the PATH 717 | // otherwise verify it exists (add extension on Windows if necessary) 718 | this.toolPath = yield io.which(this.toolPath, true); 719 | return new Promise((resolve, reject) => { 720 | this._debug(`exec tool: ${this.toolPath}`); 721 | this._debug('arguments:'); 722 | for (const arg of this.args) { 723 | this._debug(` ${arg}`); 724 | } 725 | const optionsNonNull = this._cloneExecOptions(this.options); 726 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 727 | optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); 728 | } 729 | const state = new ExecState(optionsNonNull, this.toolPath); 730 | state.on('debug', (message) => { 731 | this._debug(message); 732 | }); 733 | const fileName = this._getSpawnFileName(); 734 | const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); 735 | const stdbuffer = ''; 736 | if (cp.stdout) { 737 | cp.stdout.on('data', (data) => { 738 | if (this.options.listeners && this.options.listeners.stdout) { 739 | this.options.listeners.stdout(data); 740 | } 741 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 742 | optionsNonNull.outStream.write(data); 743 | } 744 | this._processLineBuffer(data, stdbuffer, (line) => { 745 | if (this.options.listeners && this.options.listeners.stdline) { 746 | this.options.listeners.stdline(line); 747 | } 748 | }); 749 | }); 750 | } 751 | const errbuffer = ''; 752 | if (cp.stderr) { 753 | cp.stderr.on('data', (data) => { 754 | state.processStderr = true; 755 | if (this.options.listeners && this.options.listeners.stderr) { 756 | this.options.listeners.stderr(data); 757 | } 758 | if (!optionsNonNull.silent && 759 | optionsNonNull.errStream && 760 | optionsNonNull.outStream) { 761 | const s = optionsNonNull.failOnStdErr 762 | ? optionsNonNull.errStream 763 | : optionsNonNull.outStream; 764 | s.write(data); 765 | } 766 | this._processLineBuffer(data, errbuffer, (line) => { 767 | if (this.options.listeners && this.options.listeners.errline) { 768 | this.options.listeners.errline(line); 769 | } 770 | }); 771 | }); 772 | } 773 | cp.on('error', (err) => { 774 | state.processError = err.message; 775 | state.processExited = true; 776 | state.processClosed = true; 777 | state.CheckComplete(); 778 | }); 779 | cp.on('exit', (code) => { 780 | state.processExitCode = code; 781 | state.processExited = true; 782 | this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); 783 | state.CheckComplete(); 784 | }); 785 | cp.on('close', (code) => { 786 | state.processExitCode = code; 787 | state.processExited = true; 788 | state.processClosed = true; 789 | this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); 790 | state.CheckComplete(); 791 | }); 792 | state.on('done', (error, exitCode) => { 793 | if (stdbuffer.length > 0) { 794 | this.emit('stdline', stdbuffer); 795 | } 796 | if (errbuffer.length > 0) { 797 | this.emit('errline', errbuffer); 798 | } 799 | cp.removeAllListeners(); 800 | if (error) { 801 | reject(error); 802 | } 803 | else { 804 | resolve(exitCode); 805 | } 806 | }); 807 | }); 808 | }); 809 | } 810 | } 811 | exports.ToolRunner = ToolRunner; 812 | /** 813 | * Convert an arg string to an array of args. Handles escaping 814 | * 815 | * @param argString string of arguments 816 | * @returns string[] array of arguments 817 | */ 818 | function argStringToArray(argString) { 819 | const args = []; 820 | let inQuotes = false; 821 | let escaped = false; 822 | let arg = ''; 823 | function append(c) { 824 | // we only escape double quotes. 825 | if (escaped && c !== '"') { 826 | arg += '\\'; 827 | } 828 | arg += c; 829 | escaped = false; 830 | } 831 | for (let i = 0; i < argString.length; i++) { 832 | const c = argString.charAt(i); 833 | if (c === '"') { 834 | if (!escaped) { 835 | inQuotes = !inQuotes; 836 | } 837 | else { 838 | append(c); 839 | } 840 | continue; 841 | } 842 | if (c === '\\' && escaped) { 843 | append(c); 844 | continue; 845 | } 846 | if (c === '\\' && inQuotes) { 847 | escaped = true; 848 | continue; 849 | } 850 | if (c === ' ' && !inQuotes) { 851 | if (arg.length > 0) { 852 | args.push(arg); 853 | arg = ''; 854 | } 855 | continue; 856 | } 857 | append(c); 858 | } 859 | if (arg.length > 0) { 860 | args.push(arg.trim()); 861 | } 862 | return args; 863 | } 864 | exports.argStringToArray = argStringToArray; 865 | class ExecState extends events.EventEmitter { 866 | constructor(options, toolPath) { 867 | super(); 868 | this.processClosed = false; // tracks whether the process has exited and stdio is closed 869 | this.processError = ''; 870 | this.processExitCode = 0; 871 | this.processExited = false; // tracks whether the process has exited 872 | this.processStderr = false; // tracks whether stderr was written to 873 | this.delay = 10000; // 10 seconds 874 | this.done = false; 875 | this.timeout = null; 876 | if (!toolPath) { 877 | throw new Error('toolPath must not be empty'); 878 | } 879 | this.options = options; 880 | this.toolPath = toolPath; 881 | if (options.delay) { 882 | this.delay = options.delay; 883 | } 884 | } 885 | CheckComplete() { 886 | if (this.done) { 887 | return; 888 | } 889 | if (this.processClosed) { 890 | this._setResult(); 891 | } 892 | else if (this.processExited) { 893 | this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this); 894 | } 895 | } 896 | _debug(message) { 897 | this.emit('debug', message); 898 | } 899 | _setResult() { 900 | // determine whether there is an error 901 | let error; 902 | if (this.processExited) { 903 | if (this.processError) { 904 | 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}`); 905 | } 906 | else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { 907 | error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); 908 | } 909 | else if (this.processStderr && this.options.failOnStdErr) { 910 | error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); 911 | } 912 | } 913 | // clear the timeout 914 | if (this.timeout) { 915 | clearTimeout(this.timeout); 916 | this.timeout = null; 917 | } 918 | this.done = true; 919 | this.emit('done', error, this.processExitCode); 920 | } 921 | static HandleTimeout(state) { 922 | if (state.done) { 923 | return; 924 | } 925 | if (!state.processClosed && state.processExited) { 926 | const message = `The STDIO streams did not close within ${state.delay / 927 | 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.`; 928 | state._debug(message); 929 | } 930 | state._setResult(); 931 | } 932 | } 933 | //# sourceMappingURL=toolrunner.js.map 934 | 935 | /***/ }), 936 | 937 | /***/ 16: 938 | /***/ (function(module) { 939 | 940 | module.exports = require("tls"); 941 | 942 | /***/ }), 943 | 944 | /***/ 82: 945 | /***/ (function(__unusedmodule, exports) { 946 | 947 | "use strict"; 948 | 949 | // We use any as a valid input type 950 | /* eslint-disable @typescript-eslint/no-explicit-any */ 951 | Object.defineProperty(exports, "__esModule", { value: true }); 952 | /** 953 | * Sanitizes an input into a string so it can be passed into issueCommand safely 954 | * @param input input to sanitize into a string 955 | */ 956 | function toCommandValue(input) { 957 | if (input === null || input === undefined) { 958 | return ''; 959 | } 960 | else if (typeof input === 'string' || input instanceof String) { 961 | return input; 962 | } 963 | return JSON.stringify(input); 964 | } 965 | exports.toCommandValue = toCommandValue; 966 | //# sourceMappingURL=utils.js.map 967 | 968 | /***/ }), 969 | 970 | /***/ 87: 971 | /***/ (function(module) { 972 | 973 | module.exports = require("os"); 974 | 975 | /***/ }), 976 | 977 | /***/ 102: 978 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 979 | 980 | "use strict"; 981 | 982 | // For internal use, subject to change. 983 | var __importStar = (this && this.__importStar) || function (mod) { 984 | if (mod && mod.__esModule) return mod; 985 | var result = {}; 986 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 987 | result["default"] = mod; 988 | return result; 989 | }; 990 | Object.defineProperty(exports, "__esModule", { value: true }); 991 | // We use any as a valid input type 992 | /* eslint-disable @typescript-eslint/no-explicit-any */ 993 | const fs = __importStar(__webpack_require__(747)); 994 | const os = __importStar(__webpack_require__(87)); 995 | const utils_1 = __webpack_require__(82); 996 | function issueCommand(command, message) { 997 | const filePath = process.env[`GITHUB_${command}`]; 998 | if (!filePath) { 999 | throw new Error(`Unable to find environment variable for file command ${command}`); 1000 | } 1001 | if (!fs.existsSync(filePath)) { 1002 | throw new Error(`Missing file at path: ${filePath}`); 1003 | } 1004 | fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { 1005 | encoding: 'utf8' 1006 | }); 1007 | } 1008 | exports.issueCommand = issueCommand; 1009 | //# sourceMappingURL=file-command.js.map 1010 | 1011 | /***/ }), 1012 | 1013 | /***/ 129: 1014 | /***/ (function(module) { 1015 | 1016 | module.exports = require("child_process"); 1017 | 1018 | /***/ }), 1019 | 1020 | /***/ 139: 1021 | /***/ (function(module, __unusedexports, __webpack_require__) { 1022 | 1023 | // Unique ID creation requires a high quality random # generator. In node.js 1024 | // this is pretty straight-forward - we use the crypto API. 1025 | 1026 | var crypto = __webpack_require__(417); 1027 | 1028 | module.exports = function nodeRNG() { 1029 | return crypto.randomBytes(16); 1030 | }; 1031 | 1032 | 1033 | /***/ }), 1034 | 1035 | /***/ 141: 1036 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1037 | 1038 | "use strict"; 1039 | 1040 | 1041 | var net = __webpack_require__(631); 1042 | var tls = __webpack_require__(16); 1043 | var http = __webpack_require__(605); 1044 | var https = __webpack_require__(211); 1045 | var events = __webpack_require__(614); 1046 | var assert = __webpack_require__(357); 1047 | var util = __webpack_require__(669); 1048 | 1049 | 1050 | exports.httpOverHttp = httpOverHttp; 1051 | exports.httpsOverHttp = httpsOverHttp; 1052 | exports.httpOverHttps = httpOverHttps; 1053 | exports.httpsOverHttps = httpsOverHttps; 1054 | 1055 | 1056 | function httpOverHttp(options) { 1057 | var agent = new TunnelingAgent(options); 1058 | agent.request = http.request; 1059 | return agent; 1060 | } 1061 | 1062 | function httpsOverHttp(options) { 1063 | var agent = new TunnelingAgent(options); 1064 | agent.request = http.request; 1065 | agent.createSocket = createSecureSocket; 1066 | agent.defaultPort = 443; 1067 | return agent; 1068 | } 1069 | 1070 | function httpOverHttps(options) { 1071 | var agent = new TunnelingAgent(options); 1072 | agent.request = https.request; 1073 | return agent; 1074 | } 1075 | 1076 | function httpsOverHttps(options) { 1077 | var agent = new TunnelingAgent(options); 1078 | agent.request = https.request; 1079 | agent.createSocket = createSecureSocket; 1080 | agent.defaultPort = 443; 1081 | return agent; 1082 | } 1083 | 1084 | 1085 | function TunnelingAgent(options) { 1086 | var self = this; 1087 | self.options = options || {}; 1088 | self.proxyOptions = self.options.proxy || {}; 1089 | self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; 1090 | self.requests = []; 1091 | self.sockets = []; 1092 | 1093 | self.on('free', function onFree(socket, host, port, localAddress) { 1094 | var options = toOptions(host, port, localAddress); 1095 | for (var i = 0, len = self.requests.length; i < len; ++i) { 1096 | var pending = self.requests[i]; 1097 | if (pending.host === options.host && pending.port === options.port) { 1098 | // Detect the request to connect same origin server, 1099 | // reuse the connection. 1100 | self.requests.splice(i, 1); 1101 | pending.request.onSocket(socket); 1102 | return; 1103 | } 1104 | } 1105 | socket.destroy(); 1106 | self.removeSocket(socket); 1107 | }); 1108 | } 1109 | util.inherits(TunnelingAgent, events.EventEmitter); 1110 | 1111 | TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { 1112 | var self = this; 1113 | var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); 1114 | 1115 | if (self.sockets.length >= this.maxSockets) { 1116 | // We are over limit so we'll add it to the queue. 1117 | self.requests.push(options); 1118 | return; 1119 | } 1120 | 1121 | // If we are under maxSockets create a new one. 1122 | self.createSocket(options, function(socket) { 1123 | socket.on('free', onFree); 1124 | socket.on('close', onCloseOrRemove); 1125 | socket.on('agentRemove', onCloseOrRemove); 1126 | req.onSocket(socket); 1127 | 1128 | function onFree() { 1129 | self.emit('free', socket, options); 1130 | } 1131 | 1132 | function onCloseOrRemove(err) { 1133 | self.removeSocket(socket); 1134 | socket.removeListener('free', onFree); 1135 | socket.removeListener('close', onCloseOrRemove); 1136 | socket.removeListener('agentRemove', onCloseOrRemove); 1137 | } 1138 | }); 1139 | }; 1140 | 1141 | TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { 1142 | var self = this; 1143 | var placeholder = {}; 1144 | self.sockets.push(placeholder); 1145 | 1146 | var connectOptions = mergeOptions({}, self.proxyOptions, { 1147 | method: 'CONNECT', 1148 | path: options.host + ':' + options.port, 1149 | agent: false, 1150 | headers: { 1151 | host: options.host + ':' + options.port 1152 | } 1153 | }); 1154 | if (options.localAddress) { 1155 | connectOptions.localAddress = options.localAddress; 1156 | } 1157 | if (connectOptions.proxyAuth) { 1158 | connectOptions.headers = connectOptions.headers || {}; 1159 | connectOptions.headers['Proxy-Authorization'] = 'Basic ' + 1160 | new Buffer(connectOptions.proxyAuth).toString('base64'); 1161 | } 1162 | 1163 | debug('making CONNECT request'); 1164 | var connectReq = self.request(connectOptions); 1165 | connectReq.useChunkedEncodingByDefault = false; // for v0.6 1166 | connectReq.once('response', onResponse); // for v0.6 1167 | connectReq.once('upgrade', onUpgrade); // for v0.6 1168 | connectReq.once('connect', onConnect); // for v0.7 or later 1169 | connectReq.once('error', onError); 1170 | connectReq.end(); 1171 | 1172 | function onResponse(res) { 1173 | // Very hacky. This is necessary to avoid http-parser leaks. 1174 | res.upgrade = true; 1175 | } 1176 | 1177 | function onUpgrade(res, socket, head) { 1178 | // Hacky. 1179 | process.nextTick(function() { 1180 | onConnect(res, socket, head); 1181 | }); 1182 | } 1183 | 1184 | function onConnect(res, socket, head) { 1185 | connectReq.removeAllListeners(); 1186 | socket.removeAllListeners(); 1187 | 1188 | if (res.statusCode !== 200) { 1189 | debug('tunneling socket could not be established, statusCode=%d', 1190 | res.statusCode); 1191 | socket.destroy(); 1192 | var error = new Error('tunneling socket could not be established, ' + 1193 | 'statusCode=' + res.statusCode); 1194 | error.code = 'ECONNRESET'; 1195 | options.request.emit('error', error); 1196 | self.removeSocket(placeholder); 1197 | return; 1198 | } 1199 | if (head.length > 0) { 1200 | debug('got illegal response body from proxy'); 1201 | socket.destroy(); 1202 | var error = new Error('got illegal response body from proxy'); 1203 | error.code = 'ECONNRESET'; 1204 | options.request.emit('error', error); 1205 | self.removeSocket(placeholder); 1206 | return; 1207 | } 1208 | debug('tunneling connection has established'); 1209 | self.sockets[self.sockets.indexOf(placeholder)] = socket; 1210 | return cb(socket); 1211 | } 1212 | 1213 | function onError(cause) { 1214 | connectReq.removeAllListeners(); 1215 | 1216 | debug('tunneling socket could not be established, cause=%s\n', 1217 | cause.message, cause.stack); 1218 | var error = new Error('tunneling socket could not be established, ' + 1219 | 'cause=' + cause.message); 1220 | error.code = 'ECONNRESET'; 1221 | options.request.emit('error', error); 1222 | self.removeSocket(placeholder); 1223 | } 1224 | }; 1225 | 1226 | TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { 1227 | var pos = this.sockets.indexOf(socket) 1228 | if (pos === -1) { 1229 | return; 1230 | } 1231 | this.sockets.splice(pos, 1); 1232 | 1233 | var pending = this.requests.shift(); 1234 | if (pending) { 1235 | // If we have pending requests and a socket gets closed a new one 1236 | // needs to be created to take over in the pool for the one that closed. 1237 | this.createSocket(pending, function(socket) { 1238 | pending.request.onSocket(socket); 1239 | }); 1240 | } 1241 | }; 1242 | 1243 | function createSecureSocket(options, cb) { 1244 | var self = this; 1245 | TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { 1246 | var hostHeader = options.request.getHeader('host'); 1247 | var tlsOptions = mergeOptions({}, self.options, { 1248 | socket: socket, 1249 | servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host 1250 | }); 1251 | 1252 | // 0 is dummy port for v0.6 1253 | var secureSocket = tls.connect(0, tlsOptions); 1254 | self.sockets[self.sockets.indexOf(socket)] = secureSocket; 1255 | cb(secureSocket); 1256 | }); 1257 | } 1258 | 1259 | 1260 | function toOptions(host, port, localAddress) { 1261 | if (typeof host === 'string') { // since v0.10 1262 | return { 1263 | host: host, 1264 | port: port, 1265 | localAddress: localAddress 1266 | }; 1267 | } 1268 | return host; // for v0.11 or later 1269 | } 1270 | 1271 | function mergeOptions(target) { 1272 | for (var i = 1, len = arguments.length; i < len; ++i) { 1273 | var overrides = arguments[i]; 1274 | if (typeof overrides === 'object') { 1275 | var keys = Object.keys(overrides); 1276 | for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { 1277 | var k = keys[j]; 1278 | if (overrides[k] !== undefined) { 1279 | target[k] = overrides[k]; 1280 | } 1281 | } 1282 | } 1283 | } 1284 | return target; 1285 | } 1286 | 1287 | 1288 | var debug; 1289 | if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { 1290 | debug = function() { 1291 | var args = Array.prototype.slice.call(arguments); 1292 | if (typeof args[0] === 'string') { 1293 | args[0] = 'TUNNEL: ' + args[0]; 1294 | } else { 1295 | args.unshift('TUNNEL:'); 1296 | } 1297 | console.error.apply(console, args); 1298 | } 1299 | } else { 1300 | debug = function() {}; 1301 | } 1302 | exports.debug = debug; // for test 1303 | 1304 | 1305 | /***/ }), 1306 | 1307 | /***/ 198: 1308 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1309 | 1310 | "use strict"; 1311 | 1312 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1313 | return new (P || (P = Promise))(function (resolve, reject) { 1314 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1315 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1316 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 1317 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1318 | }); 1319 | }; 1320 | var __importStar = (this && this.__importStar) || function (mod) { 1321 | if (mod && mod.__esModule) return mod; 1322 | var result = {}; 1323 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 1324 | result["default"] = mod; 1325 | return result; 1326 | }; 1327 | Object.defineProperty(exports, "__esModule", { value: true }); 1328 | const core = __importStar(__webpack_require__(470)); 1329 | const cache = __importStar(__webpack_require__(365)); 1330 | function run() { 1331 | return __awaiter(this, void 0, void 0, function* () { 1332 | try { 1333 | core.info('------------------------'); 1334 | core.info('NOTE: This action is deprecated and is no longer maintained.'); 1335 | core.info('Please, migrate to https://github.com/ruby/setup-ruby, which is being actively maintained.'); 1336 | core.info('------------------------'); 1337 | let versionSpec = core.getInput('ruby-version', { required: true }); 1338 | if (!versionSpec) { 1339 | // deprecated 1340 | versionSpec = core.getInput('version'); 1341 | } 1342 | // check in the VMs cache first 1343 | let toolPath = yield cache.find(versionSpec); 1344 | // TODO: download JIT and/or ruby-build 1345 | if (!toolPath) { 1346 | core.setFailed(`Version ${versionSpec} not found`); 1347 | return; 1348 | } 1349 | core.addPath(toolPath); 1350 | } 1351 | catch (error) { 1352 | // unhandled 1353 | core.setFailed(error.message); 1354 | } 1355 | }); 1356 | } 1357 | exports.run = run; 1358 | 1359 | 1360 | /***/ }), 1361 | 1362 | /***/ 211: 1363 | /***/ (function(module) { 1364 | 1365 | module.exports = require("https"); 1366 | 1367 | /***/ }), 1368 | 1369 | /***/ 280: 1370 | /***/ (function(module, exports) { 1371 | 1372 | exports = module.exports = SemVer 1373 | 1374 | var debug 1375 | /* istanbul ignore next */ 1376 | if (typeof process === 'object' && 1377 | process.env && 1378 | process.env.NODE_DEBUG && 1379 | /\bsemver\b/i.test(process.env.NODE_DEBUG)) { 1380 | debug = function () { 1381 | var args = Array.prototype.slice.call(arguments, 0) 1382 | args.unshift('SEMVER') 1383 | console.log.apply(console, args) 1384 | } 1385 | } else { 1386 | debug = function () {} 1387 | } 1388 | 1389 | // Note: this is the semver.org version of the spec that it implements 1390 | // Not necessarily the package version of this code. 1391 | exports.SEMVER_SPEC_VERSION = '2.0.0' 1392 | 1393 | var MAX_LENGTH = 256 1394 | var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 1395 | /* istanbul ignore next */ 9007199254740991 1396 | 1397 | // Max safe segment length for coercion. 1398 | var MAX_SAFE_COMPONENT_LENGTH = 16 1399 | 1400 | // The actual regexps go on exports.re 1401 | var re = exports.re = [] 1402 | var src = exports.src = [] 1403 | var t = exports.tokens = {} 1404 | var R = 0 1405 | 1406 | function tok (n) { 1407 | t[n] = R++ 1408 | } 1409 | 1410 | // The following Regular Expressions can be used for tokenizing, 1411 | // validating, and parsing SemVer version strings. 1412 | 1413 | // ## Numeric Identifier 1414 | // A single `0`, or a non-zero digit followed by zero or more digits. 1415 | 1416 | tok('NUMERICIDENTIFIER') 1417 | src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' 1418 | tok('NUMERICIDENTIFIERLOOSE') 1419 | src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+' 1420 | 1421 | // ## Non-numeric Identifier 1422 | // Zero or more digits, followed by a letter or hyphen, and then zero or 1423 | // more letters, digits, or hyphens. 1424 | 1425 | tok('NONNUMERICIDENTIFIER') 1426 | src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' 1427 | 1428 | // ## Main Version 1429 | // Three dot-separated numeric identifiers. 1430 | 1431 | tok('MAINVERSION') 1432 | src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + 1433 | '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + 1434 | '(' + src[t.NUMERICIDENTIFIER] + ')' 1435 | 1436 | tok('MAINVERSIONLOOSE') 1437 | src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + 1438 | '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + 1439 | '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')' 1440 | 1441 | // ## Pre-release Version Identifier 1442 | // A numeric identifier, or a non-numeric identifier. 1443 | 1444 | tok('PRERELEASEIDENTIFIER') 1445 | src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] + 1446 | '|' + src[t.NONNUMERICIDENTIFIER] + ')' 1447 | 1448 | tok('PRERELEASEIDENTIFIERLOOSE') 1449 | src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] + 1450 | '|' + src[t.NONNUMERICIDENTIFIER] + ')' 1451 | 1452 | // ## Pre-release Version 1453 | // Hyphen, followed by one or more dot-separated pre-release version 1454 | // identifiers. 1455 | 1456 | tok('PRERELEASE') 1457 | src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] + 1458 | '(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))' 1459 | 1460 | tok('PRERELEASELOOSE') 1461 | src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + 1462 | '(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))' 1463 | 1464 | // ## Build Metadata Identifier 1465 | // Any combination of digits, letters, or hyphens. 1466 | 1467 | tok('BUILDIDENTIFIER') 1468 | src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+' 1469 | 1470 | // ## Build Metadata 1471 | // Plus sign, followed by one or more period-separated build metadata 1472 | // identifiers. 1473 | 1474 | tok('BUILD') 1475 | src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] + 1476 | '(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))' 1477 | 1478 | // ## Full Version String 1479 | // A main version, followed optionally by a pre-release version and 1480 | // build metadata. 1481 | 1482 | // Note that the only major, minor, patch, and pre-release sections of 1483 | // the version string are capturing groups. The build metadata is not a 1484 | // capturing group, because it should not ever be used in version 1485 | // comparison. 1486 | 1487 | tok('FULL') 1488 | tok('FULLPLAIN') 1489 | src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] + 1490 | src[t.PRERELEASE] + '?' + 1491 | src[t.BUILD] + '?' 1492 | 1493 | src[t.FULL] = '^' + src[t.FULLPLAIN] + '$' 1494 | 1495 | // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. 1496 | // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty 1497 | // common in the npm registry. 1498 | tok('LOOSEPLAIN') 1499 | src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] + 1500 | src[t.PRERELEASELOOSE] + '?' + 1501 | src[t.BUILD] + '?' 1502 | 1503 | tok('LOOSE') 1504 | src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$' 1505 | 1506 | tok('GTLT') 1507 | src[t.GTLT] = '((?:<|>)?=?)' 1508 | 1509 | // Something like "2.*" or "1.2.x". 1510 | // Note that "x.x" is a valid xRange identifer, meaning "any version" 1511 | // Only the first item is strictly required. 1512 | tok('XRANGEIDENTIFIERLOOSE') 1513 | src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' 1514 | tok('XRANGEIDENTIFIER') 1515 | src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*' 1516 | 1517 | tok('XRANGEPLAIN') 1518 | src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' + 1519 | '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + 1520 | '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + 1521 | '(?:' + src[t.PRERELEASE] + ')?' + 1522 | src[t.BUILD] + '?' + 1523 | ')?)?' 1524 | 1525 | tok('XRANGEPLAINLOOSE') 1526 | src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 1527 | '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 1528 | '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 1529 | '(?:' + src[t.PRERELEASELOOSE] + ')?' + 1530 | src[t.BUILD] + '?' + 1531 | ')?)?' 1532 | 1533 | tok('XRANGE') 1534 | src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$' 1535 | tok('XRANGELOOSE') 1536 | src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$' 1537 | 1538 | // Coercion. 1539 | // Extract anything that could conceivably be a part of a valid semver 1540 | tok('COERCE') 1541 | src[t.COERCE] = '(^|[^\\d])' + 1542 | '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + 1543 | '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 1544 | '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 1545 | '(?:$|[^\\d])' 1546 | tok('COERCERTL') 1547 | re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') 1548 | 1549 | // Tilde ranges. 1550 | // Meaning is "reasonably at or greater than" 1551 | tok('LONETILDE') 1552 | src[t.LONETILDE] = '(?:~>?)' 1553 | 1554 | tok('TILDETRIM') 1555 | src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' 1556 | re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') 1557 | var tildeTrimReplace = '$1~' 1558 | 1559 | tok('TILDE') 1560 | src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$' 1561 | tok('TILDELOOSE') 1562 | src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$' 1563 | 1564 | // Caret ranges. 1565 | // Meaning is "at least and backwards compatible with" 1566 | tok('LONECARET') 1567 | src[t.LONECARET] = '(?:\\^)' 1568 | 1569 | tok('CARETTRIM') 1570 | src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' 1571 | re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') 1572 | var caretTrimReplace = '$1^' 1573 | 1574 | tok('CARET') 1575 | src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$' 1576 | tok('CARETLOOSE') 1577 | src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$' 1578 | 1579 | // A simple gt/lt/eq thing, or just "" to indicate "any version" 1580 | tok('COMPARATORLOOSE') 1581 | src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$' 1582 | tok('COMPARATOR') 1583 | src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$' 1584 | 1585 | // An expression to strip any whitespace between the gtlt and the thing 1586 | // it modifies, so that `> 1.2.3` ==> `>1.2.3` 1587 | tok('COMPARATORTRIM') 1588 | src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + 1589 | '\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')' 1590 | 1591 | // this one has to use the /g flag 1592 | re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') 1593 | var comparatorTrimReplace = '$1$2$3' 1594 | 1595 | // Something like `1.2.3 - 1.2.4` 1596 | // Note that these all use the loose form, because they'll be 1597 | // checked against either the strict or loose comparator form 1598 | // later. 1599 | tok('HYPHENRANGE') 1600 | src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' + 1601 | '\\s+-\\s+' + 1602 | '(' + src[t.XRANGEPLAIN] + ')' + 1603 | '\\s*$' 1604 | 1605 | tok('HYPHENRANGELOOSE') 1606 | src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' + 1607 | '\\s+-\\s+' + 1608 | '(' + src[t.XRANGEPLAINLOOSE] + ')' + 1609 | '\\s*$' 1610 | 1611 | // Star ranges basically just allow anything at all. 1612 | tok('STAR') 1613 | src[t.STAR] = '(<|>)?=?\\s*\\*' 1614 | 1615 | // Compile to actual regexp objects. 1616 | // All are flag-free, unless they were created above with a flag. 1617 | for (var i = 0; i < R; i++) { 1618 | debug(i, src[i]) 1619 | if (!re[i]) { 1620 | re[i] = new RegExp(src[i]) 1621 | } 1622 | } 1623 | 1624 | exports.parse = parse 1625 | function parse (version, options) { 1626 | if (!options || typeof options !== 'object') { 1627 | options = { 1628 | loose: !!options, 1629 | includePrerelease: false 1630 | } 1631 | } 1632 | 1633 | if (version instanceof SemVer) { 1634 | return version 1635 | } 1636 | 1637 | if (typeof version !== 'string') { 1638 | return null 1639 | } 1640 | 1641 | if (version.length > MAX_LENGTH) { 1642 | return null 1643 | } 1644 | 1645 | var r = options.loose ? re[t.LOOSE] : re[t.FULL] 1646 | if (!r.test(version)) { 1647 | return null 1648 | } 1649 | 1650 | try { 1651 | return new SemVer(version, options) 1652 | } catch (er) { 1653 | return null 1654 | } 1655 | } 1656 | 1657 | exports.valid = valid 1658 | function valid (version, options) { 1659 | var v = parse(version, options) 1660 | return v ? v.version : null 1661 | } 1662 | 1663 | exports.clean = clean 1664 | function clean (version, options) { 1665 | var s = parse(version.trim().replace(/^[=v]+/, ''), options) 1666 | return s ? s.version : null 1667 | } 1668 | 1669 | exports.SemVer = SemVer 1670 | 1671 | function SemVer (version, options) { 1672 | if (!options || typeof options !== 'object') { 1673 | options = { 1674 | loose: !!options, 1675 | includePrerelease: false 1676 | } 1677 | } 1678 | if (version instanceof SemVer) { 1679 | if (version.loose === options.loose) { 1680 | return version 1681 | } else { 1682 | version = version.version 1683 | } 1684 | } else if (typeof version !== 'string') { 1685 | throw new TypeError('Invalid Version: ' + version) 1686 | } 1687 | 1688 | if (version.length > MAX_LENGTH) { 1689 | throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') 1690 | } 1691 | 1692 | if (!(this instanceof SemVer)) { 1693 | return new SemVer(version, options) 1694 | } 1695 | 1696 | debug('SemVer', version, options) 1697 | this.options = options 1698 | this.loose = !!options.loose 1699 | 1700 | var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) 1701 | 1702 | if (!m) { 1703 | throw new TypeError('Invalid Version: ' + version) 1704 | } 1705 | 1706 | this.raw = version 1707 | 1708 | // these are actually numbers 1709 | this.major = +m[1] 1710 | this.minor = +m[2] 1711 | this.patch = +m[3] 1712 | 1713 | if (this.major > MAX_SAFE_INTEGER || this.major < 0) { 1714 | throw new TypeError('Invalid major version') 1715 | } 1716 | 1717 | if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { 1718 | throw new TypeError('Invalid minor version') 1719 | } 1720 | 1721 | if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { 1722 | throw new TypeError('Invalid patch version') 1723 | } 1724 | 1725 | // numberify any prerelease numeric ids 1726 | if (!m[4]) { 1727 | this.prerelease = [] 1728 | } else { 1729 | this.prerelease = m[4].split('.').map(function (id) { 1730 | if (/^[0-9]+$/.test(id)) { 1731 | var num = +id 1732 | if (num >= 0 && num < MAX_SAFE_INTEGER) { 1733 | return num 1734 | } 1735 | } 1736 | return id 1737 | }) 1738 | } 1739 | 1740 | this.build = m[5] ? m[5].split('.') : [] 1741 | this.format() 1742 | } 1743 | 1744 | SemVer.prototype.format = function () { 1745 | this.version = this.major + '.' + this.minor + '.' + this.patch 1746 | if (this.prerelease.length) { 1747 | this.version += '-' + this.prerelease.join('.') 1748 | } 1749 | return this.version 1750 | } 1751 | 1752 | SemVer.prototype.toString = function () { 1753 | return this.version 1754 | } 1755 | 1756 | SemVer.prototype.compare = function (other) { 1757 | debug('SemVer.compare', this.version, this.options, other) 1758 | if (!(other instanceof SemVer)) { 1759 | other = new SemVer(other, this.options) 1760 | } 1761 | 1762 | return this.compareMain(other) || this.comparePre(other) 1763 | } 1764 | 1765 | SemVer.prototype.compareMain = function (other) { 1766 | if (!(other instanceof SemVer)) { 1767 | other = new SemVer(other, this.options) 1768 | } 1769 | 1770 | return compareIdentifiers(this.major, other.major) || 1771 | compareIdentifiers(this.minor, other.minor) || 1772 | compareIdentifiers(this.patch, other.patch) 1773 | } 1774 | 1775 | SemVer.prototype.comparePre = function (other) { 1776 | if (!(other instanceof SemVer)) { 1777 | other = new SemVer(other, this.options) 1778 | } 1779 | 1780 | // NOT having a prerelease is > having one 1781 | if (this.prerelease.length && !other.prerelease.length) { 1782 | return -1 1783 | } else if (!this.prerelease.length && other.prerelease.length) { 1784 | return 1 1785 | } else if (!this.prerelease.length && !other.prerelease.length) { 1786 | return 0 1787 | } 1788 | 1789 | var i = 0 1790 | do { 1791 | var a = this.prerelease[i] 1792 | var b = other.prerelease[i] 1793 | debug('prerelease compare', i, a, b) 1794 | if (a === undefined && b === undefined) { 1795 | return 0 1796 | } else if (b === undefined) { 1797 | return 1 1798 | } else if (a === undefined) { 1799 | return -1 1800 | } else if (a === b) { 1801 | continue 1802 | } else { 1803 | return compareIdentifiers(a, b) 1804 | } 1805 | } while (++i) 1806 | } 1807 | 1808 | SemVer.prototype.compareBuild = function (other) { 1809 | if (!(other instanceof SemVer)) { 1810 | other = new SemVer(other, this.options) 1811 | } 1812 | 1813 | var i = 0 1814 | do { 1815 | var a = this.build[i] 1816 | var b = other.build[i] 1817 | debug('prerelease compare', i, a, b) 1818 | if (a === undefined && b === undefined) { 1819 | return 0 1820 | } else if (b === undefined) { 1821 | return 1 1822 | } else if (a === undefined) { 1823 | return -1 1824 | } else if (a === b) { 1825 | continue 1826 | } else { 1827 | return compareIdentifiers(a, b) 1828 | } 1829 | } while (++i) 1830 | } 1831 | 1832 | // preminor will bump the version up to the next minor release, and immediately 1833 | // down to pre-release. premajor and prepatch work the same way. 1834 | SemVer.prototype.inc = function (release, identifier) { 1835 | switch (release) { 1836 | case 'premajor': 1837 | this.prerelease.length = 0 1838 | this.patch = 0 1839 | this.minor = 0 1840 | this.major++ 1841 | this.inc('pre', identifier) 1842 | break 1843 | case 'preminor': 1844 | this.prerelease.length = 0 1845 | this.patch = 0 1846 | this.minor++ 1847 | this.inc('pre', identifier) 1848 | break 1849 | case 'prepatch': 1850 | // If this is already a prerelease, it will bump to the next version 1851 | // drop any prereleases that might already exist, since they are not 1852 | // relevant at this point. 1853 | this.prerelease.length = 0 1854 | this.inc('patch', identifier) 1855 | this.inc('pre', identifier) 1856 | break 1857 | // If the input is a non-prerelease version, this acts the same as 1858 | // prepatch. 1859 | case 'prerelease': 1860 | if (this.prerelease.length === 0) { 1861 | this.inc('patch', identifier) 1862 | } 1863 | this.inc('pre', identifier) 1864 | break 1865 | 1866 | case 'major': 1867 | // If this is a pre-major version, bump up to the same major version. 1868 | // Otherwise increment major. 1869 | // 1.0.0-5 bumps to 1.0.0 1870 | // 1.1.0 bumps to 2.0.0 1871 | if (this.minor !== 0 || 1872 | this.patch !== 0 || 1873 | this.prerelease.length === 0) { 1874 | this.major++ 1875 | } 1876 | this.minor = 0 1877 | this.patch = 0 1878 | this.prerelease = [] 1879 | break 1880 | case 'minor': 1881 | // If this is a pre-minor version, bump up to the same minor version. 1882 | // Otherwise increment minor. 1883 | // 1.2.0-5 bumps to 1.2.0 1884 | // 1.2.1 bumps to 1.3.0 1885 | if (this.patch !== 0 || this.prerelease.length === 0) { 1886 | this.minor++ 1887 | } 1888 | this.patch = 0 1889 | this.prerelease = [] 1890 | break 1891 | case 'patch': 1892 | // If this is not a pre-release version, it will increment the patch. 1893 | // If it is a pre-release it will bump up to the same patch version. 1894 | // 1.2.0-5 patches to 1.2.0 1895 | // 1.2.0 patches to 1.2.1 1896 | if (this.prerelease.length === 0) { 1897 | this.patch++ 1898 | } 1899 | this.prerelease = [] 1900 | break 1901 | // This probably shouldn't be used publicly. 1902 | // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. 1903 | case 'pre': 1904 | if (this.prerelease.length === 0) { 1905 | this.prerelease = [0] 1906 | } else { 1907 | var i = this.prerelease.length 1908 | while (--i >= 0) { 1909 | if (typeof this.prerelease[i] === 'number') { 1910 | this.prerelease[i]++ 1911 | i = -2 1912 | } 1913 | } 1914 | if (i === -1) { 1915 | // didn't increment anything 1916 | this.prerelease.push(0) 1917 | } 1918 | } 1919 | if (identifier) { 1920 | // 1.2.0-beta.1 bumps to 1.2.0-beta.2, 1921 | // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 1922 | if (this.prerelease[0] === identifier) { 1923 | if (isNaN(this.prerelease[1])) { 1924 | this.prerelease = [identifier, 0] 1925 | } 1926 | } else { 1927 | this.prerelease = [identifier, 0] 1928 | } 1929 | } 1930 | break 1931 | 1932 | default: 1933 | throw new Error('invalid increment argument: ' + release) 1934 | } 1935 | this.format() 1936 | this.raw = this.version 1937 | return this 1938 | } 1939 | 1940 | exports.inc = inc 1941 | function inc (version, release, loose, identifier) { 1942 | if (typeof (loose) === 'string') { 1943 | identifier = loose 1944 | loose = undefined 1945 | } 1946 | 1947 | try { 1948 | return new SemVer(version, loose).inc(release, identifier).version 1949 | } catch (er) { 1950 | return null 1951 | } 1952 | } 1953 | 1954 | exports.diff = diff 1955 | function diff (version1, version2) { 1956 | if (eq(version1, version2)) { 1957 | return null 1958 | } else { 1959 | var v1 = parse(version1) 1960 | var v2 = parse(version2) 1961 | var prefix = '' 1962 | if (v1.prerelease.length || v2.prerelease.length) { 1963 | prefix = 'pre' 1964 | var defaultResult = 'prerelease' 1965 | } 1966 | for (var key in v1) { 1967 | if (key === 'major' || key === 'minor' || key === 'patch') { 1968 | if (v1[key] !== v2[key]) { 1969 | return prefix + key 1970 | } 1971 | } 1972 | } 1973 | return defaultResult // may be undefined 1974 | } 1975 | } 1976 | 1977 | exports.compareIdentifiers = compareIdentifiers 1978 | 1979 | var numeric = /^[0-9]+$/ 1980 | function compareIdentifiers (a, b) { 1981 | var anum = numeric.test(a) 1982 | var bnum = numeric.test(b) 1983 | 1984 | if (anum && bnum) { 1985 | a = +a 1986 | b = +b 1987 | } 1988 | 1989 | return a === b ? 0 1990 | : (anum && !bnum) ? -1 1991 | : (bnum && !anum) ? 1 1992 | : a < b ? -1 1993 | : 1 1994 | } 1995 | 1996 | exports.rcompareIdentifiers = rcompareIdentifiers 1997 | function rcompareIdentifiers (a, b) { 1998 | return compareIdentifiers(b, a) 1999 | } 2000 | 2001 | exports.major = major 2002 | function major (a, loose) { 2003 | return new SemVer(a, loose).major 2004 | } 2005 | 2006 | exports.minor = minor 2007 | function minor (a, loose) { 2008 | return new SemVer(a, loose).minor 2009 | } 2010 | 2011 | exports.patch = patch 2012 | function patch (a, loose) { 2013 | return new SemVer(a, loose).patch 2014 | } 2015 | 2016 | exports.compare = compare 2017 | function compare (a, b, loose) { 2018 | return new SemVer(a, loose).compare(new SemVer(b, loose)) 2019 | } 2020 | 2021 | exports.compareLoose = compareLoose 2022 | function compareLoose (a, b) { 2023 | return compare(a, b, true) 2024 | } 2025 | 2026 | exports.compareBuild = compareBuild 2027 | function compareBuild (a, b, loose) { 2028 | var versionA = new SemVer(a, loose) 2029 | var versionB = new SemVer(b, loose) 2030 | return versionA.compare(versionB) || versionA.compareBuild(versionB) 2031 | } 2032 | 2033 | exports.rcompare = rcompare 2034 | function rcompare (a, b, loose) { 2035 | return compare(b, a, loose) 2036 | } 2037 | 2038 | exports.sort = sort 2039 | function sort (list, loose) { 2040 | return list.sort(function (a, b) { 2041 | return exports.compareBuild(a, b, loose) 2042 | }) 2043 | } 2044 | 2045 | exports.rsort = rsort 2046 | function rsort (list, loose) { 2047 | return list.sort(function (a, b) { 2048 | return exports.compareBuild(b, a, loose) 2049 | }) 2050 | } 2051 | 2052 | exports.gt = gt 2053 | function gt (a, b, loose) { 2054 | return compare(a, b, loose) > 0 2055 | } 2056 | 2057 | exports.lt = lt 2058 | function lt (a, b, loose) { 2059 | return compare(a, b, loose) < 0 2060 | } 2061 | 2062 | exports.eq = eq 2063 | function eq (a, b, loose) { 2064 | return compare(a, b, loose) === 0 2065 | } 2066 | 2067 | exports.neq = neq 2068 | function neq (a, b, loose) { 2069 | return compare(a, b, loose) !== 0 2070 | } 2071 | 2072 | exports.gte = gte 2073 | function gte (a, b, loose) { 2074 | return compare(a, b, loose) >= 0 2075 | } 2076 | 2077 | exports.lte = lte 2078 | function lte (a, b, loose) { 2079 | return compare(a, b, loose) <= 0 2080 | } 2081 | 2082 | exports.cmp = cmp 2083 | function cmp (a, op, b, loose) { 2084 | switch (op) { 2085 | case '===': 2086 | if (typeof a === 'object') 2087 | a = a.version 2088 | if (typeof b === 'object') 2089 | b = b.version 2090 | return a === b 2091 | 2092 | case '!==': 2093 | if (typeof a === 'object') 2094 | a = a.version 2095 | if (typeof b === 'object') 2096 | b = b.version 2097 | return a !== b 2098 | 2099 | case '': 2100 | case '=': 2101 | case '==': 2102 | return eq(a, b, loose) 2103 | 2104 | case '!=': 2105 | return neq(a, b, loose) 2106 | 2107 | case '>': 2108 | return gt(a, b, loose) 2109 | 2110 | case '>=': 2111 | return gte(a, b, loose) 2112 | 2113 | case '<': 2114 | return lt(a, b, loose) 2115 | 2116 | case '<=': 2117 | return lte(a, b, loose) 2118 | 2119 | default: 2120 | throw new TypeError('Invalid operator: ' + op) 2121 | } 2122 | } 2123 | 2124 | exports.Comparator = Comparator 2125 | function Comparator (comp, options) { 2126 | if (!options || typeof options !== 'object') { 2127 | options = { 2128 | loose: !!options, 2129 | includePrerelease: false 2130 | } 2131 | } 2132 | 2133 | if (comp instanceof Comparator) { 2134 | if (comp.loose === !!options.loose) { 2135 | return comp 2136 | } else { 2137 | comp = comp.value 2138 | } 2139 | } 2140 | 2141 | if (!(this instanceof Comparator)) { 2142 | return new Comparator(comp, options) 2143 | } 2144 | 2145 | debug('comparator', comp, options) 2146 | this.options = options 2147 | this.loose = !!options.loose 2148 | this.parse(comp) 2149 | 2150 | if (this.semver === ANY) { 2151 | this.value = '' 2152 | } else { 2153 | this.value = this.operator + this.semver.version 2154 | } 2155 | 2156 | debug('comp', this) 2157 | } 2158 | 2159 | var ANY = {} 2160 | Comparator.prototype.parse = function (comp) { 2161 | var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] 2162 | var m = comp.match(r) 2163 | 2164 | if (!m) { 2165 | throw new TypeError('Invalid comparator: ' + comp) 2166 | } 2167 | 2168 | this.operator = m[1] !== undefined ? m[1] : '' 2169 | if (this.operator === '=') { 2170 | this.operator = '' 2171 | } 2172 | 2173 | // if it literally is just '>' or '' then allow anything. 2174 | if (!m[2]) { 2175 | this.semver = ANY 2176 | } else { 2177 | this.semver = new SemVer(m[2], this.options.loose) 2178 | } 2179 | } 2180 | 2181 | Comparator.prototype.toString = function () { 2182 | return this.value 2183 | } 2184 | 2185 | Comparator.prototype.test = function (version) { 2186 | debug('Comparator.test', version, this.options.loose) 2187 | 2188 | if (this.semver === ANY || version === ANY) { 2189 | return true 2190 | } 2191 | 2192 | if (typeof version === 'string') { 2193 | try { 2194 | version = new SemVer(version, this.options) 2195 | } catch (er) { 2196 | return false 2197 | } 2198 | } 2199 | 2200 | return cmp(version, this.operator, this.semver, this.options) 2201 | } 2202 | 2203 | Comparator.prototype.intersects = function (comp, options) { 2204 | if (!(comp instanceof Comparator)) { 2205 | throw new TypeError('a Comparator is required') 2206 | } 2207 | 2208 | if (!options || typeof options !== 'object') { 2209 | options = { 2210 | loose: !!options, 2211 | includePrerelease: false 2212 | } 2213 | } 2214 | 2215 | var rangeTmp 2216 | 2217 | if (this.operator === '') { 2218 | if (this.value === '') { 2219 | return true 2220 | } 2221 | rangeTmp = new Range(comp.value, options) 2222 | return satisfies(this.value, rangeTmp, options) 2223 | } else if (comp.operator === '') { 2224 | if (comp.value === '') { 2225 | return true 2226 | } 2227 | rangeTmp = new Range(this.value, options) 2228 | return satisfies(comp.semver, rangeTmp, options) 2229 | } 2230 | 2231 | var sameDirectionIncreasing = 2232 | (this.operator === '>=' || this.operator === '>') && 2233 | (comp.operator === '>=' || comp.operator === '>') 2234 | var sameDirectionDecreasing = 2235 | (this.operator === '<=' || this.operator === '<') && 2236 | (comp.operator === '<=' || comp.operator === '<') 2237 | var sameSemVer = this.semver.version === comp.semver.version 2238 | var differentDirectionsInclusive = 2239 | (this.operator === '>=' || this.operator === '<=') && 2240 | (comp.operator === '>=' || comp.operator === '<=') 2241 | var oppositeDirectionsLessThan = 2242 | cmp(this.semver, '<', comp.semver, options) && 2243 | ((this.operator === '>=' || this.operator === '>') && 2244 | (comp.operator === '<=' || comp.operator === '<')) 2245 | var oppositeDirectionsGreaterThan = 2246 | cmp(this.semver, '>', comp.semver, options) && 2247 | ((this.operator === '<=' || this.operator === '<') && 2248 | (comp.operator === '>=' || comp.operator === '>')) 2249 | 2250 | return sameDirectionIncreasing || sameDirectionDecreasing || 2251 | (sameSemVer && differentDirectionsInclusive) || 2252 | oppositeDirectionsLessThan || oppositeDirectionsGreaterThan 2253 | } 2254 | 2255 | exports.Range = Range 2256 | function Range (range, options) { 2257 | if (!options || typeof options !== 'object') { 2258 | options = { 2259 | loose: !!options, 2260 | includePrerelease: false 2261 | } 2262 | } 2263 | 2264 | if (range instanceof Range) { 2265 | if (range.loose === !!options.loose && 2266 | range.includePrerelease === !!options.includePrerelease) { 2267 | return range 2268 | } else { 2269 | return new Range(range.raw, options) 2270 | } 2271 | } 2272 | 2273 | if (range instanceof Comparator) { 2274 | return new Range(range.value, options) 2275 | } 2276 | 2277 | if (!(this instanceof Range)) { 2278 | return new Range(range, options) 2279 | } 2280 | 2281 | this.options = options 2282 | this.loose = !!options.loose 2283 | this.includePrerelease = !!options.includePrerelease 2284 | 2285 | // First, split based on boolean or || 2286 | this.raw = range 2287 | this.set = range.split(/\s*\|\|\s*/).map(function (range) { 2288 | return this.parseRange(range.trim()) 2289 | }, this).filter(function (c) { 2290 | // throw out any that are not relevant for whatever reason 2291 | return c.length 2292 | }) 2293 | 2294 | if (!this.set.length) { 2295 | throw new TypeError('Invalid SemVer Range: ' + range) 2296 | } 2297 | 2298 | this.format() 2299 | } 2300 | 2301 | Range.prototype.format = function () { 2302 | this.range = this.set.map(function (comps) { 2303 | return comps.join(' ').trim() 2304 | }).join('||').trim() 2305 | return this.range 2306 | } 2307 | 2308 | Range.prototype.toString = function () { 2309 | return this.range 2310 | } 2311 | 2312 | Range.prototype.parseRange = function (range) { 2313 | var loose = this.options.loose 2314 | range = range.trim() 2315 | // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` 2316 | var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] 2317 | range = range.replace(hr, hyphenReplace) 2318 | debug('hyphen replace', range) 2319 | // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` 2320 | range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) 2321 | debug('comparator trim', range, re[t.COMPARATORTRIM]) 2322 | 2323 | // `~ 1.2.3` => `~1.2.3` 2324 | range = range.replace(re[t.TILDETRIM], tildeTrimReplace) 2325 | 2326 | // `^ 1.2.3` => `^1.2.3` 2327 | range = range.replace(re[t.CARETTRIM], caretTrimReplace) 2328 | 2329 | // normalize spaces 2330 | range = range.split(/\s+/).join(' ') 2331 | 2332 | // At this point, the range is completely trimmed and 2333 | // ready to be split into comparators. 2334 | 2335 | var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] 2336 | var set = range.split(' ').map(function (comp) { 2337 | return parseComparator(comp, this.options) 2338 | }, this).join(' ').split(/\s+/) 2339 | if (this.options.loose) { 2340 | // in loose mode, throw out any that are not valid comparators 2341 | set = set.filter(function (comp) { 2342 | return !!comp.match(compRe) 2343 | }) 2344 | } 2345 | set = set.map(function (comp) { 2346 | return new Comparator(comp, this.options) 2347 | }, this) 2348 | 2349 | return set 2350 | } 2351 | 2352 | Range.prototype.intersects = function (range, options) { 2353 | if (!(range instanceof Range)) { 2354 | throw new TypeError('a Range is required') 2355 | } 2356 | 2357 | return this.set.some(function (thisComparators) { 2358 | return ( 2359 | isSatisfiable(thisComparators, options) && 2360 | range.set.some(function (rangeComparators) { 2361 | return ( 2362 | isSatisfiable(rangeComparators, options) && 2363 | thisComparators.every(function (thisComparator) { 2364 | return rangeComparators.every(function (rangeComparator) { 2365 | return thisComparator.intersects(rangeComparator, options) 2366 | }) 2367 | }) 2368 | ) 2369 | }) 2370 | ) 2371 | }) 2372 | } 2373 | 2374 | // take a set of comparators and determine whether there 2375 | // exists a version which can satisfy it 2376 | function isSatisfiable (comparators, options) { 2377 | var result = true 2378 | var remainingComparators = comparators.slice() 2379 | var testComparator = remainingComparators.pop() 2380 | 2381 | while (result && remainingComparators.length) { 2382 | result = remainingComparators.every(function (otherComparator) { 2383 | return testComparator.intersects(otherComparator, options) 2384 | }) 2385 | 2386 | testComparator = remainingComparators.pop() 2387 | } 2388 | 2389 | return result 2390 | } 2391 | 2392 | // Mostly just for testing and legacy API reasons 2393 | exports.toComparators = toComparators 2394 | function toComparators (range, options) { 2395 | return new Range(range, options).set.map(function (comp) { 2396 | return comp.map(function (c) { 2397 | return c.value 2398 | }).join(' ').trim().split(' ') 2399 | }) 2400 | } 2401 | 2402 | // comprised of xranges, tildes, stars, and gtlt's at this point. 2403 | // already replaced the hyphen ranges 2404 | // turn into a set of JUST comparators. 2405 | function parseComparator (comp, options) { 2406 | debug('comp', comp, options) 2407 | comp = replaceCarets(comp, options) 2408 | debug('caret', comp) 2409 | comp = replaceTildes(comp, options) 2410 | debug('tildes', comp) 2411 | comp = replaceXRanges(comp, options) 2412 | debug('xrange', comp) 2413 | comp = replaceStars(comp, options) 2414 | debug('stars', comp) 2415 | return comp 2416 | } 2417 | 2418 | function isX (id) { 2419 | return !id || id.toLowerCase() === 'x' || id === '*' 2420 | } 2421 | 2422 | // ~, ~> --> * (any, kinda silly) 2423 | // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 2424 | // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 2425 | // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 2426 | // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 2427 | // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 2428 | function replaceTildes (comp, options) { 2429 | return comp.trim().split(/\s+/).map(function (comp) { 2430 | return replaceTilde(comp, options) 2431 | }).join(' ') 2432 | } 2433 | 2434 | function replaceTilde (comp, options) { 2435 | var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] 2436 | return comp.replace(r, function (_, M, m, p, pr) { 2437 | debug('tilde', comp, _, M, m, p, pr) 2438 | var ret 2439 | 2440 | if (isX(M)) { 2441 | ret = '' 2442 | } else if (isX(m)) { 2443 | ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 2444 | } else if (isX(p)) { 2445 | // ~1.2 == >=1.2.0 <1.3.0 2446 | ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 2447 | } else if (pr) { 2448 | debug('replaceTilde pr', pr) 2449 | ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 2450 | ' <' + M + '.' + (+m + 1) + '.0' 2451 | } else { 2452 | // ~1.2.3 == >=1.2.3 <1.3.0 2453 | ret = '>=' + M + '.' + m + '.' + p + 2454 | ' <' + M + '.' + (+m + 1) + '.0' 2455 | } 2456 | 2457 | debug('tilde return', ret) 2458 | return ret 2459 | }) 2460 | } 2461 | 2462 | // ^ --> * (any, kinda silly) 2463 | // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 2464 | // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 2465 | // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 2466 | // ^1.2.3 --> >=1.2.3 <2.0.0 2467 | // ^1.2.0 --> >=1.2.0 <2.0.0 2468 | function replaceCarets (comp, options) { 2469 | return comp.trim().split(/\s+/).map(function (comp) { 2470 | return replaceCaret(comp, options) 2471 | }).join(' ') 2472 | } 2473 | 2474 | function replaceCaret (comp, options) { 2475 | debug('caret', comp, options) 2476 | var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] 2477 | return comp.replace(r, function (_, M, m, p, pr) { 2478 | debug('caret', comp, _, M, m, p, pr) 2479 | var ret 2480 | 2481 | if (isX(M)) { 2482 | ret = '' 2483 | } else if (isX(m)) { 2484 | ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 2485 | } else if (isX(p)) { 2486 | if (M === '0') { 2487 | ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 2488 | } else { 2489 | ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' 2490 | } 2491 | } else if (pr) { 2492 | debug('replaceCaret pr', pr) 2493 | if (M === '0') { 2494 | if (m === '0') { 2495 | ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 2496 | ' <' + M + '.' + m + '.' + (+p + 1) 2497 | } else { 2498 | ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 2499 | ' <' + M + '.' + (+m + 1) + '.0' 2500 | } 2501 | } else { 2502 | ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 2503 | ' <' + (+M + 1) + '.0.0' 2504 | } 2505 | } else { 2506 | debug('no pr') 2507 | if (M === '0') { 2508 | if (m === '0') { 2509 | ret = '>=' + M + '.' + m + '.' + p + 2510 | ' <' + M + '.' + m + '.' + (+p + 1) 2511 | } else { 2512 | ret = '>=' + M + '.' + m + '.' + p + 2513 | ' <' + M + '.' + (+m + 1) + '.0' 2514 | } 2515 | } else { 2516 | ret = '>=' + M + '.' + m + '.' + p + 2517 | ' <' + (+M + 1) + '.0.0' 2518 | } 2519 | } 2520 | 2521 | debug('caret return', ret) 2522 | return ret 2523 | }) 2524 | } 2525 | 2526 | function replaceXRanges (comp, options) { 2527 | debug('replaceXRanges', comp, options) 2528 | return comp.split(/\s+/).map(function (comp) { 2529 | return replaceXRange(comp, options) 2530 | }).join(' ') 2531 | } 2532 | 2533 | function replaceXRange (comp, options) { 2534 | comp = comp.trim() 2535 | var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] 2536 | return comp.replace(r, function (ret, gtlt, M, m, p, pr) { 2537 | debug('xRange', comp, ret, gtlt, M, m, p, pr) 2538 | var xM = isX(M) 2539 | var xm = xM || isX(m) 2540 | var xp = xm || isX(p) 2541 | var anyX = xp 2542 | 2543 | if (gtlt === '=' && anyX) { 2544 | gtlt = '' 2545 | } 2546 | 2547 | // if we're including prereleases in the match, then we need 2548 | // to fix this to -0, the lowest possible prerelease value 2549 | pr = options.includePrerelease ? '-0' : '' 2550 | 2551 | if (xM) { 2552 | if (gtlt === '>' || gtlt === '<') { 2553 | // nothing is allowed 2554 | ret = '<0.0.0-0' 2555 | } else { 2556 | // nothing is forbidden 2557 | ret = '*' 2558 | } 2559 | } else if (gtlt && anyX) { 2560 | // we know patch is an x, because we have any x at all. 2561 | // replace X with 0 2562 | if (xm) { 2563 | m = 0 2564 | } 2565 | p = 0 2566 | 2567 | if (gtlt === '>') { 2568 | // >1 => >=2.0.0 2569 | // >1.2 => >=1.3.0 2570 | // >1.2.3 => >= 1.2.4 2571 | gtlt = '>=' 2572 | if (xm) { 2573 | M = +M + 1 2574 | m = 0 2575 | p = 0 2576 | } else { 2577 | m = +m + 1 2578 | p = 0 2579 | } 2580 | } else if (gtlt === '<=') { 2581 | // <=0.7.x is actually <0.8.0, since any 0.7.x should 2582 | // pass. Similarly, <=7.x is actually <8.0.0, etc. 2583 | gtlt = '<' 2584 | if (xm) { 2585 | M = +M + 1 2586 | } else { 2587 | m = +m + 1 2588 | } 2589 | } 2590 | 2591 | ret = gtlt + M + '.' + m + '.' + p + pr 2592 | } else if (xm) { 2593 | ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr 2594 | } else if (xp) { 2595 | ret = '>=' + M + '.' + m + '.0' + pr + 2596 | ' <' + M + '.' + (+m + 1) + '.0' + pr 2597 | } 2598 | 2599 | debug('xRange return', ret) 2600 | 2601 | return ret 2602 | }) 2603 | } 2604 | 2605 | // Because * is AND-ed with everything else in the comparator, 2606 | // and '' means "any version", just remove the *s entirely. 2607 | function replaceStars (comp, options) { 2608 | debug('replaceStars', comp, options) 2609 | // Looseness is ignored here. star is always as loose as it gets! 2610 | return comp.trim().replace(re[t.STAR], '') 2611 | } 2612 | 2613 | // This function is passed to string.replace(re[t.HYPHENRANGE]) 2614 | // M, m, patch, prerelease, build 2615 | // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 2616 | // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do 2617 | // 1.2 - 3.4 => >=1.2.0 <3.5.0 2618 | function hyphenReplace ($0, 2619 | from, fM, fm, fp, fpr, fb, 2620 | to, tM, tm, tp, tpr, tb) { 2621 | if (isX(fM)) { 2622 | from = '' 2623 | } else if (isX(fm)) { 2624 | from = '>=' + fM + '.0.0' 2625 | } else if (isX(fp)) { 2626 | from = '>=' + fM + '.' + fm + '.0' 2627 | } else { 2628 | from = '>=' + from 2629 | } 2630 | 2631 | if (isX(tM)) { 2632 | to = '' 2633 | } else if (isX(tm)) { 2634 | to = '<' + (+tM + 1) + '.0.0' 2635 | } else if (isX(tp)) { 2636 | to = '<' + tM + '.' + (+tm + 1) + '.0' 2637 | } else if (tpr) { 2638 | to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr 2639 | } else { 2640 | to = '<=' + to 2641 | } 2642 | 2643 | return (from + ' ' + to).trim() 2644 | } 2645 | 2646 | // if ANY of the sets match ALL of its comparators, then pass 2647 | Range.prototype.test = function (version) { 2648 | if (!version) { 2649 | return false 2650 | } 2651 | 2652 | if (typeof version === 'string') { 2653 | try { 2654 | version = new SemVer(version, this.options) 2655 | } catch (er) { 2656 | return false 2657 | } 2658 | } 2659 | 2660 | for (var i = 0; i < this.set.length; i++) { 2661 | if (testSet(this.set[i], version, this.options)) { 2662 | return true 2663 | } 2664 | } 2665 | return false 2666 | } 2667 | 2668 | function testSet (set, version, options) { 2669 | for (var i = 0; i < set.length; i++) { 2670 | if (!set[i].test(version)) { 2671 | return false 2672 | } 2673 | } 2674 | 2675 | if (version.prerelease.length && !options.includePrerelease) { 2676 | // Find the set of versions that are allowed to have prereleases 2677 | // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 2678 | // That should allow `1.2.3-pr.2` to pass. 2679 | // However, `1.2.4-alpha.notready` should NOT be allowed, 2680 | // even though it's within the range set by the comparators. 2681 | for (i = 0; i < set.length; i++) { 2682 | debug(set[i].semver) 2683 | if (set[i].semver === ANY) { 2684 | continue 2685 | } 2686 | 2687 | if (set[i].semver.prerelease.length > 0) { 2688 | var allowed = set[i].semver 2689 | if (allowed.major === version.major && 2690 | allowed.minor === version.minor && 2691 | allowed.patch === version.patch) { 2692 | return true 2693 | } 2694 | } 2695 | } 2696 | 2697 | // Version has a -pre, but it's not one of the ones we like. 2698 | return false 2699 | } 2700 | 2701 | return true 2702 | } 2703 | 2704 | exports.satisfies = satisfies 2705 | function satisfies (version, range, options) { 2706 | try { 2707 | range = new Range(range, options) 2708 | } catch (er) { 2709 | return false 2710 | } 2711 | return range.test(version) 2712 | } 2713 | 2714 | exports.maxSatisfying = maxSatisfying 2715 | function maxSatisfying (versions, range, options) { 2716 | var max = null 2717 | var maxSV = null 2718 | try { 2719 | var rangeObj = new Range(range, options) 2720 | } catch (er) { 2721 | return null 2722 | } 2723 | versions.forEach(function (v) { 2724 | if (rangeObj.test(v)) { 2725 | // satisfies(v, range, options) 2726 | if (!max || maxSV.compare(v) === -1) { 2727 | // compare(max, v, true) 2728 | max = v 2729 | maxSV = new SemVer(max, options) 2730 | } 2731 | } 2732 | }) 2733 | return max 2734 | } 2735 | 2736 | exports.minSatisfying = minSatisfying 2737 | function minSatisfying (versions, range, options) { 2738 | var min = null 2739 | var minSV = null 2740 | try { 2741 | var rangeObj = new Range(range, options) 2742 | } catch (er) { 2743 | return null 2744 | } 2745 | versions.forEach(function (v) { 2746 | if (rangeObj.test(v)) { 2747 | // satisfies(v, range, options) 2748 | if (!min || minSV.compare(v) === 1) { 2749 | // compare(min, v, true) 2750 | min = v 2751 | minSV = new SemVer(min, options) 2752 | } 2753 | } 2754 | }) 2755 | return min 2756 | } 2757 | 2758 | exports.minVersion = minVersion 2759 | function minVersion (range, loose) { 2760 | range = new Range(range, loose) 2761 | 2762 | var minver = new SemVer('0.0.0') 2763 | if (range.test(minver)) { 2764 | return minver 2765 | } 2766 | 2767 | minver = new SemVer('0.0.0-0') 2768 | if (range.test(minver)) { 2769 | return minver 2770 | } 2771 | 2772 | minver = null 2773 | for (var i = 0; i < range.set.length; ++i) { 2774 | var comparators = range.set[i] 2775 | 2776 | comparators.forEach(function (comparator) { 2777 | // Clone to avoid manipulating the comparator's semver object. 2778 | var compver = new SemVer(comparator.semver.version) 2779 | switch (comparator.operator) { 2780 | case '>': 2781 | if (compver.prerelease.length === 0) { 2782 | compver.patch++ 2783 | } else { 2784 | compver.prerelease.push(0) 2785 | } 2786 | compver.raw = compver.format() 2787 | /* fallthrough */ 2788 | case '': 2789 | case '>=': 2790 | if (!minver || gt(minver, compver)) { 2791 | minver = compver 2792 | } 2793 | break 2794 | case '<': 2795 | case '<=': 2796 | /* Ignore maximum versions */ 2797 | break 2798 | /* istanbul ignore next */ 2799 | default: 2800 | throw new Error('Unexpected operation: ' + comparator.operator) 2801 | } 2802 | }) 2803 | } 2804 | 2805 | if (minver && range.test(minver)) { 2806 | return minver 2807 | } 2808 | 2809 | return null 2810 | } 2811 | 2812 | exports.validRange = validRange 2813 | function validRange (range, options) { 2814 | try { 2815 | // Return '*' instead of '' so that truthiness works. 2816 | // This will throw if it's invalid anyway 2817 | return new Range(range, options).range || '*' 2818 | } catch (er) { 2819 | return null 2820 | } 2821 | } 2822 | 2823 | // Determine if version is less than all the versions possible in the range 2824 | exports.ltr = ltr 2825 | function ltr (version, range, options) { 2826 | return outside(version, range, '<', options) 2827 | } 2828 | 2829 | // Determine if version is greater than all the versions possible in the range. 2830 | exports.gtr = gtr 2831 | function gtr (version, range, options) { 2832 | return outside(version, range, '>', options) 2833 | } 2834 | 2835 | exports.outside = outside 2836 | function outside (version, range, hilo, options) { 2837 | version = new SemVer(version, options) 2838 | range = new Range(range, options) 2839 | 2840 | var gtfn, ltefn, ltfn, comp, ecomp 2841 | switch (hilo) { 2842 | case '>': 2843 | gtfn = gt 2844 | ltefn = lte 2845 | ltfn = lt 2846 | comp = '>' 2847 | ecomp = '>=' 2848 | break 2849 | case '<': 2850 | gtfn = lt 2851 | ltefn = gte 2852 | ltfn = gt 2853 | comp = '<' 2854 | ecomp = '<=' 2855 | break 2856 | default: 2857 | throw new TypeError('Must provide a hilo val of "<" or ">"') 2858 | } 2859 | 2860 | // If it satisifes the range it is not outside 2861 | if (satisfies(version, range, options)) { 2862 | return false 2863 | } 2864 | 2865 | // From now on, variable terms are as if we're in "gtr" mode. 2866 | // but note that everything is flipped for the "ltr" function. 2867 | 2868 | for (var i = 0; i < range.set.length; ++i) { 2869 | var comparators = range.set[i] 2870 | 2871 | var high = null 2872 | var low = null 2873 | 2874 | comparators.forEach(function (comparator) { 2875 | if (comparator.semver === ANY) { 2876 | comparator = new Comparator('>=0.0.0') 2877 | } 2878 | high = high || comparator 2879 | low = low || comparator 2880 | if (gtfn(comparator.semver, high.semver, options)) { 2881 | high = comparator 2882 | } else if (ltfn(comparator.semver, low.semver, options)) { 2883 | low = comparator 2884 | } 2885 | }) 2886 | 2887 | // If the edge version comparator has a operator then our version 2888 | // isn't outside it 2889 | if (high.operator === comp || high.operator === ecomp) { 2890 | return false 2891 | } 2892 | 2893 | // If the lowest version comparator has an operator and our version 2894 | // is less than it then it isn't higher than the range 2895 | if ((!low.operator || low.operator === comp) && 2896 | ltefn(version, low.semver)) { 2897 | return false 2898 | } else if (low.operator === ecomp && ltfn(version, low.semver)) { 2899 | return false 2900 | } 2901 | } 2902 | return true 2903 | } 2904 | 2905 | exports.prerelease = prerelease 2906 | function prerelease (version, options) { 2907 | var parsed = parse(version, options) 2908 | return (parsed && parsed.prerelease.length) ? parsed.prerelease : null 2909 | } 2910 | 2911 | exports.intersects = intersects 2912 | function intersects (r1, r2, options) { 2913 | r1 = new Range(r1, options) 2914 | r2 = new Range(r2, options) 2915 | return r1.intersects(r2) 2916 | } 2917 | 2918 | exports.coerce = coerce 2919 | function coerce (version, options) { 2920 | if (version instanceof SemVer) { 2921 | return version 2922 | } 2923 | 2924 | if (typeof version === 'number') { 2925 | version = String(version) 2926 | } 2927 | 2928 | if (typeof version !== 'string') { 2929 | return null 2930 | } 2931 | 2932 | options = options || {} 2933 | 2934 | var match = null 2935 | if (!options.rtl) { 2936 | match = version.match(re[t.COERCE]) 2937 | } else { 2938 | // Find the right-most coercible string that does not share 2939 | // a terminus with a more left-ward coercible string. 2940 | // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' 2941 | // 2942 | // Walk through the string checking with a /g regexp 2943 | // Manually set the index so as to pick up overlapping matches. 2944 | // Stop when we get a match that ends at the string end, since no 2945 | // coercible string can be more right-ward without the same terminus. 2946 | var next 2947 | while ((next = re[t.COERCERTL].exec(version)) && 2948 | (!match || match.index + match[0].length !== version.length) 2949 | ) { 2950 | if (!match || 2951 | next.index + next[0].length !== match.index + match[0].length) { 2952 | match = next 2953 | } 2954 | re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length 2955 | } 2956 | // leave it in a clean state 2957 | re[t.COERCERTL].lastIndex = -1 2958 | } 2959 | 2960 | if (match === null) { 2961 | return null 2962 | } 2963 | 2964 | return parse(match[2] + 2965 | '.' + (match[3] || '0') + 2966 | '.' + (match[4] || '0'), options) 2967 | } 2968 | 2969 | 2970 | /***/ }), 2971 | 2972 | /***/ 357: 2973 | /***/ (function(module) { 2974 | 2975 | module.exports = require("assert"); 2976 | 2977 | /***/ }), 2978 | 2979 | /***/ 365: 2980 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 2981 | 2982 | "use strict"; 2983 | 2984 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 2985 | return new (P || (P = Promise))(function (resolve, reject) { 2986 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 2987 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 2988 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 2989 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 2990 | }); 2991 | }; 2992 | var __importStar = (this && this.__importStar) || function (mod) { 2993 | if (mod && mod.__esModule) return mod; 2994 | var result = {}; 2995 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 2996 | result["default"] = mod; 2997 | return result; 2998 | }; 2999 | Object.defineProperty(exports, "__esModule", { value: true }); 3000 | const tc = __importStar(__webpack_require__(533)); 3001 | const path = __importStar(__webpack_require__(622)); 3002 | function find(version) { 3003 | return __awaiter(this, void 0, void 0, function* () { 3004 | const installDir = tc.find('Ruby', version); 3005 | let toolPath = installDir ? path.join(installDir, 'bin') : ''; 3006 | return toolPath; 3007 | }); 3008 | } 3009 | exports.find = find; 3010 | 3011 | 3012 | /***/ }), 3013 | 3014 | /***/ 367: 3015 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 3016 | 3017 | "use strict"; 3018 | 3019 | Object.defineProperty(exports, "__esModule", { value: true }); 3020 | const main_1 = __webpack_require__(198); 3021 | main_1.run(); 3022 | 3023 | 3024 | /***/ }), 3025 | 3026 | /***/ 413: 3027 | /***/ (function(module, __unusedexports, __webpack_require__) { 3028 | 3029 | module.exports = __webpack_require__(141); 3030 | 3031 | 3032 | /***/ }), 3033 | 3034 | /***/ 417: 3035 | /***/ (function(module) { 3036 | 3037 | module.exports = require("crypto"); 3038 | 3039 | /***/ }), 3040 | 3041 | /***/ 431: 3042 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 3043 | 3044 | "use strict"; 3045 | 3046 | var __importStar = (this && this.__importStar) || function (mod) { 3047 | if (mod && mod.__esModule) return mod; 3048 | var result = {}; 3049 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 3050 | result["default"] = mod; 3051 | return result; 3052 | }; 3053 | Object.defineProperty(exports, "__esModule", { value: true }); 3054 | const os = __importStar(__webpack_require__(87)); 3055 | const utils_1 = __webpack_require__(82); 3056 | /** 3057 | * Commands 3058 | * 3059 | * Command Format: 3060 | * ::name key=value,key=value::message 3061 | * 3062 | * Examples: 3063 | * ::warning::This is the message 3064 | * ::set-env name=MY_VAR::some value 3065 | */ 3066 | function issueCommand(command, properties, message) { 3067 | const cmd = new Command(command, properties, message); 3068 | process.stdout.write(cmd.toString() + os.EOL); 3069 | } 3070 | exports.issueCommand = issueCommand; 3071 | function issue(name, message = '') { 3072 | issueCommand(name, {}, message); 3073 | } 3074 | exports.issue = issue; 3075 | const CMD_STRING = '::'; 3076 | class Command { 3077 | constructor(command, properties, message) { 3078 | if (!command) { 3079 | command = 'missing.command'; 3080 | } 3081 | this.command = command; 3082 | this.properties = properties; 3083 | this.message = message; 3084 | } 3085 | toString() { 3086 | let cmdStr = CMD_STRING + this.command; 3087 | if (this.properties && Object.keys(this.properties).length > 0) { 3088 | cmdStr += ' '; 3089 | let first = true; 3090 | for (const key in this.properties) { 3091 | if (this.properties.hasOwnProperty(key)) { 3092 | const val = this.properties[key]; 3093 | if (val) { 3094 | if (first) { 3095 | first = false; 3096 | } 3097 | else { 3098 | cmdStr += ','; 3099 | } 3100 | cmdStr += `${key}=${escapeProperty(val)}`; 3101 | } 3102 | } 3103 | } 3104 | } 3105 | cmdStr += `${CMD_STRING}${escapeData(this.message)}`; 3106 | return cmdStr; 3107 | } 3108 | } 3109 | function escapeData(s) { 3110 | return utils_1.toCommandValue(s) 3111 | .replace(/%/g, '%25') 3112 | .replace(/\r/g, '%0D') 3113 | .replace(/\n/g, '%0A'); 3114 | } 3115 | function escapeProperty(s) { 3116 | return utils_1.toCommandValue(s) 3117 | .replace(/%/g, '%25') 3118 | .replace(/\r/g, '%0D') 3119 | .replace(/\n/g, '%0A') 3120 | .replace(/:/g, '%3A') 3121 | .replace(/,/g, '%2C'); 3122 | } 3123 | //# sourceMappingURL=command.js.map 3124 | 3125 | /***/ }), 3126 | 3127 | /***/ 470: 3128 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 3129 | 3130 | "use strict"; 3131 | 3132 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3133 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 3134 | return new (P || (P = Promise))(function (resolve, reject) { 3135 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 3136 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 3137 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 3138 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 3139 | }); 3140 | }; 3141 | var __importStar = (this && this.__importStar) || function (mod) { 3142 | if (mod && mod.__esModule) return mod; 3143 | var result = {}; 3144 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 3145 | result["default"] = mod; 3146 | return result; 3147 | }; 3148 | Object.defineProperty(exports, "__esModule", { value: true }); 3149 | const command_1 = __webpack_require__(431); 3150 | const file_command_1 = __webpack_require__(102); 3151 | const utils_1 = __webpack_require__(82); 3152 | const os = __importStar(__webpack_require__(87)); 3153 | const path = __importStar(__webpack_require__(622)); 3154 | /** 3155 | * The code to exit an action 3156 | */ 3157 | var ExitCode; 3158 | (function (ExitCode) { 3159 | /** 3160 | * A code indicating that the action was successful 3161 | */ 3162 | ExitCode[ExitCode["Success"] = 0] = "Success"; 3163 | /** 3164 | * A code indicating that the action was a failure 3165 | */ 3166 | ExitCode[ExitCode["Failure"] = 1] = "Failure"; 3167 | })(ExitCode = exports.ExitCode || (exports.ExitCode = {})); 3168 | //----------------------------------------------------------------------- 3169 | // Variables 3170 | //----------------------------------------------------------------------- 3171 | /** 3172 | * Sets env variable for this action and future actions in the job 3173 | * @param name the name of the variable to set 3174 | * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify 3175 | */ 3176 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3177 | function exportVariable(name, val) { 3178 | const convertedVal = utils_1.toCommandValue(val); 3179 | process.env[name] = convertedVal; 3180 | const filePath = process.env['GITHUB_ENV'] || ''; 3181 | if (filePath) { 3182 | const delimiter = '_GitHubActionsFileCommandDelimeter_'; 3183 | const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; 3184 | file_command_1.issueCommand('ENV', commandValue); 3185 | } 3186 | else { 3187 | command_1.issueCommand('set-env', { name }, convertedVal); 3188 | } 3189 | } 3190 | exports.exportVariable = exportVariable; 3191 | /** 3192 | * Registers a secret which will get masked from logs 3193 | * @param secret value of the secret 3194 | */ 3195 | function setSecret(secret) { 3196 | command_1.issueCommand('add-mask', {}, secret); 3197 | } 3198 | exports.setSecret = setSecret; 3199 | /** 3200 | * Prepends inputPath to the PATH (for this action and future actions) 3201 | * @param inputPath 3202 | */ 3203 | function addPath(inputPath) { 3204 | const filePath = process.env['GITHUB_PATH'] || ''; 3205 | if (filePath) { 3206 | file_command_1.issueCommand('PATH', inputPath); 3207 | } 3208 | else { 3209 | command_1.issueCommand('add-path', {}, inputPath); 3210 | } 3211 | process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; 3212 | } 3213 | exports.addPath = addPath; 3214 | /** 3215 | * Gets the value of an input. The value is also trimmed. 3216 | * 3217 | * @param name name of the input to get 3218 | * @param options optional. See InputOptions. 3219 | * @returns string 3220 | */ 3221 | function getInput(name, options) { 3222 | const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; 3223 | if (options && options.required && !val) { 3224 | throw new Error(`Input required and not supplied: ${name}`); 3225 | } 3226 | return val.trim(); 3227 | } 3228 | exports.getInput = getInput; 3229 | /** 3230 | * Sets the value of an output. 3231 | * 3232 | * @param name name of the output to set 3233 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify 3234 | */ 3235 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3236 | function setOutput(name, value) { 3237 | command_1.issueCommand('set-output', { name }, value); 3238 | } 3239 | exports.setOutput = setOutput; 3240 | /** 3241 | * Enables or disables the echoing of commands into stdout for the rest of the step. 3242 | * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. 3243 | * 3244 | */ 3245 | function setCommandEcho(enabled) { 3246 | command_1.issue('echo', enabled ? 'on' : 'off'); 3247 | } 3248 | exports.setCommandEcho = setCommandEcho; 3249 | //----------------------------------------------------------------------- 3250 | // Results 3251 | //----------------------------------------------------------------------- 3252 | /** 3253 | * Sets the action status to failed. 3254 | * When the action exits it will be with an exit code of 1 3255 | * @param message add error issue message 3256 | */ 3257 | function setFailed(message) { 3258 | process.exitCode = ExitCode.Failure; 3259 | error(message); 3260 | } 3261 | exports.setFailed = setFailed; 3262 | //----------------------------------------------------------------------- 3263 | // Logging Commands 3264 | //----------------------------------------------------------------------- 3265 | /** 3266 | * Gets whether Actions Step Debug is on or not 3267 | */ 3268 | function isDebug() { 3269 | return process.env['RUNNER_DEBUG'] === '1'; 3270 | } 3271 | exports.isDebug = isDebug; 3272 | /** 3273 | * Writes debug message to user log 3274 | * @param message debug message 3275 | */ 3276 | function debug(message) { 3277 | command_1.issueCommand('debug', {}, message); 3278 | } 3279 | exports.debug = debug; 3280 | /** 3281 | * Adds an error issue 3282 | * @param message error issue message. Errors will be converted to string via toString() 3283 | */ 3284 | function error(message) { 3285 | command_1.issue('error', message instanceof Error ? message.toString() : message); 3286 | } 3287 | exports.error = error; 3288 | /** 3289 | * Adds an warning issue 3290 | * @param message warning issue message. Errors will be converted to string via toString() 3291 | */ 3292 | function warning(message) { 3293 | command_1.issue('warning', message instanceof Error ? message.toString() : message); 3294 | } 3295 | exports.warning = warning; 3296 | /** 3297 | * Writes info to log with console.log. 3298 | * @param message info message 3299 | */ 3300 | function info(message) { 3301 | process.stdout.write(message + os.EOL); 3302 | } 3303 | exports.info = info; 3304 | /** 3305 | * Begin an output group. 3306 | * 3307 | * Output until the next `groupEnd` will be foldable in this group 3308 | * 3309 | * @param name The name of the output group 3310 | */ 3311 | function startGroup(name) { 3312 | command_1.issue('group', name); 3313 | } 3314 | exports.startGroup = startGroup; 3315 | /** 3316 | * End an output group. 3317 | */ 3318 | function endGroup() { 3319 | command_1.issue('endgroup'); 3320 | } 3321 | exports.endGroup = endGroup; 3322 | /** 3323 | * Wrap an asynchronous function call in a group. 3324 | * 3325 | * Returns the same type as the function itself. 3326 | * 3327 | * @param name The name of the group 3328 | * @param fn The function to wrap in the group 3329 | */ 3330 | function group(name, fn) { 3331 | return __awaiter(this, void 0, void 0, function* () { 3332 | startGroup(name); 3333 | let result; 3334 | try { 3335 | result = yield fn(); 3336 | } 3337 | finally { 3338 | endGroup(); 3339 | } 3340 | return result; 3341 | }); 3342 | } 3343 | exports.group = group; 3344 | //----------------------------------------------------------------------- 3345 | // Wrapper action state 3346 | //----------------------------------------------------------------------- 3347 | /** 3348 | * Saves state for current action, the state can only be retrieved by this action's post job execution. 3349 | * 3350 | * @param name name of the state to store 3351 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify 3352 | */ 3353 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3354 | function saveState(name, value) { 3355 | command_1.issueCommand('save-state', { name }, value); 3356 | } 3357 | exports.saveState = saveState; 3358 | /** 3359 | * Gets the value of an state set by this action's main execution. 3360 | * 3361 | * @param name name of the state to get 3362 | * @returns string 3363 | */ 3364 | function getState(name) { 3365 | return process.env[`STATE_${name}`] || ''; 3366 | } 3367 | exports.getState = getState; 3368 | //# sourceMappingURL=core.js.map 3369 | 3370 | /***/ }), 3371 | 3372 | /***/ 533: 3373 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 3374 | 3375 | "use strict"; 3376 | 3377 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3378 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 3379 | return new (P || (P = Promise))(function (resolve, reject) { 3380 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 3381 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 3382 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 3383 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 3384 | }); 3385 | }; 3386 | var __importStar = (this && this.__importStar) || function (mod) { 3387 | if (mod && mod.__esModule) return mod; 3388 | var result = {}; 3389 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 3390 | result["default"] = mod; 3391 | return result; 3392 | }; 3393 | var __importDefault = (this && this.__importDefault) || function (mod) { 3394 | return (mod && mod.__esModule) ? mod : { "default": mod }; 3395 | }; 3396 | Object.defineProperty(exports, "__esModule", { value: true }); 3397 | const core = __importStar(__webpack_require__(470)); 3398 | const io = __importStar(__webpack_require__(1)); 3399 | const fs = __importStar(__webpack_require__(747)); 3400 | const os = __importStar(__webpack_require__(87)); 3401 | const path = __importStar(__webpack_require__(622)); 3402 | const httpm = __importStar(__webpack_require__(539)); 3403 | const semver = __importStar(__webpack_require__(280)); 3404 | const v4_1 = __importDefault(__webpack_require__(826)); 3405 | const exec_1 = __webpack_require__(986); 3406 | const assert_1 = __webpack_require__(357); 3407 | class HTTPError extends Error { 3408 | constructor(httpStatusCode) { 3409 | super(`Unexpected HTTP response: ${httpStatusCode}`); 3410 | this.httpStatusCode = httpStatusCode; 3411 | Object.setPrototypeOf(this, new.target.prototype); 3412 | } 3413 | } 3414 | exports.HTTPError = HTTPError; 3415 | const IS_WINDOWS = process.platform === 'win32'; 3416 | const userAgent = 'actions/tool-cache'; 3417 | // On load grab temp directory and cache directory and remove them from env (currently don't want to expose this) 3418 | let tempDirectory = process.env['RUNNER_TEMP'] || ''; 3419 | let cacheRoot = process.env['RUNNER_TOOL_CACHE'] || ''; 3420 | // If directories not found, place them in common temp locations 3421 | if (!tempDirectory || !cacheRoot) { 3422 | let baseLocation; 3423 | if (IS_WINDOWS) { 3424 | // On windows use the USERPROFILE env variable 3425 | baseLocation = process.env['USERPROFILE'] || 'C:\\'; 3426 | } 3427 | else { 3428 | if (process.platform === 'darwin') { 3429 | baseLocation = '/Users'; 3430 | } 3431 | else { 3432 | baseLocation = '/home'; 3433 | } 3434 | } 3435 | if (!tempDirectory) { 3436 | tempDirectory = path.join(baseLocation, 'actions', 'temp'); 3437 | } 3438 | if (!cacheRoot) { 3439 | cacheRoot = path.join(baseLocation, 'actions', 'cache'); 3440 | } 3441 | } 3442 | /** 3443 | * Download a tool from an url and stream it into a file 3444 | * 3445 | * @param url url of tool to download 3446 | * @param dest path to download tool 3447 | * @returns path to downloaded tool 3448 | */ 3449 | function downloadTool(url, dest) { 3450 | return __awaiter(this, void 0, void 0, function* () { 3451 | // Wrap in a promise so that we can resolve from within stream callbacks 3452 | return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { 3453 | try { 3454 | const http = new httpm.HttpClient(userAgent, [], { 3455 | allowRetries: true, 3456 | maxRetries: 3 3457 | }); 3458 | dest = dest || path.join(tempDirectory, v4_1.default()); 3459 | yield io.mkdirP(path.dirname(dest)); 3460 | core.debug(`Downloading ${url}`); 3461 | core.debug(`Downloading ${dest}`); 3462 | if (fs.existsSync(dest)) { 3463 | throw new Error(`Destination file path ${dest} already exists`); 3464 | } 3465 | const response = yield http.get(url); 3466 | if (response.message.statusCode !== 200) { 3467 | const err = new HTTPError(response.message.statusCode); 3468 | core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); 3469 | throw err; 3470 | } 3471 | const file = fs.createWriteStream(dest); 3472 | file.on('open', () => __awaiter(this, void 0, void 0, function* () { 3473 | try { 3474 | const stream = response.message.pipe(file); 3475 | stream.on('close', () => { 3476 | core.debug('download complete'); 3477 | resolve(dest); 3478 | }); 3479 | } 3480 | catch (err) { 3481 | core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); 3482 | reject(err); 3483 | } 3484 | })); 3485 | file.on('error', err => { 3486 | file.end(); 3487 | reject(err); 3488 | }); 3489 | } 3490 | catch (err) { 3491 | reject(err); 3492 | } 3493 | })); 3494 | }); 3495 | } 3496 | exports.downloadTool = downloadTool; 3497 | /** 3498 | * Extract a .7z file 3499 | * 3500 | * @param file path to the .7z file 3501 | * @param dest destination directory. Optional. 3502 | * @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this 3503 | * problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will 3504 | * gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is 3505 | * bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line 3506 | * interface, it is smaller than the full command line interface, and it does support long paths. At the 3507 | * time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website. 3508 | * Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path 3509 | * to 7zr.exe can be pass to this function. 3510 | * @returns path to the destination directory 3511 | */ 3512 | function extract7z(file, dest, _7zPath) { 3513 | return __awaiter(this, void 0, void 0, function* () { 3514 | assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS'); 3515 | assert_1.ok(file, 'parameter "file" is required'); 3516 | dest = yield _createExtractFolder(dest); 3517 | const originalCwd = process.cwd(); 3518 | process.chdir(dest); 3519 | if (_7zPath) { 3520 | try { 3521 | const args = [ 3522 | 'x', 3523 | '-bb1', 3524 | '-bd', 3525 | '-sccUTF-8', 3526 | file 3527 | ]; 3528 | const options = { 3529 | silent: true 3530 | }; 3531 | yield exec_1.exec(`"${_7zPath}"`, args, options); 3532 | } 3533 | finally { 3534 | process.chdir(originalCwd); 3535 | } 3536 | } 3537 | else { 3538 | const escapedScript = path 3539 | .join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1') 3540 | .replace(/'/g, "''") 3541 | .replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines 3542 | const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); 3543 | const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); 3544 | const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`; 3545 | const args = [ 3546 | '-NoLogo', 3547 | '-Sta', 3548 | '-NoProfile', 3549 | '-NonInteractive', 3550 | '-ExecutionPolicy', 3551 | 'Unrestricted', 3552 | '-Command', 3553 | command 3554 | ]; 3555 | const options = { 3556 | silent: true 3557 | }; 3558 | try { 3559 | const powershellPath = yield io.which('powershell', true); 3560 | yield exec_1.exec(`"${powershellPath}"`, args, options); 3561 | } 3562 | finally { 3563 | process.chdir(originalCwd); 3564 | } 3565 | } 3566 | return dest; 3567 | }); 3568 | } 3569 | exports.extract7z = extract7z; 3570 | /** 3571 | * Extract a compressed tar archive 3572 | * 3573 | * @param file path to the tar 3574 | * @param dest destination directory. Optional. 3575 | * @param flags flags for the tar command to use for extraction. Defaults to 'xz' (extracting gzipped tars). Optional. 3576 | * @returns path to the destination directory 3577 | */ 3578 | function extractTar(file, dest, flags = 'xz') { 3579 | return __awaiter(this, void 0, void 0, function* () { 3580 | if (!file) { 3581 | throw new Error("parameter 'file' is required"); 3582 | } 3583 | // Create dest 3584 | dest = yield _createExtractFolder(dest); 3585 | // Determine whether GNU tar 3586 | let versionOutput = ''; 3587 | yield exec_1.exec('tar --version', [], { 3588 | ignoreReturnCode: true, 3589 | listeners: { 3590 | stdout: (data) => (versionOutput += data.toString()), 3591 | stderr: (data) => (versionOutput += data.toString()) 3592 | } 3593 | }); 3594 | const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR'); 3595 | // Initialize args 3596 | const args = [flags]; 3597 | let destArg = dest; 3598 | let fileArg = file; 3599 | if (IS_WINDOWS && isGnuTar) { 3600 | args.push('--force-local'); 3601 | destArg = dest.replace(/\\/g, '/'); 3602 | // Technically only the dest needs to have `/` but for aesthetic consistency 3603 | // convert slashes in the file arg too. 3604 | fileArg = file.replace(/\\/g, '/'); 3605 | } 3606 | if (isGnuTar) { 3607 | // Suppress warnings when using GNU tar to extract archives created by BSD tar 3608 | args.push('--warning=no-unknown-keyword'); 3609 | } 3610 | args.push('-C', destArg, '-f', fileArg); 3611 | yield exec_1.exec(`tar`, args); 3612 | return dest; 3613 | }); 3614 | } 3615 | exports.extractTar = extractTar; 3616 | /** 3617 | * Extract a zip 3618 | * 3619 | * @param file path to the zip 3620 | * @param dest destination directory. Optional. 3621 | * @returns path to the destination directory 3622 | */ 3623 | function extractZip(file, dest) { 3624 | return __awaiter(this, void 0, void 0, function* () { 3625 | if (!file) { 3626 | throw new Error("parameter 'file' is required"); 3627 | } 3628 | dest = yield _createExtractFolder(dest); 3629 | if (IS_WINDOWS) { 3630 | yield extractZipWin(file, dest); 3631 | } 3632 | else { 3633 | yield extractZipNix(file, dest); 3634 | } 3635 | return dest; 3636 | }); 3637 | } 3638 | exports.extractZip = extractZip; 3639 | function extractZipWin(file, dest) { 3640 | return __awaiter(this, void 0, void 0, function* () { 3641 | // build the powershell command 3642 | const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines 3643 | const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); 3644 | const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`; 3645 | // run powershell 3646 | const powershellPath = yield io.which('powershell'); 3647 | const args = [ 3648 | '-NoLogo', 3649 | '-Sta', 3650 | '-NoProfile', 3651 | '-NonInteractive', 3652 | '-ExecutionPolicy', 3653 | 'Unrestricted', 3654 | '-Command', 3655 | command 3656 | ]; 3657 | yield exec_1.exec(`"${powershellPath}"`, args); 3658 | }); 3659 | } 3660 | function extractZipNix(file, dest) { 3661 | return __awaiter(this, void 0, void 0, function* () { 3662 | const unzipPath = yield io.which('unzip'); 3663 | yield exec_1.exec(`"${unzipPath}"`, [file], { cwd: dest }); 3664 | }); 3665 | } 3666 | /** 3667 | * Caches a directory and installs it into the tool cacheDir 3668 | * 3669 | * @param sourceDir the directory to cache into tools 3670 | * @param tool tool name 3671 | * @param version version of the tool. semver format 3672 | * @param arch architecture of the tool. Optional. Defaults to machine architecture 3673 | */ 3674 | function cacheDir(sourceDir, tool, version, arch) { 3675 | return __awaiter(this, void 0, void 0, function* () { 3676 | version = semver.clean(version) || version; 3677 | arch = arch || os.arch(); 3678 | core.debug(`Caching tool ${tool} ${version} ${arch}`); 3679 | core.debug(`source dir: ${sourceDir}`); 3680 | if (!fs.statSync(sourceDir).isDirectory()) { 3681 | throw new Error('sourceDir is not a directory'); 3682 | } 3683 | // Create the tool dir 3684 | const destPath = yield _createToolPath(tool, version, arch); 3685 | // copy each child item. do not move. move can fail on Windows 3686 | // due to anti-virus software having an open handle on a file. 3687 | for (const itemName of fs.readdirSync(sourceDir)) { 3688 | const s = path.join(sourceDir, itemName); 3689 | yield io.cp(s, destPath, { recursive: true }); 3690 | } 3691 | // write .complete 3692 | _completeToolPath(tool, version, arch); 3693 | return destPath; 3694 | }); 3695 | } 3696 | exports.cacheDir = cacheDir; 3697 | /** 3698 | * Caches a downloaded file (GUID) and installs it 3699 | * into the tool cache with a given targetName 3700 | * 3701 | * @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid. 3702 | * @param targetFile the name of the file name in the tools directory 3703 | * @param tool tool name 3704 | * @param version version of the tool. semver format 3705 | * @param arch architecture of the tool. Optional. Defaults to machine architecture 3706 | */ 3707 | function cacheFile(sourceFile, targetFile, tool, version, arch) { 3708 | return __awaiter(this, void 0, void 0, function* () { 3709 | version = semver.clean(version) || version; 3710 | arch = arch || os.arch(); 3711 | core.debug(`Caching tool ${tool} ${version} ${arch}`); 3712 | core.debug(`source file: ${sourceFile}`); 3713 | if (!fs.statSync(sourceFile).isFile()) { 3714 | throw new Error('sourceFile is not a file'); 3715 | } 3716 | // create the tool dir 3717 | const destFolder = yield _createToolPath(tool, version, arch); 3718 | // copy instead of move. move can fail on Windows due to 3719 | // anti-virus software having an open handle on a file. 3720 | const destPath = path.join(destFolder, targetFile); 3721 | core.debug(`destination file ${destPath}`); 3722 | yield io.cp(sourceFile, destPath); 3723 | // write .complete 3724 | _completeToolPath(tool, version, arch); 3725 | return destFolder; 3726 | }); 3727 | } 3728 | exports.cacheFile = cacheFile; 3729 | /** 3730 | * Finds the path to a tool version in the local installed tool cache 3731 | * 3732 | * @param toolName name of the tool 3733 | * @param versionSpec version of the tool 3734 | * @param arch optional arch. defaults to arch of computer 3735 | */ 3736 | function find(toolName, versionSpec, arch) { 3737 | if (!toolName) { 3738 | throw new Error('toolName parameter is required'); 3739 | } 3740 | if (!versionSpec) { 3741 | throw new Error('versionSpec parameter is required'); 3742 | } 3743 | arch = arch || os.arch(); 3744 | // attempt to resolve an explicit version 3745 | if (!_isExplicitVersion(versionSpec)) { 3746 | const localVersions = findAllVersions(toolName, arch); 3747 | const match = _evaluateVersions(localVersions, versionSpec); 3748 | versionSpec = match; 3749 | } 3750 | // check for the explicit version in the cache 3751 | let toolPath = ''; 3752 | if (versionSpec) { 3753 | versionSpec = semver.clean(versionSpec) || ''; 3754 | const cachePath = path.join(cacheRoot, toolName, versionSpec, arch); 3755 | core.debug(`checking cache: ${cachePath}`); 3756 | if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) { 3757 | core.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`); 3758 | toolPath = cachePath; 3759 | } 3760 | else { 3761 | core.debug('not found'); 3762 | } 3763 | } 3764 | return toolPath; 3765 | } 3766 | exports.find = find; 3767 | /** 3768 | * Finds the paths to all versions of a tool that are installed in the local tool cache 3769 | * 3770 | * @param toolName name of the tool 3771 | * @param arch optional arch. defaults to arch of computer 3772 | */ 3773 | function findAllVersions(toolName, arch) { 3774 | const versions = []; 3775 | arch = arch || os.arch(); 3776 | const toolPath = path.join(cacheRoot, toolName); 3777 | if (fs.existsSync(toolPath)) { 3778 | const children = fs.readdirSync(toolPath); 3779 | for (const child of children) { 3780 | if (_isExplicitVersion(child)) { 3781 | const fullPath = path.join(toolPath, child, arch || ''); 3782 | if (fs.existsSync(fullPath) && fs.existsSync(`${fullPath}.complete`)) { 3783 | versions.push(child); 3784 | } 3785 | } 3786 | } 3787 | } 3788 | return versions; 3789 | } 3790 | exports.findAllVersions = findAllVersions; 3791 | function _createExtractFolder(dest) { 3792 | return __awaiter(this, void 0, void 0, function* () { 3793 | if (!dest) { 3794 | // create a temp dir 3795 | dest = path.join(tempDirectory, v4_1.default()); 3796 | } 3797 | yield io.mkdirP(dest); 3798 | return dest; 3799 | }); 3800 | } 3801 | function _createToolPath(tool, version, arch) { 3802 | return __awaiter(this, void 0, void 0, function* () { 3803 | const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || ''); 3804 | core.debug(`destination ${folderPath}`); 3805 | const markerPath = `${folderPath}.complete`; 3806 | yield io.rmRF(folderPath); 3807 | yield io.rmRF(markerPath); 3808 | yield io.mkdirP(folderPath); 3809 | return folderPath; 3810 | }); 3811 | } 3812 | function _completeToolPath(tool, version, arch) { 3813 | const folderPath = path.join(cacheRoot, tool, semver.clean(version) || version, arch || ''); 3814 | const markerPath = `${folderPath}.complete`; 3815 | fs.writeFileSync(markerPath, ''); 3816 | core.debug('finished caching tool'); 3817 | } 3818 | function _isExplicitVersion(versionSpec) { 3819 | const c = semver.clean(versionSpec) || ''; 3820 | core.debug(`isExplicit: ${c}`); 3821 | const valid = semver.valid(c) != null; 3822 | core.debug(`explicit? ${valid}`); 3823 | return valid; 3824 | } 3825 | function _evaluateVersions(versions, versionSpec) { 3826 | let version = ''; 3827 | core.debug(`evaluating ${versions.length} versions`); 3828 | versions = versions.sort((a, b) => { 3829 | if (semver.gt(a, b)) { 3830 | return 1; 3831 | } 3832 | return -1; 3833 | }); 3834 | for (let i = versions.length - 1; i >= 0; i--) { 3835 | const potential = versions[i]; 3836 | const satisfied = semver.satisfies(potential, versionSpec); 3837 | if (satisfied) { 3838 | version = potential; 3839 | break; 3840 | } 3841 | } 3842 | if (version) { 3843 | core.debug(`matched: ${version}`); 3844 | } 3845 | else { 3846 | core.debug('match not found'); 3847 | } 3848 | return version; 3849 | } 3850 | //# sourceMappingURL=tool-cache.js.map 3851 | 3852 | /***/ }), 3853 | 3854 | /***/ 539: 3855 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 3856 | 3857 | "use strict"; 3858 | 3859 | Object.defineProperty(exports, "__esModule", { value: true }); 3860 | const url = __webpack_require__(835); 3861 | const http = __webpack_require__(605); 3862 | const https = __webpack_require__(211); 3863 | const pm = __webpack_require__(950); 3864 | let tunnel; 3865 | var HttpCodes; 3866 | (function (HttpCodes) { 3867 | HttpCodes[HttpCodes["OK"] = 200] = "OK"; 3868 | HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; 3869 | HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; 3870 | HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; 3871 | HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; 3872 | HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; 3873 | HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; 3874 | HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; 3875 | HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; 3876 | HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; 3877 | HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; 3878 | HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; 3879 | HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; 3880 | HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; 3881 | HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; 3882 | HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; 3883 | HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; 3884 | HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; 3885 | HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; 3886 | HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; 3887 | HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; 3888 | HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; 3889 | HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; 3890 | HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; 3891 | HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; 3892 | HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; 3893 | })(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); 3894 | /** 3895 | * Returns the proxy URL, depending upon the supplied url and proxy environment variables. 3896 | * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com 3897 | */ 3898 | function getProxyUrl(serverUrl) { 3899 | let proxyUrl = pm.getProxyUrl(url.parse(serverUrl)); 3900 | return proxyUrl ? proxyUrl.href : ''; 3901 | } 3902 | exports.getProxyUrl = getProxyUrl; 3903 | const HttpRedirectCodes = [HttpCodes.MovedPermanently, HttpCodes.ResourceMoved, HttpCodes.SeeOther, HttpCodes.TemporaryRedirect, HttpCodes.PermanentRedirect]; 3904 | const HttpResponseRetryCodes = [HttpCodes.BadGateway, HttpCodes.ServiceUnavailable, HttpCodes.GatewayTimeout]; 3905 | const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; 3906 | const ExponentialBackoffCeiling = 10; 3907 | const ExponentialBackoffTimeSlice = 5; 3908 | class HttpClientResponse { 3909 | constructor(message) { 3910 | this.message = message; 3911 | } 3912 | readBody() { 3913 | return new Promise(async (resolve, reject) => { 3914 | let output = Buffer.alloc(0); 3915 | this.message.on('data', (chunk) => { 3916 | output = Buffer.concat([output, chunk]); 3917 | }); 3918 | this.message.on('end', () => { 3919 | resolve(output.toString()); 3920 | }); 3921 | }); 3922 | } 3923 | } 3924 | exports.HttpClientResponse = HttpClientResponse; 3925 | function isHttps(requestUrl) { 3926 | let parsedUrl = url.parse(requestUrl); 3927 | return parsedUrl.protocol === 'https:'; 3928 | } 3929 | exports.isHttps = isHttps; 3930 | class HttpClient { 3931 | constructor(userAgent, handlers, requestOptions) { 3932 | this._ignoreSslError = false; 3933 | this._allowRedirects = true; 3934 | this._allowRedirectDowngrade = false; 3935 | this._maxRedirects = 50; 3936 | this._allowRetries = false; 3937 | this._maxRetries = 1; 3938 | this._keepAlive = false; 3939 | this._disposed = false; 3940 | this.userAgent = userAgent; 3941 | this.handlers = handlers || []; 3942 | this.requestOptions = requestOptions; 3943 | if (requestOptions) { 3944 | if (requestOptions.ignoreSslError != null) { 3945 | this._ignoreSslError = requestOptions.ignoreSslError; 3946 | } 3947 | this._socketTimeout = requestOptions.socketTimeout; 3948 | if (requestOptions.allowRedirects != null) { 3949 | this._allowRedirects = requestOptions.allowRedirects; 3950 | } 3951 | if (requestOptions.allowRedirectDowngrade != null) { 3952 | this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; 3953 | } 3954 | if (requestOptions.maxRedirects != null) { 3955 | this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); 3956 | } 3957 | if (requestOptions.keepAlive != null) { 3958 | this._keepAlive = requestOptions.keepAlive; 3959 | } 3960 | if (requestOptions.allowRetries != null) { 3961 | this._allowRetries = requestOptions.allowRetries; 3962 | } 3963 | if (requestOptions.maxRetries != null) { 3964 | this._maxRetries = requestOptions.maxRetries; 3965 | } 3966 | } 3967 | } 3968 | options(requestUrl, additionalHeaders) { 3969 | return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); 3970 | } 3971 | get(requestUrl, additionalHeaders) { 3972 | return this.request('GET', requestUrl, null, additionalHeaders || {}); 3973 | } 3974 | del(requestUrl, additionalHeaders) { 3975 | return this.request('DELETE', requestUrl, null, additionalHeaders || {}); 3976 | } 3977 | post(requestUrl, data, additionalHeaders) { 3978 | return this.request('POST', requestUrl, data, additionalHeaders || {}); 3979 | } 3980 | patch(requestUrl, data, additionalHeaders) { 3981 | return this.request('PATCH', requestUrl, data, additionalHeaders || {}); 3982 | } 3983 | put(requestUrl, data, additionalHeaders) { 3984 | return this.request('PUT', requestUrl, data, additionalHeaders || {}); 3985 | } 3986 | head(requestUrl, additionalHeaders) { 3987 | return this.request('HEAD', requestUrl, null, additionalHeaders || {}); 3988 | } 3989 | sendStream(verb, requestUrl, stream, additionalHeaders) { 3990 | return this.request(verb, requestUrl, stream, additionalHeaders); 3991 | } 3992 | /** 3993 | * Makes a raw http request. 3994 | * All other methods such as get, post, patch, and request ultimately call this. 3995 | * Prefer get, del, post and patch 3996 | */ 3997 | async request(verb, requestUrl, data, headers) { 3998 | if (this._disposed) { 3999 | throw new Error("Client has already been disposed."); 4000 | } 4001 | let parsedUrl = url.parse(requestUrl); 4002 | let info = this._prepareRequest(verb, parsedUrl, headers); 4003 | // Only perform retries on reads since writes may not be idempotent. 4004 | let maxTries = (this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1) ? this._maxRetries + 1 : 1; 4005 | let numTries = 0; 4006 | let response; 4007 | while (numTries < maxTries) { 4008 | response = await this.requestRaw(info, data); 4009 | // Check if it's an authentication challenge 4010 | if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { 4011 | let authenticationHandler; 4012 | for (let i = 0; i < this.handlers.length; i++) { 4013 | if (this.handlers[i].canHandleAuthentication(response)) { 4014 | authenticationHandler = this.handlers[i]; 4015 | break; 4016 | } 4017 | } 4018 | if (authenticationHandler) { 4019 | return authenticationHandler.handleAuthentication(this, info, data); 4020 | } 4021 | else { 4022 | // We have received an unauthorized response but have no handlers to handle it. 4023 | // Let the response return to the caller. 4024 | return response; 4025 | } 4026 | } 4027 | let redirectsRemaining = this._maxRedirects; 4028 | while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 4029 | && this._allowRedirects 4030 | && redirectsRemaining > 0) { 4031 | const redirectUrl = response.message.headers["location"]; 4032 | if (!redirectUrl) { 4033 | // if there's no location to redirect to, we won't 4034 | break; 4035 | } 4036 | let parsedRedirectUrl = url.parse(redirectUrl); 4037 | if (parsedUrl.protocol == 'https:' && parsedUrl.protocol != parsedRedirectUrl.protocol && !this._allowRedirectDowngrade) { 4038 | throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true."); 4039 | } 4040 | // we need to finish reading the response before reassigning response 4041 | // which will leak the open socket. 4042 | await response.readBody(); 4043 | // let's make the request with the new redirectUrl 4044 | info = this._prepareRequest(verb, parsedRedirectUrl, headers); 4045 | response = await this.requestRaw(info, data); 4046 | redirectsRemaining--; 4047 | } 4048 | if (HttpResponseRetryCodes.indexOf(response.message.statusCode) == -1) { 4049 | // If not a retry code, return immediately instead of retrying 4050 | return response; 4051 | } 4052 | numTries += 1; 4053 | if (numTries < maxTries) { 4054 | await response.readBody(); 4055 | await this._performExponentialBackoff(numTries); 4056 | } 4057 | } 4058 | return response; 4059 | } 4060 | /** 4061 | * Needs to be called if keepAlive is set to true in request options. 4062 | */ 4063 | dispose() { 4064 | if (this._agent) { 4065 | this._agent.destroy(); 4066 | } 4067 | this._disposed = true; 4068 | } 4069 | /** 4070 | * Raw request. 4071 | * @param info 4072 | * @param data 4073 | */ 4074 | requestRaw(info, data) { 4075 | return new Promise((resolve, reject) => { 4076 | let callbackForResult = function (err, res) { 4077 | if (err) { 4078 | reject(err); 4079 | } 4080 | resolve(res); 4081 | }; 4082 | this.requestRawWithCallback(info, data, callbackForResult); 4083 | }); 4084 | } 4085 | /** 4086 | * Raw request with callback. 4087 | * @param info 4088 | * @param data 4089 | * @param onResult 4090 | */ 4091 | requestRawWithCallback(info, data, onResult) { 4092 | let socket; 4093 | if (typeof (data) === 'string') { 4094 | info.options.headers["Content-Length"] = Buffer.byteLength(data, 'utf8'); 4095 | } 4096 | let callbackCalled = false; 4097 | let handleResult = (err, res) => { 4098 | if (!callbackCalled) { 4099 | callbackCalled = true; 4100 | onResult(err, res); 4101 | } 4102 | }; 4103 | let req = info.httpModule.request(info.options, (msg) => { 4104 | let res = new HttpClientResponse(msg); 4105 | handleResult(null, res); 4106 | }); 4107 | req.on('socket', (sock) => { 4108 | socket = sock; 4109 | }); 4110 | // If we ever get disconnected, we want the socket to timeout eventually 4111 | req.setTimeout(this._socketTimeout || 3 * 60000, () => { 4112 | if (socket) { 4113 | socket.end(); 4114 | } 4115 | handleResult(new Error('Request timeout: ' + info.options.path), null); 4116 | }); 4117 | req.on('error', function (err) { 4118 | // err has statusCode property 4119 | // res should have headers 4120 | handleResult(err, null); 4121 | }); 4122 | if (data && typeof (data) === 'string') { 4123 | req.write(data, 'utf8'); 4124 | } 4125 | if (data && typeof (data) !== 'string') { 4126 | data.on('close', function () { 4127 | req.end(); 4128 | }); 4129 | data.pipe(req); 4130 | } 4131 | else { 4132 | req.end(); 4133 | } 4134 | } 4135 | /** 4136 | * Gets an http agent. This function is useful when you need an http agent that handles 4137 | * routing through a proxy server - depending upon the url and proxy environment variables. 4138 | * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com 4139 | */ 4140 | getAgent(serverUrl) { 4141 | let parsedUrl = url.parse(serverUrl); 4142 | return this._getAgent(parsedUrl); 4143 | } 4144 | _prepareRequest(method, requestUrl, headers) { 4145 | const info = {}; 4146 | info.parsedUrl = requestUrl; 4147 | const usingSsl = info.parsedUrl.protocol === 'https:'; 4148 | info.httpModule = usingSsl ? https : http; 4149 | const defaultPort = usingSsl ? 443 : 80; 4150 | info.options = {}; 4151 | info.options.host = info.parsedUrl.hostname; 4152 | info.options.port = info.parsedUrl.port ? parseInt(info.parsedUrl.port) : defaultPort; 4153 | info.options.path = (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); 4154 | info.options.method = method; 4155 | info.options.headers = this._mergeHeaders(headers); 4156 | if (this.userAgent != null) { 4157 | info.options.headers["user-agent"] = this.userAgent; 4158 | } 4159 | info.options.agent = this._getAgent(info.parsedUrl); 4160 | // gives handlers an opportunity to participate 4161 | if (this.handlers) { 4162 | this.handlers.forEach((handler) => { 4163 | handler.prepareRequest(info.options); 4164 | }); 4165 | } 4166 | return info; 4167 | } 4168 | _mergeHeaders(headers) { 4169 | const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {}); 4170 | if (this.requestOptions && this.requestOptions.headers) { 4171 | return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers)); 4172 | } 4173 | return lowercaseKeys(headers || {}); 4174 | } 4175 | _getAgent(parsedUrl) { 4176 | let agent; 4177 | let proxyUrl = pm.getProxyUrl(parsedUrl); 4178 | let useProxy = proxyUrl && proxyUrl.hostname; 4179 | if (this._keepAlive && useProxy) { 4180 | agent = this._proxyAgent; 4181 | } 4182 | if (this._keepAlive && !useProxy) { 4183 | agent = this._agent; 4184 | } 4185 | // if agent is already assigned use that agent. 4186 | if (!!agent) { 4187 | return agent; 4188 | } 4189 | const usingSsl = parsedUrl.protocol === 'https:'; 4190 | let maxSockets = 100; 4191 | if (!!this.requestOptions) { 4192 | maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; 4193 | } 4194 | if (useProxy) { 4195 | // If using proxy, need tunnel 4196 | if (!tunnel) { 4197 | tunnel = __webpack_require__(413); 4198 | } 4199 | const agentOptions = { 4200 | maxSockets: maxSockets, 4201 | keepAlive: this._keepAlive, 4202 | proxy: { 4203 | proxyAuth: proxyUrl.auth, 4204 | host: proxyUrl.hostname, 4205 | port: proxyUrl.port 4206 | }, 4207 | }; 4208 | let tunnelAgent; 4209 | const overHttps = proxyUrl.protocol === 'https:'; 4210 | if (usingSsl) { 4211 | tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; 4212 | } 4213 | else { 4214 | tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; 4215 | } 4216 | agent = tunnelAgent(agentOptions); 4217 | this._proxyAgent = agent; 4218 | } 4219 | // if reusing agent across request and tunneling agent isn't assigned create a new agent 4220 | if (this._keepAlive && !agent) { 4221 | const options = { keepAlive: this._keepAlive, maxSockets: maxSockets }; 4222 | agent = usingSsl ? new https.Agent(options) : new http.Agent(options); 4223 | this._agent = agent; 4224 | } 4225 | // if not using private agent and tunnel agent isn't setup then use global agent 4226 | if (!agent) { 4227 | agent = usingSsl ? https.globalAgent : http.globalAgent; 4228 | } 4229 | if (usingSsl && this._ignoreSslError) { 4230 | // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process 4231 | // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options 4232 | // we have to cast it to any and change it directly 4233 | agent.options = Object.assign(agent.options || {}, { rejectUnauthorized: false }); 4234 | } 4235 | return agent; 4236 | } 4237 | _performExponentialBackoff(retryNumber) { 4238 | retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); 4239 | const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); 4240 | return new Promise(resolve => setTimeout(() => resolve(), ms)); 4241 | } 4242 | } 4243 | exports.HttpClient = HttpClient; 4244 | 4245 | 4246 | /***/ }), 4247 | 4248 | /***/ 605: 4249 | /***/ (function(module) { 4250 | 4251 | module.exports = require("http"); 4252 | 4253 | /***/ }), 4254 | 4255 | /***/ 614: 4256 | /***/ (function(module) { 4257 | 4258 | module.exports = require("events"); 4259 | 4260 | /***/ }), 4261 | 4262 | /***/ 622: 4263 | /***/ (function(module) { 4264 | 4265 | module.exports = require("path"); 4266 | 4267 | /***/ }), 4268 | 4269 | /***/ 631: 4270 | /***/ (function(module) { 4271 | 4272 | module.exports = require("net"); 4273 | 4274 | /***/ }), 4275 | 4276 | /***/ 669: 4277 | /***/ (function(module) { 4278 | 4279 | module.exports = require("util"); 4280 | 4281 | /***/ }), 4282 | 4283 | /***/ 672: 4284 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 4285 | 4286 | "use strict"; 4287 | 4288 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 4289 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4290 | return new (P || (P = Promise))(function (resolve, reject) { 4291 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 4292 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 4293 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 4294 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 4295 | }); 4296 | }; 4297 | var _a; 4298 | Object.defineProperty(exports, "__esModule", { value: true }); 4299 | const assert_1 = __webpack_require__(357); 4300 | const fs = __webpack_require__(747); 4301 | const path = __webpack_require__(622); 4302 | _a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; 4303 | exports.IS_WINDOWS = process.platform === 'win32'; 4304 | function exists(fsPath) { 4305 | return __awaiter(this, void 0, void 0, function* () { 4306 | try { 4307 | yield exports.stat(fsPath); 4308 | } 4309 | catch (err) { 4310 | if (err.code === 'ENOENT') { 4311 | return false; 4312 | } 4313 | throw err; 4314 | } 4315 | return true; 4316 | }); 4317 | } 4318 | exports.exists = exists; 4319 | function isDirectory(fsPath, useStat = false) { 4320 | return __awaiter(this, void 0, void 0, function* () { 4321 | const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); 4322 | return stats.isDirectory(); 4323 | }); 4324 | } 4325 | exports.isDirectory = isDirectory; 4326 | /** 4327 | * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: 4328 | * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). 4329 | */ 4330 | function isRooted(p) { 4331 | p = normalizeSeparators(p); 4332 | if (!p) { 4333 | throw new Error('isRooted() parameter "p" cannot be empty'); 4334 | } 4335 | if (exports.IS_WINDOWS) { 4336 | return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello 4337 | ); // e.g. C: or C:\hello 4338 | } 4339 | return p.startsWith('/'); 4340 | } 4341 | exports.isRooted = isRooted; 4342 | /** 4343 | * Recursively create a directory at `fsPath`. 4344 | * 4345 | * This implementation is optimistic, meaning it attempts to create the full 4346 | * path first, and backs up the path stack from there. 4347 | * 4348 | * @param fsPath The path to create 4349 | * @param maxDepth The maximum recursion depth 4350 | * @param depth The current recursion depth 4351 | */ 4352 | function mkdirP(fsPath, maxDepth = 1000, depth = 1) { 4353 | return __awaiter(this, void 0, void 0, function* () { 4354 | assert_1.ok(fsPath, 'a path argument must be provided'); 4355 | fsPath = path.resolve(fsPath); 4356 | if (depth >= maxDepth) 4357 | return exports.mkdir(fsPath); 4358 | try { 4359 | yield exports.mkdir(fsPath); 4360 | return; 4361 | } 4362 | catch (err) { 4363 | switch (err.code) { 4364 | case 'ENOENT': { 4365 | yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); 4366 | yield exports.mkdir(fsPath); 4367 | return; 4368 | } 4369 | default: { 4370 | let stats; 4371 | try { 4372 | stats = yield exports.stat(fsPath); 4373 | } 4374 | catch (err2) { 4375 | throw err; 4376 | } 4377 | if (!stats.isDirectory()) 4378 | throw err; 4379 | } 4380 | } 4381 | } 4382 | }); 4383 | } 4384 | exports.mkdirP = mkdirP; 4385 | /** 4386 | * Best effort attempt to determine whether a file exists and is executable. 4387 | * @param filePath file path to check 4388 | * @param extensions additional file extensions to try 4389 | * @return if file exists and is executable, returns the file path. otherwise empty string. 4390 | */ 4391 | function tryGetExecutablePath(filePath, extensions) { 4392 | return __awaiter(this, void 0, void 0, function* () { 4393 | let stats = undefined; 4394 | try { 4395 | // test file exists 4396 | stats = yield exports.stat(filePath); 4397 | } 4398 | catch (err) { 4399 | if (err.code !== 'ENOENT') { 4400 | // eslint-disable-next-line no-console 4401 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 4402 | } 4403 | } 4404 | if (stats && stats.isFile()) { 4405 | if (exports.IS_WINDOWS) { 4406 | // on Windows, test for valid extension 4407 | const upperExt = path.extname(filePath).toUpperCase(); 4408 | if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { 4409 | return filePath; 4410 | } 4411 | } 4412 | else { 4413 | if (isUnixExecutable(stats)) { 4414 | return filePath; 4415 | } 4416 | } 4417 | } 4418 | // try each extension 4419 | const originalFilePath = filePath; 4420 | for (const extension of extensions) { 4421 | filePath = originalFilePath + extension; 4422 | stats = undefined; 4423 | try { 4424 | stats = yield exports.stat(filePath); 4425 | } 4426 | catch (err) { 4427 | if (err.code !== 'ENOENT') { 4428 | // eslint-disable-next-line no-console 4429 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 4430 | } 4431 | } 4432 | if (stats && stats.isFile()) { 4433 | if (exports.IS_WINDOWS) { 4434 | // preserve the case of the actual file (since an extension was appended) 4435 | try { 4436 | const directory = path.dirname(filePath); 4437 | const upperName = path.basename(filePath).toUpperCase(); 4438 | for (const actualName of yield exports.readdir(directory)) { 4439 | if (upperName === actualName.toUpperCase()) { 4440 | filePath = path.join(directory, actualName); 4441 | break; 4442 | } 4443 | } 4444 | } 4445 | catch (err) { 4446 | // eslint-disable-next-line no-console 4447 | console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); 4448 | } 4449 | return filePath; 4450 | } 4451 | else { 4452 | if (isUnixExecutable(stats)) { 4453 | return filePath; 4454 | } 4455 | } 4456 | } 4457 | } 4458 | return ''; 4459 | }); 4460 | } 4461 | exports.tryGetExecutablePath = tryGetExecutablePath; 4462 | function normalizeSeparators(p) { 4463 | p = p || ''; 4464 | if (exports.IS_WINDOWS) { 4465 | // convert slashes on Windows 4466 | p = p.replace(/\//g, '\\'); 4467 | // remove redundant slashes 4468 | return p.replace(/\\\\+/g, '\\'); 4469 | } 4470 | // remove redundant slashes 4471 | return p.replace(/\/\/+/g, '/'); 4472 | } 4473 | // on Mac/Linux, test the execute bit 4474 | // R W X R W X R W X 4475 | // 256 128 64 32 16 8 4 2 1 4476 | function isUnixExecutable(stats) { 4477 | return ((stats.mode & 1) > 0 || 4478 | ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || 4479 | ((stats.mode & 64) > 0 && stats.uid === process.getuid())); 4480 | } 4481 | //# sourceMappingURL=io-util.js.map 4482 | 4483 | /***/ }), 4484 | 4485 | /***/ 722: 4486 | /***/ (function(module) { 4487 | 4488 | /** 4489 | * Convert array of 16 byte values to UUID string format of the form: 4490 | * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 4491 | */ 4492 | var byteToHex = []; 4493 | for (var i = 0; i < 256; ++i) { 4494 | byteToHex[i] = (i + 0x100).toString(16).substr(1); 4495 | } 4496 | 4497 | function bytesToUuid(buf, offset) { 4498 | var i = offset || 0; 4499 | var bth = byteToHex; 4500 | // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 4501 | return ([bth[buf[i++]], bth[buf[i++]], 4502 | bth[buf[i++]], bth[buf[i++]], '-', 4503 | bth[buf[i++]], bth[buf[i++]], '-', 4504 | bth[buf[i++]], bth[buf[i++]], '-', 4505 | bth[buf[i++]], bth[buf[i++]], '-', 4506 | bth[buf[i++]], bth[buf[i++]], 4507 | bth[buf[i++]], bth[buf[i++]], 4508 | bth[buf[i++]], bth[buf[i++]]]).join(''); 4509 | } 4510 | 4511 | module.exports = bytesToUuid; 4512 | 4513 | 4514 | /***/ }), 4515 | 4516 | /***/ 747: 4517 | /***/ (function(module) { 4518 | 4519 | module.exports = require("fs"); 4520 | 4521 | /***/ }), 4522 | 4523 | /***/ 826: 4524 | /***/ (function(module, __unusedexports, __webpack_require__) { 4525 | 4526 | var rng = __webpack_require__(139); 4527 | var bytesToUuid = __webpack_require__(722); 4528 | 4529 | function v4(options, buf, offset) { 4530 | var i = buf && offset || 0; 4531 | 4532 | if (typeof(options) == 'string') { 4533 | buf = options === 'binary' ? new Array(16) : null; 4534 | options = null; 4535 | } 4536 | options = options || {}; 4537 | 4538 | var rnds = options.random || (options.rng || rng)(); 4539 | 4540 | // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` 4541 | rnds[6] = (rnds[6] & 0x0f) | 0x40; 4542 | rnds[8] = (rnds[8] & 0x3f) | 0x80; 4543 | 4544 | // Copy bytes to buffer, if provided 4545 | if (buf) { 4546 | for (var ii = 0; ii < 16; ++ii) { 4547 | buf[i + ii] = rnds[ii]; 4548 | } 4549 | } 4550 | 4551 | return buf || bytesToUuid(rnds); 4552 | } 4553 | 4554 | module.exports = v4; 4555 | 4556 | 4557 | /***/ }), 4558 | 4559 | /***/ 835: 4560 | /***/ (function(module) { 4561 | 4562 | module.exports = require("url"); 4563 | 4564 | /***/ }), 4565 | 4566 | /***/ 950: 4567 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 4568 | 4569 | "use strict"; 4570 | 4571 | Object.defineProperty(exports, "__esModule", { value: true }); 4572 | const url = __webpack_require__(835); 4573 | function getProxyUrl(reqUrl) { 4574 | let usingSsl = reqUrl.protocol === 'https:'; 4575 | let proxyUrl; 4576 | if (checkBypass(reqUrl)) { 4577 | return proxyUrl; 4578 | } 4579 | let proxyVar; 4580 | if (usingSsl) { 4581 | proxyVar = process.env["https_proxy"] || 4582 | process.env["HTTPS_PROXY"]; 4583 | } 4584 | else { 4585 | proxyVar = process.env["http_proxy"] || 4586 | process.env["HTTP_PROXY"]; 4587 | } 4588 | if (proxyVar) { 4589 | proxyUrl = url.parse(proxyVar); 4590 | } 4591 | return proxyUrl; 4592 | } 4593 | exports.getProxyUrl = getProxyUrl; 4594 | function checkBypass(reqUrl) { 4595 | if (!reqUrl.hostname) { 4596 | return false; 4597 | } 4598 | let noProxy = process.env["no_proxy"] || process.env["NO_PROXY"] || ''; 4599 | if (!noProxy) { 4600 | return false; 4601 | } 4602 | // Determine the request port 4603 | let reqPort; 4604 | if (reqUrl.port) { 4605 | reqPort = Number(reqUrl.port); 4606 | } 4607 | else if (reqUrl.protocol === 'http:') { 4608 | reqPort = 80; 4609 | } 4610 | else if (reqUrl.protocol === 'https:') { 4611 | reqPort = 443; 4612 | } 4613 | // Format the request hostname and hostname with port 4614 | let upperReqHosts = [reqUrl.hostname.toUpperCase()]; 4615 | if (typeof reqPort === 'number') { 4616 | upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); 4617 | } 4618 | // Compare request host against noproxy 4619 | for (let upperNoProxyItem of noProxy.split(',').map(x => x.trim().toUpperCase()).filter(x => x)) { 4620 | if (upperReqHosts.some(x => x === upperNoProxyItem)) { 4621 | return true; 4622 | } 4623 | } 4624 | return false; 4625 | } 4626 | exports.checkBypass = checkBypass; 4627 | 4628 | 4629 | /***/ }), 4630 | 4631 | /***/ 986: 4632 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 4633 | 4634 | "use strict"; 4635 | 4636 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 4637 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4638 | return new (P || (P = Promise))(function (resolve, reject) { 4639 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 4640 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 4641 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 4642 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 4643 | }); 4644 | }; 4645 | Object.defineProperty(exports, "__esModule", { value: true }); 4646 | const tr = __webpack_require__(9); 4647 | /** 4648 | * Exec a command. 4649 | * Output will be streamed to the live console. 4650 | * Returns promise with return code 4651 | * 4652 | * @param commandLine command to execute (can include additional args). Must be correctly escaped. 4653 | * @param args optional arguments for tool. Escaping is handled by the lib. 4654 | * @param options optional exec options. See ExecOptions 4655 | * @returns Promise exit code 4656 | */ 4657 | function exec(commandLine, args, options) { 4658 | return __awaiter(this, void 0, void 0, function* () { 4659 | const commandArgs = tr.argStringToArray(commandLine); 4660 | if (commandArgs.length === 0) { 4661 | throw new Error(`Parameter 'commandLine' cannot be null or empty.`); 4662 | } 4663 | // Path to tool to execute should be first arg 4664 | const toolPath = commandArgs[0]; 4665 | args = commandArgs.slice(1).concat(args || []); 4666 | const runner = new tr.ToolRunner(toolPath, args, options); 4667 | return runner.exec(); 4668 | }); 4669 | } 4670 | exports.exec = exec; 4671 | //# sourceMappingURL=exec.js.map 4672 | 4673 | /***/ }) 4674 | 4675 | /******/ }); -------------------------------------------------------------------------------- /docs/contributors.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | ### Changes 4 | 5 | The process is consistent for internal and external contributions. The only difference is external contributions PRs come from a fork. 6 | 7 | For trivial bug fixes, create an issue to discuss and then a PR can follow referencing the issue. 8 | 9 | For enhancements and new features, create an enhancment issue for discuss followed by a [design proposal known as an ADR](https://github.com/actions/setup-ruby/blob/adrs/adrs/README.md). This allows everyone to get to consensus before coding and also serves as a record going forward. 10 | 11 | ### Checkin 12 | 13 | - Do checkin source (src) 14 | - Do checkin build output (lib) 15 | - Do checkin runtime node_modules 16 | - Do not checkin devDependency node_modules (husky can help see below) 17 | 18 | ### devDependencies 19 | 20 | In order to handle correctly checking in node_modules without devDependencies, we run [Husky](https://github.com/typicode/husky) before each commit. 21 | This step ensures that formatting and checkin rules are followed and that devDependencies are excluded. To make sure Husky runs correctly, please use the following workflow: 22 | 23 | ``` 24 | npm install # installs all devDependencies including Husky 25 | git add abc.ext # Add the files you've changed. This should include files in src, lib, and node_modules (see above) 26 | git commit -m "Informative commit message" # Commit. This will run Husky 27 | ``` 28 | 29 | During the commit step, Husky will take care of formatting all files with [Prettier](https://github.com/prettier/prettier) as well as pruning out devDependencies using `npm prune --production`. 30 | It will also make sure these changes are appropriately included in your commit (no further work is needed) -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | clearMocks: true, 3 | moduleFileExtensions: ['js', 'ts'], 4 | testEnvironment: 'node', 5 | testMatch: ['**/*.test.ts'], 6 | testRunner: 'jest-circus/runner', 7 | transform: { 8 | '^.+\\.ts$': 'ts-jest' 9 | }, 10 | verbose: true 11 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-ruby", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "setup ruby action", 6 | "main": "lib/setup-ruby.js", 7 | "scripts": { 8 | "build": "tsc && ncc build", 9 | "format": "prettier --write **/*.ts", 10 | "format-check": "prettier --check **/*.ts", 11 | "test": "jest", 12 | "pre-checkin": "npm run format && npm run build && npm test" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/actions/setup-ruby.git" 17 | }, 18 | "keywords": [ 19 | "actions", 20 | "ruby", 21 | "setup" 22 | ], 23 | "author": "GitHub", 24 | "license": "MIT", 25 | "dependencies": { 26 | "@actions/core": "^1.2.2", 27 | "@actions/tool-cache": "^1.3.1", 28 | "semver": "^6.1.1" 29 | }, 30 | "devDependencies": { 31 | "@types/jest": "^24.0.13", 32 | "@types/node": "^12.0.4", 33 | "@types/semver": "^6.0.0", 34 | "@zeit/ncc": "^0.21.0", 35 | "jest": "^24.8.0", 36 | "jest-circus": "^24.7.1", 37 | "prettier": "^1.17.1", 38 | "ts-jest": "^24.0.2", 39 | "typescript": "^3.5.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/cache.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import * as tc from '@actions/tool-cache'; 3 | import * as path from 'path'; 4 | 5 | export async function find(version: string): Promise { 6 | const installDir: string | null = tc.find('Ruby', version); 7 | 8 | let toolPath: string = installDir ? path.join(installDir, 'bin') : ''; 9 | 10 | return toolPath; 11 | } 12 | -------------------------------------------------------------------------------- /src/installer.ts: -------------------------------------------------------------------------------- 1 | // TODO: support acquiring JIT 2 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import * as cache from './cache'; 3 | 4 | export async function run() { 5 | try { 6 | core.info('------------------------'); 7 | core.info('NOTE: This action is deprecated and is no longer maintained.'); 8 | core.info( 9 | 'Please, migrate to https://github.com/ruby/setup-ruby, which is being actively maintained.' 10 | ); 11 | core.info('------------------------'); 12 | 13 | let versionSpec = core.getInput('ruby-version', {required: true}); 14 | if (!versionSpec) { 15 | // deprecated 16 | versionSpec = core.getInput('version'); 17 | } 18 | 19 | // check in the VMs cache first 20 | let toolPath: string = await cache.find(versionSpec); 21 | 22 | // TODO: download JIT and/or ruby-build 23 | 24 | if (!toolPath) { 25 | core.setFailed(`Version ${versionSpec} not found`); 26 | return; 27 | } 28 | 29 | core.addPath(toolPath); 30 | } catch (error) { 31 | // unhandled 32 | core.setFailed(error.message); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/setup-ruby.ts: -------------------------------------------------------------------------------- 1 | import {run} from './main'; 2 | 3 | run(); 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./lib", /* Redirect output structure to the directory. */ 15 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 18 | // "removeComments": true, /* Do not emit comments to output. */ 19 | // "noEmit": true, /* Do not emit outputs. */ 20 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 21 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 22 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 23 | 24 | /* Strict Type-Checking Options */ 25 | "strict": true, /* Enable all strict type-checking options. */ 26 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 27 | // "strictNullChecks": true, /* Enable strict null checks. */ 28 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 29 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 30 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 31 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 32 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 33 | 34 | /* Additional Checks */ 35 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 36 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 37 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 38 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 39 | 40 | /* Module Resolution Options */ 41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 45 | // "typeRoots": [], /* List of folders to include type definitions from. */ 46 | // "types": [], /* Type declaration files to be included in compilation. */ 47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 48 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 50 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 60 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 61 | }, 62 | "exclude": ["node_modules", "**/*.test.ts"] 63 | } 64 | --------------------------------------------------------------------------------