├── .github
├── CODEOWNERS
├── actions
│ └── generate-action-code
│ │ └── action.yml
├── codeql
│ └── config.yml
├── dependabot.yml
└── workflows
│ ├── codeql-analysis.yml
│ ├── deploy.yml
│ ├── enable-auto-merge.yml
│ ├── tag-update.yml
│ └── tests.yml
├── .gitignore
├── LICENSE
├── README.md
├── __test__
└── TestProject
│ ├── .gitignore
│ ├── Package.swift
│ ├── Sources
│ ├── TestProject1
│ │ └── MainObject.swift
│ └── TestProject2
│ │ └── SomeObject.swift
│ └── Tests
│ ├── TestProject1Tests
│ └── MainObjectTests.swift
│ └── TestProject2Tests
│ └── SomeObjectTests.swift
├── action.yml
├── dist
├── index.js
└── license.txt
├── package-lock.json
├── package.json
├── src
└── main.ts
└── tsconfig.json
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Global
2 | * @ffried
3 |
4 | # Workflow & Deployment related files
5 | .github/* @ffried
6 | action.yml @ffried
7 |
8 | # Project & Source files
9 | /__test__ @ffried
10 | /*.json @ffried
11 | *.ts @ffried
12 |
--------------------------------------------------------------------------------
/.github/actions/generate-action-code/action.yml:
--------------------------------------------------------------------------------
1 | name: Generate Action Code
2 | description: Generates the action code
3 |
4 | runs:
5 | using: composite
6 | steps:
7 | - uses: actions/setup-node@v4
8 | with:
9 | node-version: 20
10 | check-latest: true
11 | cache: 'npm'
12 | - name: Generate action code
13 | shell: bash
14 | run: |
15 | npm clean-install
16 | npm run build
17 | npm run pack
18 |
--------------------------------------------------------------------------------
/.github/codeql/config.yml:
--------------------------------------------------------------------------------
1 | paths-ignore:
2 | - node_modules
3 | - __test__
4 | - dist
5 | - lib
6 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | open-pull-requests-limit: 10
7 | schedule:
8 | interval: "daily"
9 | time: "07:00"
10 | timezone: "Europe/Berlin"
11 | assignees:
12 | - ffried
13 | reviewers:
14 | - ffried
15 | - package-ecosystem: "github-actions"
16 | directory: ".github/actions/generate-action-code"
17 | open-pull-requests-limit: 10
18 | schedule:
19 | interval: "daily"
20 | time: "07:00"
21 | timezone: "Europe/Berlin"
22 | assignees:
23 | - ffried
24 | reviewers:
25 | - ffried
26 | - package-ecosystem: "npm"
27 | directory: "/"
28 | open-pull-requests-limit: 10
29 | schedule:
30 | interval: "daily"
31 | time: "07:00"
32 | timezone: "Europe/Berlin"
33 | assignees:
34 | - ffried
35 | reviewers:
36 | - ffried
37 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: CodeQL
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths-ignore: [ 'dist/*.js' ]
7 | pull_request:
8 | # The branches below must be a subset of the branches above
9 | branches: [ main ]
10 | schedule:
11 | - cron: '15 11 * * 1'
12 |
13 | jobs:
14 | analyze:
15 | name: Analyze
16 | runs-on: ubuntu-latest
17 | permissions:
18 | actions: read
19 | contents: read
20 | security-events: write
21 |
22 | strategy:
23 | fail-fast: false
24 | matrix:
25 | language: [ 'javascript' ]
26 |
27 | steps:
28 | - name: Checkout repository
29 | uses: actions/checkout@v4
30 |
31 | - name: Initialize CodeQL
32 | uses: github/codeql-action/init@v3
33 | with:
34 | config-file: ./.github/codeql/config.yml
35 | languages: ${{ matrix.language }}
36 |
37 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
38 | # If this step fails, then you should remove it and run the build manually (see below)
39 | - name: Autobuild
40 | uses: github/codeql-action/autobuild@v3
41 |
42 | # ℹ️ Command-line programs to run using the OS shell.
43 | # 📚 https://git.io/JvXDl
44 |
45 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
46 | # and modify them (or add more) to build your code if your project
47 | # uses a compiled language
48 |
49 | #- run: |
50 | # make bootstrap
51 | # make release
52 |
53 | - name: Perform CodeQL Analysis
54 | uses: github/codeql-action/analyze@v3
55 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Action Code
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths-ignore: [ 'dist/*.js' ]
7 |
8 | jobs:
9 | deploy-action-code:
10 | name: Deploy Action Code
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | with:
15 | token: ${{ secrets.BOT_TOKEN }}
16 | - uses: ./.github/actions/generate-action-code
17 | - name: Configure repository
18 | env:
19 | BOT_USERNAME: ${{ secrets.BOT_USERNAME }}
20 | run: |
21 | git config user.name "${BOT_USERNAME}"
22 | git config user.email "${BOT_USERNAME}@users.noreply.github.com"
23 | - name: Commit changes
24 | run: |
25 | if ! git diff --exit-code --quiet; then
26 | git add .
27 | git commit -m '[AUTO] Update generated code'
28 | git push
29 | fi
30 |
--------------------------------------------------------------------------------
/.github/workflows/enable-auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: Auto-merge for Dependabot PRs
2 |
3 | on: pull_request
4 |
5 | permissions:
6 | contents: write
7 | pull-requests: write
8 |
9 | jobs:
10 | enable-auto-merge:
11 | runs-on: ubuntu-latest
12 | if: ${{ github.actor == 'dependabot[bot]' }}
13 | steps:
14 | - name: Enable auto-merge
15 | run: gh pr merge --auto --rebase "${PR_URL}"
16 | env:
17 | PR_URL: ${{ github.event.pull_request.html_url }}
18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 |
--------------------------------------------------------------------------------
/.github/workflows/tag-update.yml:
--------------------------------------------------------------------------------
1 | name: Update Release Tags
2 |
3 | on:
4 | release:
5 | types: [ published ]
6 |
7 | jobs:
8 | update-tags:
9 | name: Update Running Releases
10 | runs-on: ubuntu-latest
11 | if: ${{ github.event.release.prerelease == false }}
12 | steps:
13 | - uses: actions/checkout@v4
14 | - uses: sersoft-gmbh/running-release-tags-action@v3
15 | with:
16 | update-full-release: true
17 | github-token: ${{ secrets.GITHUB_TOKEN }}
18 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths:
7 | - 'dist/*.js'
8 | - '.github/workflows/tests.yml'
9 | pull_request:
10 | branches: [ main ]
11 |
12 | jobs:
13 | test-defaults:
14 | name: Test Default Inputs
15 | strategy:
16 | matrix:
17 | os: [ macos-14, ubuntu-latest ]
18 | runs-on: ${{ matrix.os }}
19 | container: ${{ matrix.os == 'ubuntu-latest' && 'swift:5.9' || '' }}
20 | steps:
21 | - uses: maxim-lobanov/setup-xcode@v1
22 | if: ${{ runner.os == 'macOS' }}
23 | with:
24 | xcode-version: ^15.0
25 | - uses: actions/checkout@v4
26 | - name: Generate action code
27 | if: ${{ github.event_name == 'pull_request' }}
28 | uses: ./.github/actions/generate-action-code
29 | - uses: sersoft-gmbh/xcodebuild-action@v3
30 | if: ${{ runner.os == 'macOS' }}
31 | with:
32 | spm-package: __test__/TestProject
33 | scheme: TestProject-Package
34 | destination: platform=macOS
35 | action: test
36 | enable-code-coverage: true
37 | parallel-testing-enabled: true
38 | - run: swift test --parallel --enable-code-coverage
39 | working-directory: __test__/TestProject
40 | - run: ln -s __test__/TestProject/.build .build
41 | - uses: sersoft-gmbh/swift-coverage-action@main
42 | if: ${{ github.event_name == 'push' }}
43 | - uses: './'
44 | if: ${{ github.event_name == 'pull_request' }}
45 | - name: Check for produced coverage files
46 | run: | # check that the directory exists and contains files
47 | test -d '.swiftcov' && \
48 | test "$(find '.swiftcov' -name '*.lcov')" != ''
49 |
50 | test-customized:
51 | name: Test Customized Inputs
52 | strategy:
53 | matrix:
54 | os: [ macos-14, ubuntu-latest ]
55 | cov-format: [ 'txt', 'lcov' ]
56 | env:
57 | INPUT_DERIVED_DATA: .derived-data
58 | INPUT_SEARCH_PATHS: |
59 | __test__/TestProject/.build
60 | .derived-data
61 | INPUT_TARGET_NAME_FILTER: TestProject(1|Package).*
62 | INPUT_OUTPUT_FOLDER: .swiftcov-test
63 | runs-on: ${{ matrix.os }}
64 | container: ${{ matrix.os == 'ubuntu-latest' && 'swift:5.9' || '' }}
65 | steps:
66 | - uses: maxim-lobanov/setup-xcode@v1
67 | if: ${{ runner.os == 'macOS' }}
68 | with:
69 | xcode-version: ^15.0
70 | - uses: actions/checkout@v4
71 | - name: Generate action code
72 | if: ${{ github.event_name == 'pull_request' }}
73 | uses: ./.github/actions/generate-action-code
74 | - uses: sersoft-gmbh/xcodebuild-action@v3
75 | if: ${{ runner.os == 'macOS' }}
76 | with:
77 | spm-package: __test__/TestProject
78 | scheme: TestProject-Package
79 | destination: platform=macOS
80 | action: test
81 | enable-code-coverage: true
82 | parallel-testing-enabled: true
83 | derived-data-path: ${{ env.INPUT_DERIVED_DATA }}
84 | - run: swift test --parallel --enable-code-coverage
85 | working-directory: __test__/TestProject
86 | - uses: sersoft-gmbh/swift-coverage-action@main
87 | if: ${{ github.event_name == 'push' }}
88 | with:
89 | format: ${{ matrix.cov-format }}
90 | search-paths: ${{ env.INPUT_SEARCH_PATHS }}
91 | output: ${{ env.INPUT_OUTPUT_FOLDER }}
92 | target-name-filter: ${{ env.INPUT_TARGET_NAME_FILTER }}
93 | - uses: './'
94 | if: ${{ github.event_name == 'pull_request' }}
95 | with:
96 | format: ${{ matrix.cov-format }}
97 | search-paths: ${{ env.INPUT_SEARCH_PATHS }}
98 | output: ${{ env.INPUT_OUTPUT_FOLDER }}
99 | target-name-filter: ${{ env.INPUT_TARGET_NAME_FILTER }}
100 | - name: Check for produced coverage files
101 | env:
102 | RUNNER_OS: ${{ runner.os }}
103 | COV_FORMAT: ${{ matrix.cov-format }}
104 | run: | # check that the directory exists and contains files
105 | if [ ! -d "${INPUT_OUTPUT_FOLDER}" ]; then
106 | echo '::error::Output folder does not exist!'
107 | exit 1
108 | fi
109 | if [ "$(find "${INPUT_OUTPUT_FOLDER}" -name "TestProject2*.${COV_FORMAT}")" != '' ]; then
110 | echo '::error::Coverage files for incorrect project found!'
111 | exit 1
112 | fi
113 | if [ "${RUNNER_OS}" = 'macOS' ]; then
114 | if [ "$(find "${INPUT_OUTPUT_FOLDER}" -name "TestProject1*.${COV_FORMAT}")" = '' ]; then
115 | echo '::error::No coverage files found!'
116 | exit 1
117 | fi
118 | elif [ "${RUNNER_OS}" = 'Linux' ]; then
119 | if [ "$(find "${INPUT_OUTPUT_FOLDER}" -name "TestProjectPackage*.${COV_FORMAT}")" = '' ]; then
120 | echo '::error::No coverage files found!'
121 | exit 1
122 | fi
123 | else
124 | echo '::error::Unsupported OS!'
125 | exit 1
126 | fi
127 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | .idea/
4 |
5 | node_modules/
6 |
7 | # Lib is just temporary - so we ignore it
8 | lib/
9 |
10 | # Default and test output folder of coverage files generated by this action.
11 | .swiftcov/
12 | .swiftcov-test/
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift Coverage Conversion
2 |
3 | [](https://github.com/sersoft-gmbh/swift-coverage-action/actions/workflows/tests.yml)
4 |
5 | This action converts code coverage files from `swift test` or `xcodebuild` runs for processing with e.g. codecov.
6 | Note that this action does not run any test. Use `swift test`, `xcodebuild` or [xcodebuild-action](https://github.com/sersoft-gmbh/xcodebuild-action) for that.
7 |
8 | ## Inputs
9 |
10 | ### `search-paths`
11 |
12 | A list of search paths (one per line) that should be used for searching coverage data.
13 | Default:
14 | ```
15 | ./.build
16 | $HOME/Library/Developer/Xcode/DerivedData
17 | ```
18 |
19 | ### `output`
20 |
21 | The path to the output folder. Note that this folder will be deleted / overwritten by this action.
22 | You should probably put it in `.gitignore`.
23 | Default: `./.swiftcov`
24 |
25 | ### `format`
26 |
27 | The format to write the coverage files in. Can be 'lcov' or 'txt'.
28 | Default: `lcov`
29 |
30 | ### `target-name-filter`
31 |
32 | A regular expression that is used to filter coverage files by their target names.
33 |
34 | ### `ignore-conversion-failures`
35 |
36 | If `true`, conversion failures are ignored. If `fail-on-empty-output` is also set to `true`, the action might still fail if all conversions fail.
37 | Default: `'false'`
38 |
39 | ### `fail-on-empty-output`
40 |
41 | If `true`, the action fails if no coverage files were found (output is still set to an empty array).
42 | Default: `'false'`
43 |
44 | ## Outputs
45 |
46 | ### `files`
47 |
48 | The JSON encoded array of (absolute) file paths that were written. They are all contained inside the directory specified in the `output` input.
49 |
50 | ## Example Usage
51 |
52 | Use the following snippet after running tests with Swift or Xcode to convert those coverage files:
53 | ```yaml
54 | uses: sersoft-gmbh/swift-coverage-action@v4
55 | ```
56 |
57 | ### Codecov Action (v2 or later)
58 |
59 | To use this action together with [codecov/codecov-action](https://github.com/codecov/codecov-action), you need to convert the output to a comma separated string:
60 | ```yaml
61 | - uses: sersoft-gmbh/swift-coverage-action@v4
62 | id: coverage-files
63 | - uses: codecov/codecov-action@v3
64 | with:
65 | token: ${{ secrets.CODECOV_TOKEN }}
66 | files: ${{ join(fromJSON(steps.coverage-files.outputs.files), ',') }}
67 | ```
68 |
--------------------------------------------------------------------------------
/__test__/TestProject/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /.swiftpm
4 | /Packages
5 | /*.xcodeproj
6 | xcuserdata/
7 |
--------------------------------------------------------------------------------
/__test__/TestProject/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.6
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "TestProject",
8 | products: [
9 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
10 | .library(
11 | name: "TestProject1",
12 | targets: ["TestProject1"]),
13 | .library(
14 | name: "TestProject2",
15 | targets: ["TestProject2"]),
16 | .library(
17 | name: "TestProjectCombined",
18 | targets: ["TestProject1", "TestProject2"]),
19 | ],
20 | targets: [
21 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
22 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
23 | .target(name: "TestProject1"),
24 | .target(name: "TestProject2"),
25 | .testTarget(
26 | name: "TestProject1Tests",
27 | dependencies: ["TestProject1"]),
28 | .testTarget(
29 | name: "TestProject2Tests",
30 | dependencies: ["TestProject2"]),
31 | ]
32 | )
33 |
--------------------------------------------------------------------------------
/__test__/TestProject/Sources/TestProject1/MainObject.swift:
--------------------------------------------------------------------------------
1 | /// This is an exemplary enumeration.
2 | public enum SomeEnum: Equatable {
3 | /// The A case
4 | case a
5 | /// The B case
6 | case b
7 | /// The C case
8 | case c
9 |
10 | /// Returns whether self is equal to ``b``.
11 | public var isB: Bool { self == .b }
12 | }
13 |
14 | /// This is an exemplary final class.
15 | public final class SomeClass {
16 | /// Simply creates a new instance of this class.
17 | public init() {}
18 |
19 | /// This prints 'Hello' into the given stream.
20 | public func sayHello(to stream: inout S) {
21 | print("Hello", to: &stream)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/__test__/TestProject/Sources/TestProject2/SomeObject.swift:
--------------------------------------------------------------------------------
1 | /// This is an exemplary struct.
2 | public struct SomeObject: Hashable {
3 | /// The name of this struct.
4 | public let name: String
5 |
6 | /// Creates a new instance of this struct.
7 | /// - Parameter name: The name to use for the new instance.
8 | public init(name: String) {
9 | self.name = name
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/__test__/TestProject/Tests/TestProject1Tests/MainObjectTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import TestProject1
3 |
4 | final class MainObjectTests: XCTestCase {
5 | private struct Stream: TextOutputStream {
6 | private var _string = ""
7 |
8 | mutating func write(_ string: String) {
9 | _string += string
10 | }
11 |
12 | mutating func finalize() -> String {
13 | defer { _string = "" }
14 | return _string
15 | }
16 | }
17 |
18 | func testSomeEnum() throws {
19 | XCTAssertFalse(SomeEnum.a.isB)
20 | XCTAssertTrue(SomeEnum.b.isB)
21 | }
22 |
23 | func testSomeClass() throws {
24 | let cls = SomeClass()
25 | var stream = Stream()
26 | cls.sayHello(to: &stream)
27 | XCTAssertEqual(stream.finalize(), "Hello\n")
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/__test__/TestProject/Tests/TestProject2Tests/SomeObjectTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import TestProject2
3 |
4 | final class SomeObjectTests: XCTestCase {
5 | func testSomeObject() throws {
6 | XCTAssertEqual(SomeObject(name: "Test"), SomeObject(name: "Test"))
7 | XCTAssertNotEqual(SomeObject(name: "Test1"), SomeObject(name: "Test2"))
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: Swift Coverage Conversion
2 | description: Converts Swift / Xcode code coverage files for processing with e.g. codecov.
3 | author: ser.soft GmbH
4 | inputs:
5 | search-paths:
6 | description: A list of search paths (one per line) that should be used for searching coverage data.
7 | required: true
8 | default: |
9 | ./.build
10 | $HOME/Library/Developer/Xcode/DerivedData
11 | output:
12 | description: The path to the output folder to put the converted coverage files in.
13 | required: true
14 | default: './.swiftcov'
15 | format:
16 | description: The format to write the coverage files in. Can be 'lcov' or 'txt'.
17 | required: true
18 | default: 'lcov'
19 | target-name-filter:
20 | description: A regular expression that is used to filter coverage files by their target names.
21 | required: false
22 | ignore-conversion-failures:
23 | description: If `true`, conversion failures are ignored. If `fail-on-empty-output` is also set to `true`, the action might still fail if all conversions fail.
24 | required: true
25 | default: 'false'
26 | fail-on-empty-output:
27 | description: If `true`, the action fails if no coverage files were found (output is still set to an empty array).
28 | required: true
29 | default: 'false'
30 | outputs:
31 | files:
32 | description: The JSON-encoded array of (absolute) file paths that were converted.
33 | runs:
34 | using: node20
35 | main: dist/index.js
36 | branding:
37 | color: gray-dark
38 | icon: refresh-cw
39 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | /******/ (() => { // webpackBootstrap
2 | /******/ var __webpack_modules__ = ({
3 |
4 | /***/ 915:
5 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
6 |
7 | "use strict";
8 |
9 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | var desc = Object.getOwnPropertyDescriptor(m, k);
12 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13 | desc = { enumerable: true, get: function() { return m[k]; } };
14 | }
15 | Object.defineProperty(o, k2, desc);
16 | }) : (function(o, m, k, k2) {
17 | if (k2 === undefined) k2 = k;
18 | o[k2] = m[k];
19 | }));
20 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21 | Object.defineProperty(o, "default", { enumerable: true, value: v });
22 | }) : function(o, v) {
23 | o["default"] = v;
24 | });
25 | var __importStar = (this && this.__importStar) || (function () {
26 | var ownKeys = function(o) {
27 | ownKeys = Object.getOwnPropertyNames || function (o) {
28 | var ar = [];
29 | for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30 | return ar;
31 | };
32 | return ownKeys(o);
33 | };
34 | return function (mod) {
35 | if (mod && mod.__esModule) return mod;
36 | var result = {};
37 | if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38 | __setModuleDefault(result, mod);
39 | return result;
40 | };
41 | })();
42 | Object.defineProperty(exports, "__esModule", ({ value: true }));
43 | const core = __importStar(__nccwpck_require__(484));
44 | const exec_1 = __nccwpck_require__(236);
45 | const io = __importStar(__nccwpck_require__(994));
46 | const fs_1 = __nccwpck_require__(896);
47 | const path = __importStar(__nccwpck_require__(928));
48 | const os = __importStar(__nccwpck_require__(857));
49 | async function runCmd(cmd, ...args) {
50 | const output = await (0, exec_1.getExecOutput)(cmd, args.length <= 0 ? undefined : args, { silent: !core.isDebug() });
51 | if (output.stderr.length > 0)
52 | core.warning(`Command execution wrote lines to stderr:\n${output.stderr}`);
53 | return output.stdout;
54 | }
55 | var CovFormat;
56 | (function (CovFormat) {
57 | CovFormat["txt"] = "txt";
58 | CovFormat["lcov"] = "lcov";
59 | })(CovFormat || (CovFormat = {}));
60 | // Taken and adjusted from https://stackoverflow.com/a/65415138/1388842
61 | async function* walk(dir, onlyFiles = true) {
62 | const entries = await fs_1.promises.readdir(dir, { withFileTypes: true });
63 | for (const entry of entries) {
64 | const res = path.resolve(dir, entry.name);
65 | if (entry.isDirectory()) {
66 | let skipDesc = false;
67 | if (!onlyFiles)
68 | yield { path: res, isDirectory: true, skipDescendants: () => skipDesc = true };
69 | if (!skipDesc)
70 | yield* walk(res, onlyFiles);
71 | }
72 | else {
73 | yield { path: res, isDirectory: false, skipDescendants: () => { } };
74 | }
75 | }
76 | }
77 | async function directoryExists(path) {
78 | if (!(0, fs_1.existsSync)(path))
79 | return false;
80 | const stat = await fs_1.promises.stat(path);
81 | return stat.isDirectory();
82 | }
83 | async function fileExists(path) {
84 | if (!(0, fs_1.existsSync)(path))
85 | return false;
86 | const stat = await fs_1.promises.stat(path);
87 | return stat.isFile();
88 | }
89 | async function main() {
90 | switch (process.platform) {
91 | case 'darwin': break;
92 | case 'linux': break;
93 | default: throw new Error('This action only supports macOS and Linux!');
94 | }
95 | core.startGroup('Validating input');
96 | const searchPaths = core.getMultilineInput('search-paths', { required: true })
97 | .map(p => path.resolve(p.replace(/(~|\$HOME|\${HOME})/g, os.homedir)));
98 | const outputFolder = path.resolve(core.getInput('output', { required: true })
99 | .replace(/(~|\$HOME|\${HOME})/g, os.homedir));
100 | const _format = core.getInput('format', { required: true });
101 | const format = CovFormat[_format];
102 | if (!format)
103 | throw new Error(`Invalid format: ${_format}`);
104 | const _targetNameFilter = core.getInput('target-name-filter');
105 | const targetNameFilter = _targetNameFilter ? new RegExp(_targetNameFilter) : null;
106 | const ignoreConversionFailures = core.getBooleanInput('ignore-conversion-failures');
107 | const failOnEmptyOutput = core.getBooleanInput('fail-on-empty-output');
108 | core.endGroup();
109 | await core.group('Setting up paths', async () => {
110 | await io.rmRF(outputFolder);
111 | await io.mkdirP(outputFolder);
112 | });
113 | const profDataFiles = await core.group('Finding coverage files', async () => {
114 | let profDataFiles = [];
115 | for (const searchPath of searchPaths) {
116 | if (!await directoryExists(searchPath)) {
117 | core.info(`Skipping non-existent search path ${searchPath}...`);
118 | continue;
119 | }
120 | for await (const entry of walk(searchPath, true)) {
121 | if (/.*\.profdata$/.test(entry.path)) {
122 | profDataFiles.push(entry.path);
123 | core.debug(`Found profdata file: ${entry.path}`);
124 | }
125 | }
126 | }
127 | core.info(`Found ${profDataFiles.length} profiling data file(s):\n${profDataFiles.join('\n')}`);
128 | return profDataFiles;
129 | });
130 | let convertedFiles = [];
131 | if (profDataFiles.length > 0) {
132 | convertedFiles = await core.group('Converting files', async () => {
133 | let outFiles = [];
134 | let conversionFailures = [];
135 | let processedTargets = new Set();
136 | for (const profDataFile of profDataFiles) {
137 | const profDataDir = path.dirname(profDataFile);
138 | const xcodeRegex = /(Build).*/;
139 | let buildDir;
140 | let isXcode;
141 | if (xcodeRegex.test(profDataDir)) {
142 | buildDir = profDataDir.replace(xcodeRegex, '$1');
143 | isXcode = true;
144 | }
145 | else { // SPM
146 | buildDir = path.dirname(profDataDir);
147 | isXcode = false;
148 | }
149 | core.debug(`Checking contents of build dir ${buildDir} of prof data file ${profDataFile}`);
150 | for await (const entry of walk(buildDir, false)) {
151 | const typesRegex = /.*\.(app|framework|xctest)$/;
152 | if (!typesRegex.test(entry.path))
153 | continue;
154 | entry.skipDescendants(); // Don't process any further files inside this container.
155 | if (isXcode && !/\/Build[^/]*\/Products\//.test(entry.path)) {
156 | core.info(`Skipping ${entry.path} because it is not in a Xcode build products directory...`);
157 | continue;
158 | }
159 | const type = entry.path.replace(typesRegex, '$1');
160 | core.debug(`Found match of type ${type}: ${entry.path}`);
161 | const proj = entry.path
162 | .replace(/.*\//, '')
163 | .replace(`.${type}`, '');
164 | core.debug(`Project name: ${proj}`);
165 | if (processedTargets.has(`${proj}.${type}`)) {
166 | core.info(`Skipping ${proj} with type ${type} because it has already been converted...`);
167 | continue;
168 | }
169 | if (targetNameFilter && !targetNameFilter.test(proj)) {
170 | core.info(`Skipping ${proj} due to target name filter...`);
171 | continue;
172 | }
173 | let dest;
174 | let cmd;
175 | let args;
176 | if (process.platform === 'darwin') {
177 | dest = path.join(entry.path, proj);
178 | if (!await fileExists(dest)) {
179 | const macOSPath = path.join(entry.path, 'Contents', 'MacOS');
180 | dest = path.join(macOSPath, proj);
181 | if (!await fileExists(dest)) {
182 | // Try again with whitespaces removed.
183 | dest = path.join(macOSPath, proj.replace(' ', ''));
184 | }
185 | if (!await fileExists(dest)) {
186 | core.warning(`Couldn't find a suitable target file in ${entry.path}. Using the path itself...`);
187 | dest = entry.path;
188 | }
189 | }
190 | cmd = 'xcrun';
191 | args = ['llvm-cov'];
192 | }
193 | else {
194 | dest = entry.path;
195 | cmd = 'llvm-cov';
196 | args = [];
197 | }
198 | let fileEnding;
199 | switch (format) {
200 | case CovFormat.txt:
201 | args.push('show');
202 | fileEnding = 'txt';
203 | break;
204 | case CovFormat.lcov:
205 | args.push('export', '-format=lcov');
206 | fileEnding = 'lcov';
207 | break;
208 | }
209 | args.push('-instr-profile', profDataFile, dest);
210 | let converted;
211 | try {
212 | converted = await runCmd(cmd, ...args);
213 | }
214 | catch (error) {
215 | const msg = `Failed to convert ${dest}: ${error}`;
216 | if (error instanceof Error)
217 | conversionFailures.push(error);
218 | else
219 | conversionFailures.push(new Error(msg));
220 | if (ignoreConversionFailures)
221 | core.info(msg);
222 | else
223 | core.error(msg);
224 | continue;
225 | }
226 | const projFileName = proj.replace(/\s/g, '');
227 | const outFile = path.join(outputFolder, `${projFileName}.${type}.coverage.${fileEnding}`);
228 | core.debug(`Writing coverage report to ${outFile}`);
229 | await fs_1.promises.writeFile(outFile, converted);
230 | outFiles.push(outFile);
231 | processedTargets.add(`${proj}.${type}`);
232 | }
233 | }
234 | if (conversionFailures.length > 0) {
235 | if (ignoreConversionFailures)
236 | core.info(`Failed to convert ${conversionFailures.length} file(s)...`);
237 | else
238 | throw new Error('Conversion failures:\n' + conversionFailures.map(e => e.toString()).join('\n'));
239 | }
240 | core.info(`Processed ${outFiles.length} file(s):\n${outFiles.join('\n')}`);
241 | return outFiles;
242 | });
243 | }
244 | core.setOutput('files', JSON.stringify(convertedFiles));
245 | if (convertedFiles.length <= 0 && failOnEmptyOutput)
246 | throw new Error('No coverage files found (or none succeeded to convert)!');
247 | }
248 | try {
249 | main().catch(error => core.setFailed(error.message));
250 | }
251 | catch (error) {
252 | core.setFailed(error.message);
253 | }
254 |
255 |
256 | /***/ }),
257 |
258 | /***/ 914:
259 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
260 |
261 | "use strict";
262 |
263 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
264 | if (k2 === undefined) k2 = k;
265 | var desc = Object.getOwnPropertyDescriptor(m, k);
266 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
267 | desc = { enumerable: true, get: function() { return m[k]; } };
268 | }
269 | Object.defineProperty(o, k2, desc);
270 | }) : (function(o, m, k, k2) {
271 | if (k2 === undefined) k2 = k;
272 | o[k2] = m[k];
273 | }));
274 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
275 | Object.defineProperty(o, "default", { enumerable: true, value: v });
276 | }) : function(o, v) {
277 | o["default"] = v;
278 | });
279 | var __importStar = (this && this.__importStar) || function (mod) {
280 | if (mod && mod.__esModule) return mod;
281 | var result = {};
282 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
283 | __setModuleDefault(result, mod);
284 | return result;
285 | };
286 | Object.defineProperty(exports, "__esModule", ({ value: true }));
287 | exports.issue = exports.issueCommand = void 0;
288 | const os = __importStar(__nccwpck_require__(857));
289 | const utils_1 = __nccwpck_require__(302);
290 | /**
291 | * Commands
292 | *
293 | * Command Format:
294 | * ::name key=value,key=value::message
295 | *
296 | * Examples:
297 | * ::warning::This is the message
298 | * ::set-env name=MY_VAR::some value
299 | */
300 | function issueCommand(command, properties, message) {
301 | const cmd = new Command(command, properties, message);
302 | process.stdout.write(cmd.toString() + os.EOL);
303 | }
304 | exports.issueCommand = issueCommand;
305 | function issue(name, message = '') {
306 | issueCommand(name, {}, message);
307 | }
308 | exports.issue = issue;
309 | const CMD_STRING = '::';
310 | class Command {
311 | constructor(command, properties, message) {
312 | if (!command) {
313 | command = 'missing.command';
314 | }
315 | this.command = command;
316 | this.properties = properties;
317 | this.message = message;
318 | }
319 | toString() {
320 | let cmdStr = CMD_STRING + this.command;
321 | if (this.properties && Object.keys(this.properties).length > 0) {
322 | cmdStr += ' ';
323 | let first = true;
324 | for (const key in this.properties) {
325 | if (this.properties.hasOwnProperty(key)) {
326 | const val = this.properties[key];
327 | if (val) {
328 | if (first) {
329 | first = false;
330 | }
331 | else {
332 | cmdStr += ',';
333 | }
334 | cmdStr += `${key}=${escapeProperty(val)}`;
335 | }
336 | }
337 | }
338 | }
339 | cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
340 | return cmdStr;
341 | }
342 | }
343 | function escapeData(s) {
344 | return (0, utils_1.toCommandValue)(s)
345 | .replace(/%/g, '%25')
346 | .replace(/\r/g, '%0D')
347 | .replace(/\n/g, '%0A');
348 | }
349 | function escapeProperty(s) {
350 | return (0, utils_1.toCommandValue)(s)
351 | .replace(/%/g, '%25')
352 | .replace(/\r/g, '%0D')
353 | .replace(/\n/g, '%0A')
354 | .replace(/:/g, '%3A')
355 | .replace(/,/g, '%2C');
356 | }
357 | //# sourceMappingURL=command.js.map
358 |
359 | /***/ }),
360 |
361 | /***/ 484:
362 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
363 |
364 | "use strict";
365 |
366 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
367 | if (k2 === undefined) k2 = k;
368 | var desc = Object.getOwnPropertyDescriptor(m, k);
369 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
370 | desc = { enumerable: true, get: function() { return m[k]; } };
371 | }
372 | Object.defineProperty(o, k2, desc);
373 | }) : (function(o, m, k, k2) {
374 | if (k2 === undefined) k2 = k;
375 | o[k2] = m[k];
376 | }));
377 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
378 | Object.defineProperty(o, "default", { enumerable: true, value: v });
379 | }) : function(o, v) {
380 | o["default"] = v;
381 | });
382 | var __importStar = (this && this.__importStar) || function (mod) {
383 | if (mod && mod.__esModule) return mod;
384 | var result = {};
385 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
386 | __setModuleDefault(result, mod);
387 | return result;
388 | };
389 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
390 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
391 | return new (P || (P = Promise))(function (resolve, reject) {
392 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
393 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
394 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
395 | step((generator = generator.apply(thisArg, _arguments || [])).next());
396 | });
397 | };
398 | Object.defineProperty(exports, "__esModule", ({ value: true }));
399 | exports.platform = exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = exports.markdownSummary = exports.summary = exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0;
400 | const command_1 = __nccwpck_require__(914);
401 | const file_command_1 = __nccwpck_require__(753);
402 | const utils_1 = __nccwpck_require__(302);
403 | const os = __importStar(__nccwpck_require__(857));
404 | const path = __importStar(__nccwpck_require__(928));
405 | const oidc_utils_1 = __nccwpck_require__(306);
406 | /**
407 | * The code to exit an action
408 | */
409 | var ExitCode;
410 | (function (ExitCode) {
411 | /**
412 | * A code indicating that the action was successful
413 | */
414 | ExitCode[ExitCode["Success"] = 0] = "Success";
415 | /**
416 | * A code indicating that the action was a failure
417 | */
418 | ExitCode[ExitCode["Failure"] = 1] = "Failure";
419 | })(ExitCode || (exports.ExitCode = ExitCode = {}));
420 | //-----------------------------------------------------------------------
421 | // Variables
422 | //-----------------------------------------------------------------------
423 | /**
424 | * Sets env variable for this action and future actions in the job
425 | * @param name the name of the variable to set
426 | * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
427 | */
428 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
429 | function exportVariable(name, val) {
430 | const convertedVal = (0, utils_1.toCommandValue)(val);
431 | process.env[name] = convertedVal;
432 | const filePath = process.env['GITHUB_ENV'] || '';
433 | if (filePath) {
434 | return (0, file_command_1.issueFileCommand)('ENV', (0, file_command_1.prepareKeyValueMessage)(name, val));
435 | }
436 | (0, command_1.issueCommand)('set-env', { name }, convertedVal);
437 | }
438 | exports.exportVariable = exportVariable;
439 | /**
440 | * Registers a secret which will get masked from logs
441 | * @param secret value of the secret
442 | */
443 | function setSecret(secret) {
444 | (0, command_1.issueCommand)('add-mask', {}, secret);
445 | }
446 | exports.setSecret = setSecret;
447 | /**
448 | * Prepends inputPath to the PATH (for this action and future actions)
449 | * @param inputPath
450 | */
451 | function addPath(inputPath) {
452 | const filePath = process.env['GITHUB_PATH'] || '';
453 | if (filePath) {
454 | (0, file_command_1.issueFileCommand)('PATH', inputPath);
455 | }
456 | else {
457 | (0, command_1.issueCommand)('add-path', {}, inputPath);
458 | }
459 | process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
460 | }
461 | exports.addPath = addPath;
462 | /**
463 | * Gets the value of an input.
464 | * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed.
465 | * Returns an empty string if the value is not defined.
466 | *
467 | * @param name name of the input to get
468 | * @param options optional. See InputOptions.
469 | * @returns string
470 | */
471 | function getInput(name, options) {
472 | const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
473 | if (options && options.required && !val) {
474 | throw new Error(`Input required and not supplied: ${name}`);
475 | }
476 | if (options && options.trimWhitespace === false) {
477 | return val;
478 | }
479 | return val.trim();
480 | }
481 | exports.getInput = getInput;
482 | /**
483 | * Gets the values of an multiline input. Each value is also trimmed.
484 | *
485 | * @param name name of the input to get
486 | * @param options optional. See InputOptions.
487 | * @returns string[]
488 | *
489 | */
490 | function getMultilineInput(name, options) {
491 | const inputs = getInput(name, options)
492 | .split('\n')
493 | .filter(x => x !== '');
494 | if (options && options.trimWhitespace === false) {
495 | return inputs;
496 | }
497 | return inputs.map(input => input.trim());
498 | }
499 | exports.getMultilineInput = getMultilineInput;
500 | /**
501 | * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification.
502 | * Support boolean input list: `true | True | TRUE | false | False | FALSE` .
503 | * The return value is also in boolean type.
504 | * ref: https://yaml.org/spec/1.2/spec.html#id2804923
505 | *
506 | * @param name name of the input to get
507 | * @param options optional. See InputOptions.
508 | * @returns boolean
509 | */
510 | function getBooleanInput(name, options) {
511 | const trueValue = ['true', 'True', 'TRUE'];
512 | const falseValue = ['false', 'False', 'FALSE'];
513 | const val = getInput(name, options);
514 | if (trueValue.includes(val))
515 | return true;
516 | if (falseValue.includes(val))
517 | return false;
518 | throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
519 | `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
520 | }
521 | exports.getBooleanInput = getBooleanInput;
522 | /**
523 | * Sets the value of an output.
524 | *
525 | * @param name name of the output to set
526 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify
527 | */
528 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
529 | function setOutput(name, value) {
530 | const filePath = process.env['GITHUB_OUTPUT'] || '';
531 | if (filePath) {
532 | return (0, file_command_1.issueFileCommand)('OUTPUT', (0, file_command_1.prepareKeyValueMessage)(name, value));
533 | }
534 | process.stdout.write(os.EOL);
535 | (0, command_1.issueCommand)('set-output', { name }, (0, utils_1.toCommandValue)(value));
536 | }
537 | exports.setOutput = setOutput;
538 | /**
539 | * Enables or disables the echoing of commands into stdout for the rest of the step.
540 | * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
541 | *
542 | */
543 | function setCommandEcho(enabled) {
544 | (0, command_1.issue)('echo', enabled ? 'on' : 'off');
545 | }
546 | exports.setCommandEcho = setCommandEcho;
547 | //-----------------------------------------------------------------------
548 | // Results
549 | //-----------------------------------------------------------------------
550 | /**
551 | * Sets the action status to failed.
552 | * When the action exits it will be with an exit code of 1
553 | * @param message add error issue message
554 | */
555 | function setFailed(message) {
556 | process.exitCode = ExitCode.Failure;
557 | error(message);
558 | }
559 | exports.setFailed = setFailed;
560 | //-----------------------------------------------------------------------
561 | // Logging Commands
562 | //-----------------------------------------------------------------------
563 | /**
564 | * Gets whether Actions Step Debug is on or not
565 | */
566 | function isDebug() {
567 | return process.env['RUNNER_DEBUG'] === '1';
568 | }
569 | exports.isDebug = isDebug;
570 | /**
571 | * Writes debug message to user log
572 | * @param message debug message
573 | */
574 | function debug(message) {
575 | (0, command_1.issueCommand)('debug', {}, message);
576 | }
577 | exports.debug = debug;
578 | /**
579 | * Adds an error issue
580 | * @param message error issue message. Errors will be converted to string via toString()
581 | * @param properties optional properties to add to the annotation.
582 | */
583 | function error(message, properties = {}) {
584 | (0, command_1.issueCommand)('error', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
585 | }
586 | exports.error = error;
587 | /**
588 | * Adds a warning issue
589 | * @param message warning issue message. Errors will be converted to string via toString()
590 | * @param properties optional properties to add to the annotation.
591 | */
592 | function warning(message, properties = {}) {
593 | (0, command_1.issueCommand)('warning', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
594 | }
595 | exports.warning = warning;
596 | /**
597 | * Adds a notice issue
598 | * @param message notice issue message. Errors will be converted to string via toString()
599 | * @param properties optional properties to add to the annotation.
600 | */
601 | function notice(message, properties = {}) {
602 | (0, command_1.issueCommand)('notice', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
603 | }
604 | exports.notice = notice;
605 | /**
606 | * Writes info to log with console.log.
607 | * @param message info message
608 | */
609 | function info(message) {
610 | process.stdout.write(message + os.EOL);
611 | }
612 | exports.info = info;
613 | /**
614 | * Begin an output group.
615 | *
616 | * Output until the next `groupEnd` will be foldable in this group
617 | *
618 | * @param name The name of the output group
619 | */
620 | function startGroup(name) {
621 | (0, command_1.issue)('group', name);
622 | }
623 | exports.startGroup = startGroup;
624 | /**
625 | * End an output group.
626 | */
627 | function endGroup() {
628 | (0, command_1.issue)('endgroup');
629 | }
630 | exports.endGroup = endGroup;
631 | /**
632 | * Wrap an asynchronous function call in a group.
633 | *
634 | * Returns the same type as the function itself.
635 | *
636 | * @param name The name of the group
637 | * @param fn The function to wrap in the group
638 | */
639 | function group(name, fn) {
640 | return __awaiter(this, void 0, void 0, function* () {
641 | startGroup(name);
642 | let result;
643 | try {
644 | result = yield fn();
645 | }
646 | finally {
647 | endGroup();
648 | }
649 | return result;
650 | });
651 | }
652 | exports.group = group;
653 | //-----------------------------------------------------------------------
654 | // Wrapper action state
655 | //-----------------------------------------------------------------------
656 | /**
657 | * Saves state for current action, the state can only be retrieved by this action's post job execution.
658 | *
659 | * @param name name of the state to store
660 | * @param value value to store. Non-string values will be converted to a string via JSON.stringify
661 | */
662 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
663 | function saveState(name, value) {
664 | const filePath = process.env['GITHUB_STATE'] || '';
665 | if (filePath) {
666 | return (0, file_command_1.issueFileCommand)('STATE', (0, file_command_1.prepareKeyValueMessage)(name, value));
667 | }
668 | (0, command_1.issueCommand)('save-state', { name }, (0, utils_1.toCommandValue)(value));
669 | }
670 | exports.saveState = saveState;
671 | /**
672 | * Gets the value of an state set by this action's main execution.
673 | *
674 | * @param name name of the state to get
675 | * @returns string
676 | */
677 | function getState(name) {
678 | return process.env[`STATE_${name}`] || '';
679 | }
680 | exports.getState = getState;
681 | function getIDToken(aud) {
682 | return __awaiter(this, void 0, void 0, function* () {
683 | return yield oidc_utils_1.OidcClient.getIDToken(aud);
684 | });
685 | }
686 | exports.getIDToken = getIDToken;
687 | /**
688 | * Summary exports
689 | */
690 | var summary_1 = __nccwpck_require__(847);
691 | Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } }));
692 | /**
693 | * @deprecated use core.summary
694 | */
695 | var summary_2 = __nccwpck_require__(847);
696 | Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } }));
697 | /**
698 | * Path exports
699 | */
700 | var path_utils_1 = __nccwpck_require__(976);
701 | Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } }));
702 | Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } }));
703 | Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } }));
704 | /**
705 | * Platform utilities exports
706 | */
707 | exports.platform = __importStar(__nccwpck_require__(968));
708 | //# sourceMappingURL=core.js.map
709 |
710 | /***/ }),
711 |
712 | /***/ 753:
713 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
714 |
715 | "use strict";
716 |
717 | // For internal use, subject to change.
718 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
719 | if (k2 === undefined) k2 = k;
720 | var desc = Object.getOwnPropertyDescriptor(m, k);
721 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
722 | desc = { enumerable: true, get: function() { return m[k]; } };
723 | }
724 | Object.defineProperty(o, k2, desc);
725 | }) : (function(o, m, k, k2) {
726 | if (k2 === undefined) k2 = k;
727 | o[k2] = m[k];
728 | }));
729 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
730 | Object.defineProperty(o, "default", { enumerable: true, value: v });
731 | }) : function(o, v) {
732 | o["default"] = v;
733 | });
734 | var __importStar = (this && this.__importStar) || function (mod) {
735 | if (mod && mod.__esModule) return mod;
736 | var result = {};
737 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
738 | __setModuleDefault(result, mod);
739 | return result;
740 | };
741 | Object.defineProperty(exports, "__esModule", ({ value: true }));
742 | exports.prepareKeyValueMessage = exports.issueFileCommand = void 0;
743 | // We use any as a valid input type
744 | /* eslint-disable @typescript-eslint/no-explicit-any */
745 | const crypto = __importStar(__nccwpck_require__(982));
746 | const fs = __importStar(__nccwpck_require__(896));
747 | const os = __importStar(__nccwpck_require__(857));
748 | const utils_1 = __nccwpck_require__(302);
749 | function issueFileCommand(command, message) {
750 | const filePath = process.env[`GITHUB_${command}`];
751 | if (!filePath) {
752 | throw new Error(`Unable to find environment variable for file command ${command}`);
753 | }
754 | if (!fs.existsSync(filePath)) {
755 | throw new Error(`Missing file at path: ${filePath}`);
756 | }
757 | fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, {
758 | encoding: 'utf8'
759 | });
760 | }
761 | exports.issueFileCommand = issueFileCommand;
762 | function prepareKeyValueMessage(key, value) {
763 | const delimiter = `ghadelimiter_${crypto.randomUUID()}`;
764 | const convertedValue = (0, utils_1.toCommandValue)(value);
765 | // These should realistically never happen, but just in case someone finds a
766 | // way to exploit uuid generation let's not allow keys or values that contain
767 | // the delimiter.
768 | if (key.includes(delimiter)) {
769 | throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
770 | }
771 | if (convertedValue.includes(delimiter)) {
772 | throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
773 | }
774 | return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;
775 | }
776 | exports.prepareKeyValueMessage = prepareKeyValueMessage;
777 | //# sourceMappingURL=file-command.js.map
778 |
779 | /***/ }),
780 |
781 | /***/ 306:
782 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
783 |
784 | "use strict";
785 |
786 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
787 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
788 | return new (P || (P = Promise))(function (resolve, reject) {
789 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
790 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
791 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
792 | step((generator = generator.apply(thisArg, _arguments || [])).next());
793 | });
794 | };
795 | Object.defineProperty(exports, "__esModule", ({ value: true }));
796 | exports.OidcClient = void 0;
797 | const http_client_1 = __nccwpck_require__(844);
798 | const auth_1 = __nccwpck_require__(552);
799 | const core_1 = __nccwpck_require__(484);
800 | class OidcClient {
801 | static createHttpClient(allowRetry = true, maxRetry = 10) {
802 | const requestOptions = {
803 | allowRetries: allowRetry,
804 | maxRetries: maxRetry
805 | };
806 | return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions);
807 | }
808 | static getRequestToken() {
809 | const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'];
810 | if (!token) {
811 | throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable');
812 | }
813 | return token;
814 | }
815 | static getIDTokenUrl() {
816 | const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL'];
817 | if (!runtimeUrl) {
818 | throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable');
819 | }
820 | return runtimeUrl;
821 | }
822 | static getCall(id_token_url) {
823 | var _a;
824 | return __awaiter(this, void 0, void 0, function* () {
825 | const httpclient = OidcClient.createHttpClient();
826 | const res = yield httpclient
827 | .getJson(id_token_url)
828 | .catch(error => {
829 | throw new Error(`Failed to get ID Token. \n
830 | Error Code : ${error.statusCode}\n
831 | Error Message: ${error.message}`);
832 | });
833 | const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value;
834 | if (!id_token) {
835 | throw new Error('Response json body do not have ID Token field');
836 | }
837 | return id_token;
838 | });
839 | }
840 | static getIDToken(audience) {
841 | return __awaiter(this, void 0, void 0, function* () {
842 | try {
843 | // New ID Token is requested from action service
844 | let id_token_url = OidcClient.getIDTokenUrl();
845 | if (audience) {
846 | const encodedAudience = encodeURIComponent(audience);
847 | id_token_url = `${id_token_url}&audience=${encodedAudience}`;
848 | }
849 | (0, core_1.debug)(`ID token url is ${id_token_url}`);
850 | const id_token = yield OidcClient.getCall(id_token_url);
851 | (0, core_1.setSecret)(id_token);
852 | return id_token;
853 | }
854 | catch (error) {
855 | throw new Error(`Error message: ${error.message}`);
856 | }
857 | });
858 | }
859 | }
860 | exports.OidcClient = OidcClient;
861 | //# sourceMappingURL=oidc-utils.js.map
862 |
863 | /***/ }),
864 |
865 | /***/ 976:
866 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
867 |
868 | "use strict";
869 |
870 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
871 | if (k2 === undefined) k2 = k;
872 | var desc = Object.getOwnPropertyDescriptor(m, k);
873 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
874 | desc = { enumerable: true, get: function() { return m[k]; } };
875 | }
876 | Object.defineProperty(o, k2, desc);
877 | }) : (function(o, m, k, k2) {
878 | if (k2 === undefined) k2 = k;
879 | o[k2] = m[k];
880 | }));
881 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
882 | Object.defineProperty(o, "default", { enumerable: true, value: v });
883 | }) : function(o, v) {
884 | o["default"] = v;
885 | });
886 | var __importStar = (this && this.__importStar) || function (mod) {
887 | if (mod && mod.__esModule) return mod;
888 | var result = {};
889 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
890 | __setModuleDefault(result, mod);
891 | return result;
892 | };
893 | Object.defineProperty(exports, "__esModule", ({ value: true }));
894 | exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;
895 | const path = __importStar(__nccwpck_require__(928));
896 | /**
897 | * toPosixPath converts the given path to the posix form. On Windows, \\ will be
898 | * replaced with /.
899 | *
900 | * @param pth. Path to transform.
901 | * @return string Posix path.
902 | */
903 | function toPosixPath(pth) {
904 | return pth.replace(/[\\]/g, '/');
905 | }
906 | exports.toPosixPath = toPosixPath;
907 | /**
908 | * toWin32Path converts the given path to the win32 form. On Linux, / will be
909 | * replaced with \\.
910 | *
911 | * @param pth. Path to transform.
912 | * @return string Win32 path.
913 | */
914 | function toWin32Path(pth) {
915 | return pth.replace(/[/]/g, '\\');
916 | }
917 | exports.toWin32Path = toWin32Path;
918 | /**
919 | * toPlatformPath converts the given path to a platform-specific path. It does
920 | * this by replacing instances of / and \ with the platform-specific path
921 | * separator.
922 | *
923 | * @param pth The path to platformize.
924 | * @return string The platform-specific path.
925 | */
926 | function toPlatformPath(pth) {
927 | return pth.replace(/[/\\]/g, path.sep);
928 | }
929 | exports.toPlatformPath = toPlatformPath;
930 | //# sourceMappingURL=path-utils.js.map
931 |
932 | /***/ }),
933 |
934 | /***/ 968:
935 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
936 |
937 | "use strict";
938 |
939 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
940 | if (k2 === undefined) k2 = k;
941 | var desc = Object.getOwnPropertyDescriptor(m, k);
942 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
943 | desc = { enumerable: true, get: function() { return m[k]; } };
944 | }
945 | Object.defineProperty(o, k2, desc);
946 | }) : (function(o, m, k, k2) {
947 | if (k2 === undefined) k2 = k;
948 | o[k2] = m[k];
949 | }));
950 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
951 | Object.defineProperty(o, "default", { enumerable: true, value: v });
952 | }) : function(o, v) {
953 | o["default"] = v;
954 | });
955 | var __importStar = (this && this.__importStar) || function (mod) {
956 | if (mod && mod.__esModule) return mod;
957 | var result = {};
958 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
959 | __setModuleDefault(result, mod);
960 | return result;
961 | };
962 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
963 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
964 | return new (P || (P = Promise))(function (resolve, reject) {
965 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
966 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
967 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
968 | step((generator = generator.apply(thisArg, _arguments || [])).next());
969 | });
970 | };
971 | var __importDefault = (this && this.__importDefault) || function (mod) {
972 | return (mod && mod.__esModule) ? mod : { "default": mod };
973 | };
974 | Object.defineProperty(exports, "__esModule", ({ value: true }));
975 | exports.getDetails = exports.isLinux = exports.isMacOS = exports.isWindows = exports.arch = exports.platform = void 0;
976 | const os_1 = __importDefault(__nccwpck_require__(857));
977 | const exec = __importStar(__nccwpck_require__(236));
978 | const getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () {
979 | const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, {
980 | silent: true
981 | });
982 | const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, {
983 | silent: true
984 | });
985 | return {
986 | name: name.trim(),
987 | version: version.trim()
988 | };
989 | });
990 | const getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () {
991 | var _a, _b, _c, _d;
992 | const { stdout } = yield exec.getExecOutput('sw_vers', undefined, {
993 | silent: true
994 | });
995 | const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : '';
996 | const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : '';
997 | return {
998 | name,
999 | version
1000 | };
1001 | });
1002 | const getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () {
1003 | const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], {
1004 | silent: true
1005 | });
1006 | const [name, version] = stdout.trim().split('\n');
1007 | return {
1008 | name,
1009 | version
1010 | };
1011 | });
1012 | exports.platform = os_1.default.platform();
1013 | exports.arch = os_1.default.arch();
1014 | exports.isWindows = exports.platform === 'win32';
1015 | exports.isMacOS = exports.platform === 'darwin';
1016 | exports.isLinux = exports.platform === 'linux';
1017 | function getDetails() {
1018 | return __awaiter(this, void 0, void 0, function* () {
1019 | return Object.assign(Object.assign({}, (yield (exports.isWindows
1020 | ? getWindowsInfo()
1021 | : exports.isMacOS
1022 | ? getMacOsInfo()
1023 | : getLinuxInfo()))), { platform: exports.platform,
1024 | arch: exports.arch,
1025 | isWindows: exports.isWindows,
1026 | isMacOS: exports.isMacOS,
1027 | isLinux: exports.isLinux });
1028 | });
1029 | }
1030 | exports.getDetails = getDetails;
1031 | //# sourceMappingURL=platform.js.map
1032 |
1033 | /***/ }),
1034 |
1035 | /***/ 847:
1036 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
1037 |
1038 | "use strict";
1039 |
1040 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1041 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1042 | return new (P || (P = Promise))(function (resolve, reject) {
1043 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1044 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1045 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1046 | step((generator = generator.apply(thisArg, _arguments || [])).next());
1047 | });
1048 | };
1049 | Object.defineProperty(exports, "__esModule", ({ value: true }));
1050 | exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0;
1051 | const os_1 = __nccwpck_require__(857);
1052 | const fs_1 = __nccwpck_require__(896);
1053 | const { access, appendFile, writeFile } = fs_1.promises;
1054 | exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY';
1055 | exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary';
1056 | class Summary {
1057 | constructor() {
1058 | this._buffer = '';
1059 | }
1060 | /**
1061 | * Finds the summary file path from the environment, rejects if env var is not found or file does not exist
1062 | * Also checks r/w permissions.
1063 | *
1064 | * @returns step summary file path
1065 | */
1066 | filePath() {
1067 | return __awaiter(this, void 0, void 0, function* () {
1068 | if (this._filePath) {
1069 | return this._filePath;
1070 | }
1071 | const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR];
1072 | if (!pathFromEnv) {
1073 | throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`);
1074 | }
1075 | try {
1076 | yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK);
1077 | }
1078 | catch (_a) {
1079 | throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`);
1080 | }
1081 | this._filePath = pathFromEnv;
1082 | return this._filePath;
1083 | });
1084 | }
1085 | /**
1086 | * Wraps content in an HTML tag, adding any HTML attributes
1087 | *
1088 | * @param {string} tag HTML tag to wrap
1089 | * @param {string | null} content content within the tag
1090 | * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add
1091 | *
1092 | * @returns {string} content wrapped in HTML element
1093 | */
1094 | wrap(tag, content, attrs = {}) {
1095 | const htmlAttrs = Object.entries(attrs)
1096 | .map(([key, value]) => ` ${key}="${value}"`)
1097 | .join('');
1098 | if (!content) {
1099 | return `<${tag}${htmlAttrs}>`;
1100 | }
1101 | return `<${tag}${htmlAttrs}>${content}${tag}>`;
1102 | }
1103 | /**
1104 | * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default.
1105 | *
1106 | * @param {SummaryWriteOptions} [options] (optional) options for write operation
1107 | *
1108 | * @returns {Promise} summary instance
1109 | */
1110 | write(options) {
1111 | return __awaiter(this, void 0, void 0, function* () {
1112 | const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite);
1113 | const filePath = yield this.filePath();
1114 | const writeFunc = overwrite ? writeFile : appendFile;
1115 | yield writeFunc(filePath, this._buffer, { encoding: 'utf8' });
1116 | return this.emptyBuffer();
1117 | });
1118 | }
1119 | /**
1120 | * Clears the summary buffer and wipes the summary file
1121 | *
1122 | * @returns {Summary} summary instance
1123 | */
1124 | clear() {
1125 | return __awaiter(this, void 0, void 0, function* () {
1126 | return this.emptyBuffer().write({ overwrite: true });
1127 | });
1128 | }
1129 | /**
1130 | * Returns the current summary buffer as a string
1131 | *
1132 | * @returns {string} string of summary buffer
1133 | */
1134 | stringify() {
1135 | return this._buffer;
1136 | }
1137 | /**
1138 | * If the summary buffer is empty
1139 | *
1140 | * @returns {boolen} true if the buffer is empty
1141 | */
1142 | isEmptyBuffer() {
1143 | return this._buffer.length === 0;
1144 | }
1145 | /**
1146 | * Resets the summary buffer without writing to summary file
1147 | *
1148 | * @returns {Summary} summary instance
1149 | */
1150 | emptyBuffer() {
1151 | this._buffer = '';
1152 | return this;
1153 | }
1154 | /**
1155 | * Adds raw text to the summary buffer
1156 | *
1157 | * @param {string} text content to add
1158 | * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false)
1159 | *
1160 | * @returns {Summary} summary instance
1161 | */
1162 | addRaw(text, addEOL = false) {
1163 | this._buffer += text;
1164 | return addEOL ? this.addEOL() : this;
1165 | }
1166 | /**
1167 | * Adds the operating system-specific end-of-line marker to the buffer
1168 | *
1169 | * @returns {Summary} summary instance
1170 | */
1171 | addEOL() {
1172 | return this.addRaw(os_1.EOL);
1173 | }
1174 | /**
1175 | * Adds an HTML codeblock to the summary buffer
1176 | *
1177 | * @param {string} code content to render within fenced code block
1178 | * @param {string} lang (optional) language to syntax highlight code
1179 | *
1180 | * @returns {Summary} summary instance
1181 | */
1182 | addCodeBlock(code, lang) {
1183 | const attrs = Object.assign({}, (lang && { lang }));
1184 | const element = this.wrap('pre', this.wrap('code', code), attrs);
1185 | return this.addRaw(element).addEOL();
1186 | }
1187 | /**
1188 | * Adds an HTML list to the summary buffer
1189 | *
1190 | * @param {string[]} items list of items to render
1191 | * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false)
1192 | *
1193 | * @returns {Summary} summary instance
1194 | */
1195 | addList(items, ordered = false) {
1196 | const tag = ordered ? 'ol' : 'ul';
1197 | const listItems = items.map(item => this.wrap('li', item)).join('');
1198 | const element = this.wrap(tag, listItems);
1199 | return this.addRaw(element).addEOL();
1200 | }
1201 | /**
1202 | * Adds an HTML table to the summary buffer
1203 | *
1204 | * @param {SummaryTableCell[]} rows table rows
1205 | *
1206 | * @returns {Summary} summary instance
1207 | */
1208 | addTable(rows) {
1209 | const tableBody = rows
1210 | .map(row => {
1211 | const cells = row
1212 | .map(cell => {
1213 | if (typeof cell === 'string') {
1214 | return this.wrap('td', cell);
1215 | }
1216 | const { header, data, colspan, rowspan } = cell;
1217 | const tag = header ? 'th' : 'td';
1218 | const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan }));
1219 | return this.wrap(tag, data, attrs);
1220 | })
1221 | .join('');
1222 | return this.wrap('tr', cells);
1223 | })
1224 | .join('');
1225 | const element = this.wrap('table', tableBody);
1226 | return this.addRaw(element).addEOL();
1227 | }
1228 | /**
1229 | * Adds a collapsable HTML details element to the summary buffer
1230 | *
1231 | * @param {string} label text for the closed state
1232 | * @param {string} content collapsable content
1233 | *
1234 | * @returns {Summary} summary instance
1235 | */
1236 | addDetails(label, content) {
1237 | const element = this.wrap('details', this.wrap('summary', label) + content);
1238 | return this.addRaw(element).addEOL();
1239 | }
1240 | /**
1241 | * Adds an HTML image tag to the summary buffer
1242 | *
1243 | * @param {string} src path to the image you to embed
1244 | * @param {string} alt text description of the image
1245 | * @param {SummaryImageOptions} options (optional) addition image attributes
1246 | *
1247 | * @returns {Summary} summary instance
1248 | */
1249 | addImage(src, alt, options) {
1250 | const { width, height } = options || {};
1251 | const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height }));
1252 | const element = this.wrap('img', null, Object.assign({ src, alt }, attrs));
1253 | return this.addRaw(element).addEOL();
1254 | }
1255 | /**
1256 | * Adds an HTML section heading element
1257 | *
1258 | * @param {string} text heading text
1259 | * @param {number | string} [level=1] (optional) the heading level, default: 1
1260 | *
1261 | * @returns {Summary} summary instance
1262 | */
1263 | addHeading(text, level) {
1264 | const tag = `h${level}`;
1265 | const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag)
1266 | ? tag
1267 | : 'h1';
1268 | const element = this.wrap(allowedTag, text);
1269 | return this.addRaw(element).addEOL();
1270 | }
1271 | /**
1272 | * Adds an HTML thematic break (
) to the summary buffer
1273 | *
1274 | * @returns {Summary} summary instance
1275 | */
1276 | addSeparator() {
1277 | const element = this.wrap('hr', null);
1278 | return this.addRaw(element).addEOL();
1279 | }
1280 | /**
1281 | * Adds an HTML line break (
) to the summary buffer
1282 | *
1283 | * @returns {Summary} summary instance
1284 | */
1285 | addBreak() {
1286 | const element = this.wrap('br', null);
1287 | return this.addRaw(element).addEOL();
1288 | }
1289 | /**
1290 | * Adds an HTML blockquote to the summary buffer
1291 | *
1292 | * @param {string} text quote text
1293 | * @param {string} cite (optional) citation url
1294 | *
1295 | * @returns {Summary} summary instance
1296 | */
1297 | addQuote(text, cite) {
1298 | const attrs = Object.assign({}, (cite && { cite }));
1299 | const element = this.wrap('blockquote', text, attrs);
1300 | return this.addRaw(element).addEOL();
1301 | }
1302 | /**
1303 | * Adds an HTML anchor tag to the summary buffer
1304 | *
1305 | * @param {string} text link text/content
1306 | * @param {string} href hyperlink
1307 | *
1308 | * @returns {Summary} summary instance
1309 | */
1310 | addLink(text, href) {
1311 | const element = this.wrap('a', text, { href });
1312 | return this.addRaw(element).addEOL();
1313 | }
1314 | }
1315 | const _summary = new Summary();
1316 | /**
1317 | * @deprecated use `core.summary`
1318 | */
1319 | exports.markdownSummary = _summary;
1320 | exports.summary = _summary;
1321 | //# sourceMappingURL=summary.js.map
1322 |
1323 | /***/ }),
1324 |
1325 | /***/ 302:
1326 | /***/ ((__unused_webpack_module, exports) => {
1327 |
1328 | "use strict";
1329 |
1330 | // We use any as a valid input type
1331 | /* eslint-disable @typescript-eslint/no-explicit-any */
1332 | Object.defineProperty(exports, "__esModule", ({ value: true }));
1333 | exports.toCommandProperties = exports.toCommandValue = void 0;
1334 | /**
1335 | * Sanitizes an input into a string so it can be passed into issueCommand safely
1336 | * @param input input to sanitize into a string
1337 | */
1338 | function toCommandValue(input) {
1339 | if (input === null || input === undefined) {
1340 | return '';
1341 | }
1342 | else if (typeof input === 'string' || input instanceof String) {
1343 | return input;
1344 | }
1345 | return JSON.stringify(input);
1346 | }
1347 | exports.toCommandValue = toCommandValue;
1348 | /**
1349 | *
1350 | * @param annotationProperties
1351 | * @returns The command properties to send with the actual annotation command
1352 | * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646
1353 | */
1354 | function toCommandProperties(annotationProperties) {
1355 | if (!Object.keys(annotationProperties).length) {
1356 | return {};
1357 | }
1358 | return {
1359 | title: annotationProperties.title,
1360 | file: annotationProperties.file,
1361 | line: annotationProperties.startLine,
1362 | endLine: annotationProperties.endLine,
1363 | col: annotationProperties.startColumn,
1364 | endColumn: annotationProperties.endColumn
1365 | };
1366 | }
1367 | exports.toCommandProperties = toCommandProperties;
1368 | //# sourceMappingURL=utils.js.map
1369 |
1370 | /***/ }),
1371 |
1372 | /***/ 236:
1373 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
1374 |
1375 | "use strict";
1376 |
1377 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
1378 | if (k2 === undefined) k2 = k;
1379 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
1380 | }) : (function(o, m, k, k2) {
1381 | if (k2 === undefined) k2 = k;
1382 | o[k2] = m[k];
1383 | }));
1384 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
1385 | Object.defineProperty(o, "default", { enumerable: true, value: v });
1386 | }) : function(o, v) {
1387 | o["default"] = v;
1388 | });
1389 | var __importStar = (this && this.__importStar) || function (mod) {
1390 | if (mod && mod.__esModule) return mod;
1391 | var result = {};
1392 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
1393 | __setModuleDefault(result, mod);
1394 | return result;
1395 | };
1396 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1397 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1398 | return new (P || (P = Promise))(function (resolve, reject) {
1399 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1400 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1401 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1402 | step((generator = generator.apply(thisArg, _arguments || [])).next());
1403 | });
1404 | };
1405 | Object.defineProperty(exports, "__esModule", ({ value: true }));
1406 | exports.getExecOutput = exports.exec = void 0;
1407 | const string_decoder_1 = __nccwpck_require__(193);
1408 | const tr = __importStar(__nccwpck_require__(665));
1409 | /**
1410 | * Exec a command.
1411 | * Output will be streamed to the live console.
1412 | * Returns promise with return code
1413 | *
1414 | * @param commandLine command to execute (can include additional args). Must be correctly escaped.
1415 | * @param args optional arguments for tool. Escaping is handled by the lib.
1416 | * @param options optional exec options. See ExecOptions
1417 | * @returns Promise exit code
1418 | */
1419 | function exec(commandLine, args, options) {
1420 | return __awaiter(this, void 0, void 0, function* () {
1421 | const commandArgs = tr.argStringToArray(commandLine);
1422 | if (commandArgs.length === 0) {
1423 | throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
1424 | }
1425 | // Path to tool to execute should be first arg
1426 | const toolPath = commandArgs[0];
1427 | args = commandArgs.slice(1).concat(args || []);
1428 | const runner = new tr.ToolRunner(toolPath, args, options);
1429 | return runner.exec();
1430 | });
1431 | }
1432 | exports.exec = exec;
1433 | /**
1434 | * Exec a command and get the output.
1435 | * Output will be streamed to the live console.
1436 | * Returns promise with the exit code and collected stdout and stderr
1437 | *
1438 | * @param commandLine command to execute (can include additional args). Must be correctly escaped.
1439 | * @param args optional arguments for tool. Escaping is handled by the lib.
1440 | * @param options optional exec options. See ExecOptions
1441 | * @returns Promise exit code, stdout, and stderr
1442 | */
1443 | function getExecOutput(commandLine, args, options) {
1444 | var _a, _b;
1445 | return __awaiter(this, void 0, void 0, function* () {
1446 | let stdout = '';
1447 | let stderr = '';
1448 | //Using string decoder covers the case where a mult-byte character is split
1449 | const stdoutDecoder = new string_decoder_1.StringDecoder('utf8');
1450 | const stderrDecoder = new string_decoder_1.StringDecoder('utf8');
1451 | const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout;
1452 | const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr;
1453 | const stdErrListener = (data) => {
1454 | stderr += stderrDecoder.write(data);
1455 | if (originalStdErrListener) {
1456 | originalStdErrListener(data);
1457 | }
1458 | };
1459 | const stdOutListener = (data) => {
1460 | stdout += stdoutDecoder.write(data);
1461 | if (originalStdoutListener) {
1462 | originalStdoutListener(data);
1463 | }
1464 | };
1465 | const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener });
1466 | const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners }));
1467 | //flush any remaining characters
1468 | stdout += stdoutDecoder.end();
1469 | stderr += stderrDecoder.end();
1470 | return {
1471 | exitCode,
1472 | stdout,
1473 | stderr
1474 | };
1475 | });
1476 | }
1477 | exports.getExecOutput = getExecOutput;
1478 | //# sourceMappingURL=exec.js.map
1479 |
1480 | /***/ }),
1481 |
1482 | /***/ 665:
1483 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
1484 |
1485 | "use strict";
1486 |
1487 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
1488 | if (k2 === undefined) k2 = k;
1489 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
1490 | }) : (function(o, m, k, k2) {
1491 | if (k2 === undefined) k2 = k;
1492 | o[k2] = m[k];
1493 | }));
1494 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
1495 | Object.defineProperty(o, "default", { enumerable: true, value: v });
1496 | }) : function(o, v) {
1497 | o["default"] = v;
1498 | });
1499 | var __importStar = (this && this.__importStar) || function (mod) {
1500 | if (mod && mod.__esModule) return mod;
1501 | var result = {};
1502 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
1503 | __setModuleDefault(result, mod);
1504 | return result;
1505 | };
1506 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
1507 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1508 | return new (P || (P = Promise))(function (resolve, reject) {
1509 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1510 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1511 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1512 | step((generator = generator.apply(thisArg, _arguments || [])).next());
1513 | });
1514 | };
1515 | Object.defineProperty(exports, "__esModule", ({ value: true }));
1516 | exports.argStringToArray = exports.ToolRunner = void 0;
1517 | const os = __importStar(__nccwpck_require__(857));
1518 | const events = __importStar(__nccwpck_require__(434));
1519 | const child = __importStar(__nccwpck_require__(317));
1520 | const path = __importStar(__nccwpck_require__(928));
1521 | const io = __importStar(__nccwpck_require__(994));
1522 | const ioUtil = __importStar(__nccwpck_require__(207));
1523 | const timers_1 = __nccwpck_require__(557);
1524 | /* eslint-disable @typescript-eslint/unbound-method */
1525 | const IS_WINDOWS = process.platform === 'win32';
1526 | /*
1527 | * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.
1528 | */
1529 | class ToolRunner extends events.EventEmitter {
1530 | constructor(toolPath, args, options) {
1531 | super();
1532 | if (!toolPath) {
1533 | throw new Error("Parameter 'toolPath' cannot be null or empty.");
1534 | }
1535 | this.toolPath = toolPath;
1536 | this.args = args || [];
1537 | this.options = options || {};
1538 | }
1539 | _debug(message) {
1540 | if (this.options.listeners && this.options.listeners.debug) {
1541 | this.options.listeners.debug(message);
1542 | }
1543 | }
1544 | _getCommandString(options, noPrefix) {
1545 | const toolPath = this._getSpawnFileName();
1546 | const args = this._getSpawnArgs(options);
1547 | let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool
1548 | if (IS_WINDOWS) {
1549 | // Windows + cmd file
1550 | if (this._isCmdFile()) {
1551 | cmd += toolPath;
1552 | for (const a of args) {
1553 | cmd += ` ${a}`;
1554 | }
1555 | }
1556 | // Windows + verbatim
1557 | else if (options.windowsVerbatimArguments) {
1558 | cmd += `"${toolPath}"`;
1559 | for (const a of args) {
1560 | cmd += ` ${a}`;
1561 | }
1562 | }
1563 | // Windows (regular)
1564 | else {
1565 | cmd += this._windowsQuoteCmdArg(toolPath);
1566 | for (const a of args) {
1567 | cmd += ` ${this._windowsQuoteCmdArg(a)}`;
1568 | }
1569 | }
1570 | }
1571 | else {
1572 | // OSX/Linux - this can likely be improved with some form of quoting.
1573 | // creating processes on Unix is fundamentally different than Windows.
1574 | // on Unix, execvp() takes an arg array.
1575 | cmd += toolPath;
1576 | for (const a of args) {
1577 | cmd += ` ${a}`;
1578 | }
1579 | }
1580 | return cmd;
1581 | }
1582 | _processLineBuffer(data, strBuffer, onLine) {
1583 | try {
1584 | let s = strBuffer + data.toString();
1585 | let n = s.indexOf(os.EOL);
1586 | while (n > -1) {
1587 | const line = s.substring(0, n);
1588 | onLine(line);
1589 | // the rest of the string ...
1590 | s = s.substring(n + os.EOL.length);
1591 | n = s.indexOf(os.EOL);
1592 | }
1593 | return s;
1594 | }
1595 | catch (err) {
1596 | // streaming lines to console is best effort. Don't fail a build.
1597 | this._debug(`error processing line. Failed with error ${err}`);
1598 | return '';
1599 | }
1600 | }
1601 | _getSpawnFileName() {
1602 | if (IS_WINDOWS) {
1603 | if (this._isCmdFile()) {
1604 | return process.env['COMSPEC'] || 'cmd.exe';
1605 | }
1606 | }
1607 | return this.toolPath;
1608 | }
1609 | _getSpawnArgs(options) {
1610 | if (IS_WINDOWS) {
1611 | if (this._isCmdFile()) {
1612 | let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;
1613 | for (const a of this.args) {
1614 | argline += ' ';
1615 | argline += options.windowsVerbatimArguments
1616 | ? a
1617 | : this._windowsQuoteCmdArg(a);
1618 | }
1619 | argline += '"';
1620 | return [argline];
1621 | }
1622 | }
1623 | return this.args;
1624 | }
1625 | _endsWith(str, end) {
1626 | return str.endsWith(end);
1627 | }
1628 | _isCmdFile() {
1629 | const upperToolPath = this.toolPath.toUpperCase();
1630 | return (this._endsWith(upperToolPath, '.CMD') ||
1631 | this._endsWith(upperToolPath, '.BAT'));
1632 | }
1633 | _windowsQuoteCmdArg(arg) {
1634 | // for .exe, apply the normal quoting rules that libuv applies
1635 | if (!this._isCmdFile()) {
1636 | return this._uvQuoteCmdArg(arg);
1637 | }
1638 | // otherwise apply quoting rules specific to the cmd.exe command line parser.
1639 | // the libuv rules are generic and are not designed specifically for cmd.exe
1640 | // command line parser.
1641 | //
1642 | // for a detailed description of the cmd.exe command line parser, refer to
1643 | // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
1644 | // need quotes for empty arg
1645 | if (!arg) {
1646 | return '""';
1647 | }
1648 | // determine whether the arg needs to be quoted
1649 | const cmdSpecialChars = [
1650 | ' ',
1651 | '\t',
1652 | '&',
1653 | '(',
1654 | ')',
1655 | '[',
1656 | ']',
1657 | '{',
1658 | '}',
1659 | '^',
1660 | '=',
1661 | ';',
1662 | '!',
1663 | "'",
1664 | '+',
1665 | ',',
1666 | '`',
1667 | '~',
1668 | '|',
1669 | '<',
1670 | '>',
1671 | '"'
1672 | ];
1673 | let needsQuotes = false;
1674 | for (const char of arg) {
1675 | if (cmdSpecialChars.some(x => x === char)) {
1676 | needsQuotes = true;
1677 | break;
1678 | }
1679 | }
1680 | // short-circuit if quotes not needed
1681 | if (!needsQuotes) {
1682 | return arg;
1683 | }
1684 | // the following quoting rules are very similar to the rules that by libuv applies.
1685 | //
1686 | // 1) wrap the string in quotes
1687 | //
1688 | // 2) double-up quotes - i.e. " => ""
1689 | //
1690 | // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately
1691 | // doesn't work well with a cmd.exe command line.
1692 | //
1693 | // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app.
1694 | // for example, the command line:
1695 | // foo.exe "myarg:""my val"""
1696 | // is parsed by a .NET console app into an arg array:
1697 | // [ "myarg:\"my val\"" ]
1698 | // which is the same end result when applying libuv quoting rules. although the actual
1699 | // command line from libuv quoting rules would look like:
1700 | // foo.exe "myarg:\"my val\""
1701 | //
1702 | // 3) double-up slashes that precede a quote,
1703 | // e.g. hello \world => "hello \world"
1704 | // hello\"world => "hello\\""world"
1705 | // hello\\"world => "hello\\\\""world"
1706 | // hello world\ => "hello world\\"
1707 | //
1708 | // technically this is not required for a cmd.exe command line, or the batch argument parser.
1709 | // the reasons for including this as a .cmd quoting rule are:
1710 | //
1711 | // a) this is optimized for the scenario where the argument is passed from the .cmd file to an
1712 | // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.
1713 | //
1714 | // b) it's what we've been doing previously (by deferring to node default behavior) and we
1715 | // haven't heard any complaints about that aspect.
1716 | //
1717 | // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be
1718 | // escaped when used on the command line directly - even though within a .cmd file % can be escaped
1719 | // by using %%.
1720 | //
1721 | // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts
1722 | // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.
1723 | //
1724 | // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would
1725 | // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the
1726 | // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args
1727 | // to an external program.
1728 | //
1729 | // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.
1730 | // % can be escaped within a .cmd file.
1731 | let reverse = '"';
1732 | let quoteHit = true;
1733 | for (let i = arg.length; i > 0; i--) {
1734 | // walk the string in reverse
1735 | reverse += arg[i - 1];
1736 | if (quoteHit && arg[i - 1] === '\\') {
1737 | reverse += '\\'; // double the slash
1738 | }
1739 | else if (arg[i - 1] === '"') {
1740 | quoteHit = true;
1741 | reverse += '"'; // double the quote
1742 | }
1743 | else {
1744 | quoteHit = false;
1745 | }
1746 | }
1747 | reverse += '"';
1748 | return reverse
1749 | .split('')
1750 | .reverse()
1751 | .join('');
1752 | }
1753 | _uvQuoteCmdArg(arg) {
1754 | // Tool runner wraps child_process.spawn() and needs to apply the same quoting as
1755 | // Node in certain cases where the undocumented spawn option windowsVerbatimArguments
1756 | // is used.
1757 | //
1758 | // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,
1759 | // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),
1760 | // pasting copyright notice from Node within this function:
1761 | //
1762 | // Copyright Joyent, Inc. and other Node contributors. All rights reserved.
1763 | //
1764 | // Permission is hereby granted, free of charge, to any person obtaining a copy
1765 | // of this software and associated documentation files (the "Software"), to
1766 | // deal in the Software without restriction, including without limitation the
1767 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1768 | // sell copies of the Software, and to permit persons to whom the Software is
1769 | // furnished to do so, subject to the following conditions:
1770 | //
1771 | // The above copyright notice and this permission notice shall be included in
1772 | // all copies or substantial portions of the Software.
1773 | //
1774 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1775 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1776 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1777 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1778 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1779 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1780 | // IN THE SOFTWARE.
1781 | if (!arg) {
1782 | // Need double quotation for empty argument
1783 | return '""';
1784 | }
1785 | if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) {
1786 | // No quotation needed
1787 | return arg;
1788 | }
1789 | if (!arg.includes('"') && !arg.includes('\\')) {
1790 | // No embedded double quotes or backslashes, so I can just wrap
1791 | // quote marks around the whole thing.
1792 | return `"${arg}"`;
1793 | }
1794 | // Expected input/output:
1795 | // input : hello"world
1796 | // output: "hello\"world"
1797 | // input : hello""world
1798 | // output: "hello\"\"world"
1799 | // input : hello\world
1800 | // output: hello\world
1801 | // input : hello\\world
1802 | // output: hello\\world
1803 | // input : hello\"world
1804 | // output: "hello\\\"world"
1805 | // input : hello\\"world
1806 | // output: "hello\\\\\"world"
1807 | // input : hello world\
1808 | // output: "hello world\\" - note the comment in libuv actually reads "hello world\"
1809 | // but it appears the comment is wrong, it should be "hello world\\"
1810 | let reverse = '"';
1811 | let quoteHit = true;
1812 | for (let i = arg.length; i > 0; i--) {
1813 | // walk the string in reverse
1814 | reverse += arg[i - 1];
1815 | if (quoteHit && arg[i - 1] === '\\') {
1816 | reverse += '\\';
1817 | }
1818 | else if (arg[i - 1] === '"') {
1819 | quoteHit = true;
1820 | reverse += '\\';
1821 | }
1822 | else {
1823 | quoteHit = false;
1824 | }
1825 | }
1826 | reverse += '"';
1827 | return reverse
1828 | .split('')
1829 | .reverse()
1830 | .join('');
1831 | }
1832 | _cloneExecOptions(options) {
1833 | options = options || {};
1834 | const result = {
1835 | cwd: options.cwd || process.cwd(),
1836 | env: options.env || process.env,
1837 | silent: options.silent || false,
1838 | windowsVerbatimArguments: options.windowsVerbatimArguments || false,
1839 | failOnStdErr: options.failOnStdErr || false,
1840 | ignoreReturnCode: options.ignoreReturnCode || false,
1841 | delay: options.delay || 10000
1842 | };
1843 | result.outStream = options.outStream || process.stdout;
1844 | result.errStream = options.errStream || process.stderr;
1845 | return result;
1846 | }
1847 | _getSpawnOptions(options, toolPath) {
1848 | options = options || {};
1849 | const result = {};
1850 | result.cwd = options.cwd;
1851 | result.env = options.env;
1852 | result['windowsVerbatimArguments'] =
1853 | options.windowsVerbatimArguments || this._isCmdFile();
1854 | if (options.windowsVerbatimArguments) {
1855 | result.argv0 = `"${toolPath}"`;
1856 | }
1857 | return result;
1858 | }
1859 | /**
1860 | * Exec a tool.
1861 | * Output will be streamed to the live console.
1862 | * Returns promise with return code
1863 | *
1864 | * @param tool path to tool to exec
1865 | * @param options optional exec options. See ExecOptions
1866 | * @returns number
1867 | */
1868 | exec() {
1869 | return __awaiter(this, void 0, void 0, function* () {
1870 | // root the tool path if it is unrooted and contains relative pathing
1871 | if (!ioUtil.isRooted(this.toolPath) &&
1872 | (this.toolPath.includes('/') ||
1873 | (IS_WINDOWS && this.toolPath.includes('\\')))) {
1874 | // prefer options.cwd if it is specified, however options.cwd may also need to be rooted
1875 | this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);
1876 | }
1877 | // if the tool is only a file name, then resolve it from the PATH
1878 | // otherwise verify it exists (add extension on Windows if necessary)
1879 | this.toolPath = yield io.which(this.toolPath, true);
1880 | return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
1881 | this._debug(`exec tool: ${this.toolPath}`);
1882 | this._debug('arguments:');
1883 | for (const arg of this.args) {
1884 | this._debug(` ${arg}`);
1885 | }
1886 | const optionsNonNull = this._cloneExecOptions(this.options);
1887 | if (!optionsNonNull.silent && optionsNonNull.outStream) {
1888 | optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
1889 | }
1890 | const state = new ExecState(optionsNonNull, this.toolPath);
1891 | state.on('debug', (message) => {
1892 | this._debug(message);
1893 | });
1894 | if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) {
1895 | return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`));
1896 | }
1897 | const fileName = this._getSpawnFileName();
1898 | const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));
1899 | let stdbuffer = '';
1900 | if (cp.stdout) {
1901 | cp.stdout.on('data', (data) => {
1902 | if (this.options.listeners && this.options.listeners.stdout) {
1903 | this.options.listeners.stdout(data);
1904 | }
1905 | if (!optionsNonNull.silent && optionsNonNull.outStream) {
1906 | optionsNonNull.outStream.write(data);
1907 | }
1908 | stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => {
1909 | if (this.options.listeners && this.options.listeners.stdline) {
1910 | this.options.listeners.stdline(line);
1911 | }
1912 | });
1913 | });
1914 | }
1915 | let errbuffer = '';
1916 | if (cp.stderr) {
1917 | cp.stderr.on('data', (data) => {
1918 | state.processStderr = true;
1919 | if (this.options.listeners && this.options.listeners.stderr) {
1920 | this.options.listeners.stderr(data);
1921 | }
1922 | if (!optionsNonNull.silent &&
1923 | optionsNonNull.errStream &&
1924 | optionsNonNull.outStream) {
1925 | const s = optionsNonNull.failOnStdErr
1926 | ? optionsNonNull.errStream
1927 | : optionsNonNull.outStream;
1928 | s.write(data);
1929 | }
1930 | errbuffer = this._processLineBuffer(data, errbuffer, (line) => {
1931 | if (this.options.listeners && this.options.listeners.errline) {
1932 | this.options.listeners.errline(line);
1933 | }
1934 | });
1935 | });
1936 | }
1937 | cp.on('error', (err) => {
1938 | state.processError = err.message;
1939 | state.processExited = true;
1940 | state.processClosed = true;
1941 | state.CheckComplete();
1942 | });
1943 | cp.on('exit', (code) => {
1944 | state.processExitCode = code;
1945 | state.processExited = true;
1946 | this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
1947 | state.CheckComplete();
1948 | });
1949 | cp.on('close', (code) => {
1950 | state.processExitCode = code;
1951 | state.processExited = true;
1952 | state.processClosed = true;
1953 | this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);
1954 | state.CheckComplete();
1955 | });
1956 | state.on('done', (error, exitCode) => {
1957 | if (stdbuffer.length > 0) {
1958 | this.emit('stdline', stdbuffer);
1959 | }
1960 | if (errbuffer.length > 0) {
1961 | this.emit('errline', errbuffer);
1962 | }
1963 | cp.removeAllListeners();
1964 | if (error) {
1965 | reject(error);
1966 | }
1967 | else {
1968 | resolve(exitCode);
1969 | }
1970 | });
1971 | if (this.options.input) {
1972 | if (!cp.stdin) {
1973 | throw new Error('child process missing stdin');
1974 | }
1975 | cp.stdin.end(this.options.input);
1976 | }
1977 | }));
1978 | });
1979 | }
1980 | }
1981 | exports.ToolRunner = ToolRunner;
1982 | /**
1983 | * Convert an arg string to an array of args. Handles escaping
1984 | *
1985 | * @param argString string of arguments
1986 | * @returns string[] array of arguments
1987 | */
1988 | function argStringToArray(argString) {
1989 | const args = [];
1990 | let inQuotes = false;
1991 | let escaped = false;
1992 | let arg = '';
1993 | function append(c) {
1994 | // we only escape double quotes.
1995 | if (escaped && c !== '"') {
1996 | arg += '\\';
1997 | }
1998 | arg += c;
1999 | escaped = false;
2000 | }
2001 | for (let i = 0; i < argString.length; i++) {
2002 | const c = argString.charAt(i);
2003 | if (c === '"') {
2004 | if (!escaped) {
2005 | inQuotes = !inQuotes;
2006 | }
2007 | else {
2008 | append(c);
2009 | }
2010 | continue;
2011 | }
2012 | if (c === '\\' && escaped) {
2013 | append(c);
2014 | continue;
2015 | }
2016 | if (c === '\\' && inQuotes) {
2017 | escaped = true;
2018 | continue;
2019 | }
2020 | if (c === ' ' && !inQuotes) {
2021 | if (arg.length > 0) {
2022 | args.push(arg);
2023 | arg = '';
2024 | }
2025 | continue;
2026 | }
2027 | append(c);
2028 | }
2029 | if (arg.length > 0) {
2030 | args.push(arg.trim());
2031 | }
2032 | return args;
2033 | }
2034 | exports.argStringToArray = argStringToArray;
2035 | class ExecState extends events.EventEmitter {
2036 | constructor(options, toolPath) {
2037 | super();
2038 | this.processClosed = false; // tracks whether the process has exited and stdio is closed
2039 | this.processError = '';
2040 | this.processExitCode = 0;
2041 | this.processExited = false; // tracks whether the process has exited
2042 | this.processStderr = false; // tracks whether stderr was written to
2043 | this.delay = 10000; // 10 seconds
2044 | this.done = false;
2045 | this.timeout = null;
2046 | if (!toolPath) {
2047 | throw new Error('toolPath must not be empty');
2048 | }
2049 | this.options = options;
2050 | this.toolPath = toolPath;
2051 | if (options.delay) {
2052 | this.delay = options.delay;
2053 | }
2054 | }
2055 | CheckComplete() {
2056 | if (this.done) {
2057 | return;
2058 | }
2059 | if (this.processClosed) {
2060 | this._setResult();
2061 | }
2062 | else if (this.processExited) {
2063 | this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this);
2064 | }
2065 | }
2066 | _debug(message) {
2067 | this.emit('debug', message);
2068 | }
2069 | _setResult() {
2070 | // determine whether there is an error
2071 | let error;
2072 | if (this.processExited) {
2073 | if (this.processError) {
2074 | 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}`);
2075 | }
2076 | else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {
2077 | error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);
2078 | }
2079 | else if (this.processStderr && this.options.failOnStdErr) {
2080 | error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);
2081 | }
2082 | }
2083 | // clear the timeout
2084 | if (this.timeout) {
2085 | clearTimeout(this.timeout);
2086 | this.timeout = null;
2087 | }
2088 | this.done = true;
2089 | this.emit('done', error, this.processExitCode);
2090 | }
2091 | static HandleTimeout(state) {
2092 | if (state.done) {
2093 | return;
2094 | }
2095 | if (!state.processClosed && state.processExited) {
2096 | const message = `The STDIO streams did not close within ${state.delay /
2097 | 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.`;
2098 | state._debug(message);
2099 | }
2100 | state._setResult();
2101 | }
2102 | }
2103 | //# sourceMappingURL=toolrunner.js.map
2104 |
2105 | /***/ }),
2106 |
2107 | /***/ 552:
2108 | /***/ (function(__unused_webpack_module, exports) {
2109 |
2110 | "use strict";
2111 |
2112 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2113 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2114 | return new (P || (P = Promise))(function (resolve, reject) {
2115 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2116 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2117 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2118 | step((generator = generator.apply(thisArg, _arguments || [])).next());
2119 | });
2120 | };
2121 | Object.defineProperty(exports, "__esModule", ({ value: true }));
2122 | exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0;
2123 | class BasicCredentialHandler {
2124 | constructor(username, password) {
2125 | this.username = username;
2126 | this.password = password;
2127 | }
2128 | prepareRequest(options) {
2129 | if (!options.headers) {
2130 | throw Error('The request has no headers');
2131 | }
2132 | options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`;
2133 | }
2134 | // This handler cannot handle 401
2135 | canHandleAuthentication() {
2136 | return false;
2137 | }
2138 | handleAuthentication() {
2139 | return __awaiter(this, void 0, void 0, function* () {
2140 | throw new Error('not implemented');
2141 | });
2142 | }
2143 | }
2144 | exports.BasicCredentialHandler = BasicCredentialHandler;
2145 | class BearerCredentialHandler {
2146 | constructor(token) {
2147 | this.token = token;
2148 | }
2149 | // currently implements pre-authorization
2150 | // TODO: support preAuth = false where it hooks on 401
2151 | prepareRequest(options) {
2152 | if (!options.headers) {
2153 | throw Error('The request has no headers');
2154 | }
2155 | options.headers['Authorization'] = `Bearer ${this.token}`;
2156 | }
2157 | // This handler cannot handle 401
2158 | canHandleAuthentication() {
2159 | return false;
2160 | }
2161 | handleAuthentication() {
2162 | return __awaiter(this, void 0, void 0, function* () {
2163 | throw new Error('not implemented');
2164 | });
2165 | }
2166 | }
2167 | exports.BearerCredentialHandler = BearerCredentialHandler;
2168 | class PersonalAccessTokenCredentialHandler {
2169 | constructor(token) {
2170 | this.token = token;
2171 | }
2172 | // currently implements pre-authorization
2173 | // TODO: support preAuth = false where it hooks on 401
2174 | prepareRequest(options) {
2175 | if (!options.headers) {
2176 | throw Error('The request has no headers');
2177 | }
2178 | options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`;
2179 | }
2180 | // This handler cannot handle 401
2181 | canHandleAuthentication() {
2182 | return false;
2183 | }
2184 | handleAuthentication() {
2185 | return __awaiter(this, void 0, void 0, function* () {
2186 | throw new Error('not implemented');
2187 | });
2188 | }
2189 | }
2190 | exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler;
2191 | //# sourceMappingURL=auth.js.map
2192 |
2193 | /***/ }),
2194 |
2195 | /***/ 844:
2196 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
2197 |
2198 | "use strict";
2199 |
2200 | /* eslint-disable @typescript-eslint/no-explicit-any */
2201 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
2202 | if (k2 === undefined) k2 = k;
2203 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
2204 | }) : (function(o, m, k, k2) {
2205 | if (k2 === undefined) k2 = k;
2206 | o[k2] = m[k];
2207 | }));
2208 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
2209 | Object.defineProperty(o, "default", { enumerable: true, value: v });
2210 | }) : function(o, v) {
2211 | o["default"] = v;
2212 | });
2213 | var __importStar = (this && this.__importStar) || function (mod) {
2214 | if (mod && mod.__esModule) return mod;
2215 | var result = {};
2216 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
2217 | __setModuleDefault(result, mod);
2218 | return result;
2219 | };
2220 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2221 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2222 | return new (P || (P = Promise))(function (resolve, reject) {
2223 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2224 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2225 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2226 | step((generator = generator.apply(thisArg, _arguments || [])).next());
2227 | });
2228 | };
2229 | Object.defineProperty(exports, "__esModule", ({ value: true }));
2230 | exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0;
2231 | const http = __importStar(__nccwpck_require__(611));
2232 | const https = __importStar(__nccwpck_require__(692));
2233 | const pm = __importStar(__nccwpck_require__(988));
2234 | const tunnel = __importStar(__nccwpck_require__(770));
2235 | var HttpCodes;
2236 | (function (HttpCodes) {
2237 | HttpCodes[HttpCodes["OK"] = 200] = "OK";
2238 | HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices";
2239 | HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently";
2240 | HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved";
2241 | HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther";
2242 | HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified";
2243 | HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy";
2244 | HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy";
2245 | HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect";
2246 | HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect";
2247 | HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest";
2248 | HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized";
2249 | HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired";
2250 | HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden";
2251 | HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound";
2252 | HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed";
2253 | HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable";
2254 | HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
2255 | HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout";
2256 | HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict";
2257 | HttpCodes[HttpCodes["Gone"] = 410] = "Gone";
2258 | HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests";
2259 | HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError";
2260 | HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented";
2261 | HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway";
2262 | HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable";
2263 | HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout";
2264 | })(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {}));
2265 | var Headers;
2266 | (function (Headers) {
2267 | Headers["Accept"] = "accept";
2268 | Headers["ContentType"] = "content-type";
2269 | })(Headers = exports.Headers || (exports.Headers = {}));
2270 | var MediaTypes;
2271 | (function (MediaTypes) {
2272 | MediaTypes["ApplicationJson"] = "application/json";
2273 | })(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {}));
2274 | /**
2275 | * Returns the proxy URL, depending upon the supplied url and proxy environment variables.
2276 | * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
2277 | */
2278 | function getProxyUrl(serverUrl) {
2279 | const proxyUrl = pm.getProxyUrl(new URL(serverUrl));
2280 | return proxyUrl ? proxyUrl.href : '';
2281 | }
2282 | exports.getProxyUrl = getProxyUrl;
2283 | const HttpRedirectCodes = [
2284 | HttpCodes.MovedPermanently,
2285 | HttpCodes.ResourceMoved,
2286 | HttpCodes.SeeOther,
2287 | HttpCodes.TemporaryRedirect,
2288 | HttpCodes.PermanentRedirect
2289 | ];
2290 | const HttpResponseRetryCodes = [
2291 | HttpCodes.BadGateway,
2292 | HttpCodes.ServiceUnavailable,
2293 | HttpCodes.GatewayTimeout
2294 | ];
2295 | const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD'];
2296 | const ExponentialBackoffCeiling = 10;
2297 | const ExponentialBackoffTimeSlice = 5;
2298 | class HttpClientError extends Error {
2299 | constructor(message, statusCode) {
2300 | super(message);
2301 | this.name = 'HttpClientError';
2302 | this.statusCode = statusCode;
2303 | Object.setPrototypeOf(this, HttpClientError.prototype);
2304 | }
2305 | }
2306 | exports.HttpClientError = HttpClientError;
2307 | class HttpClientResponse {
2308 | constructor(message) {
2309 | this.message = message;
2310 | }
2311 | readBody() {
2312 | return __awaiter(this, void 0, void 0, function* () {
2313 | return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
2314 | let output = Buffer.alloc(0);
2315 | this.message.on('data', (chunk) => {
2316 | output = Buffer.concat([output, chunk]);
2317 | });
2318 | this.message.on('end', () => {
2319 | resolve(output.toString());
2320 | });
2321 | }));
2322 | });
2323 | }
2324 | }
2325 | exports.HttpClientResponse = HttpClientResponse;
2326 | function isHttps(requestUrl) {
2327 | const parsedUrl = new URL(requestUrl);
2328 | return parsedUrl.protocol === 'https:';
2329 | }
2330 | exports.isHttps = isHttps;
2331 | class HttpClient {
2332 | constructor(userAgent, handlers, requestOptions) {
2333 | this._ignoreSslError = false;
2334 | this._allowRedirects = true;
2335 | this._allowRedirectDowngrade = false;
2336 | this._maxRedirects = 50;
2337 | this._allowRetries = false;
2338 | this._maxRetries = 1;
2339 | this._keepAlive = false;
2340 | this._disposed = false;
2341 | this.userAgent = userAgent;
2342 | this.handlers = handlers || [];
2343 | this.requestOptions = requestOptions;
2344 | if (requestOptions) {
2345 | if (requestOptions.ignoreSslError != null) {
2346 | this._ignoreSslError = requestOptions.ignoreSslError;
2347 | }
2348 | this._socketTimeout = requestOptions.socketTimeout;
2349 | if (requestOptions.allowRedirects != null) {
2350 | this._allowRedirects = requestOptions.allowRedirects;
2351 | }
2352 | if (requestOptions.allowRedirectDowngrade != null) {
2353 | this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade;
2354 | }
2355 | if (requestOptions.maxRedirects != null) {
2356 | this._maxRedirects = Math.max(requestOptions.maxRedirects, 0);
2357 | }
2358 | if (requestOptions.keepAlive != null) {
2359 | this._keepAlive = requestOptions.keepAlive;
2360 | }
2361 | if (requestOptions.allowRetries != null) {
2362 | this._allowRetries = requestOptions.allowRetries;
2363 | }
2364 | if (requestOptions.maxRetries != null) {
2365 | this._maxRetries = requestOptions.maxRetries;
2366 | }
2367 | }
2368 | }
2369 | options(requestUrl, additionalHeaders) {
2370 | return __awaiter(this, void 0, void 0, function* () {
2371 | return this.request('OPTIONS', requestUrl, null, additionalHeaders || {});
2372 | });
2373 | }
2374 | get(requestUrl, additionalHeaders) {
2375 | return __awaiter(this, void 0, void 0, function* () {
2376 | return this.request('GET', requestUrl, null, additionalHeaders || {});
2377 | });
2378 | }
2379 | del(requestUrl, additionalHeaders) {
2380 | return __awaiter(this, void 0, void 0, function* () {
2381 | return this.request('DELETE', requestUrl, null, additionalHeaders || {});
2382 | });
2383 | }
2384 | post(requestUrl, data, additionalHeaders) {
2385 | return __awaiter(this, void 0, void 0, function* () {
2386 | return this.request('POST', requestUrl, data, additionalHeaders || {});
2387 | });
2388 | }
2389 | patch(requestUrl, data, additionalHeaders) {
2390 | return __awaiter(this, void 0, void 0, function* () {
2391 | return this.request('PATCH', requestUrl, data, additionalHeaders || {});
2392 | });
2393 | }
2394 | put(requestUrl, data, additionalHeaders) {
2395 | return __awaiter(this, void 0, void 0, function* () {
2396 | return this.request('PUT', requestUrl, data, additionalHeaders || {});
2397 | });
2398 | }
2399 | head(requestUrl, additionalHeaders) {
2400 | return __awaiter(this, void 0, void 0, function* () {
2401 | return this.request('HEAD', requestUrl, null, additionalHeaders || {});
2402 | });
2403 | }
2404 | sendStream(verb, requestUrl, stream, additionalHeaders) {
2405 | return __awaiter(this, void 0, void 0, function* () {
2406 | return this.request(verb, requestUrl, stream, additionalHeaders);
2407 | });
2408 | }
2409 | /**
2410 | * Gets a typed object from an endpoint
2411 | * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise
2412 | */
2413 | getJson(requestUrl, additionalHeaders = {}) {
2414 | return __awaiter(this, void 0, void 0, function* () {
2415 | additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
2416 | const res = yield this.get(requestUrl, additionalHeaders);
2417 | return this._processResponse(res, this.requestOptions);
2418 | });
2419 | }
2420 | postJson(requestUrl, obj, additionalHeaders = {}) {
2421 | return __awaiter(this, void 0, void 0, function* () {
2422 | const data = JSON.stringify(obj, null, 2);
2423 | additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
2424 | additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
2425 | const res = yield this.post(requestUrl, data, additionalHeaders);
2426 | return this._processResponse(res, this.requestOptions);
2427 | });
2428 | }
2429 | putJson(requestUrl, obj, additionalHeaders = {}) {
2430 | return __awaiter(this, void 0, void 0, function* () {
2431 | const data = JSON.stringify(obj, null, 2);
2432 | additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
2433 | additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
2434 | const res = yield this.put(requestUrl, data, additionalHeaders);
2435 | return this._processResponse(res, this.requestOptions);
2436 | });
2437 | }
2438 | patchJson(requestUrl, obj, additionalHeaders = {}) {
2439 | return __awaiter(this, void 0, void 0, function* () {
2440 | const data = JSON.stringify(obj, null, 2);
2441 | additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson);
2442 | additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson);
2443 | const res = yield this.patch(requestUrl, data, additionalHeaders);
2444 | return this._processResponse(res, this.requestOptions);
2445 | });
2446 | }
2447 | /**
2448 | * Makes a raw http request.
2449 | * All other methods such as get, post, patch, and request ultimately call this.
2450 | * Prefer get, del, post and patch
2451 | */
2452 | request(verb, requestUrl, data, headers) {
2453 | return __awaiter(this, void 0, void 0, function* () {
2454 | if (this._disposed) {
2455 | throw new Error('Client has already been disposed.');
2456 | }
2457 | const parsedUrl = new URL(requestUrl);
2458 | let info = this._prepareRequest(verb, parsedUrl, headers);
2459 | // Only perform retries on reads since writes may not be idempotent.
2460 | const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb)
2461 | ? this._maxRetries + 1
2462 | : 1;
2463 | let numTries = 0;
2464 | let response;
2465 | do {
2466 | response = yield this.requestRaw(info, data);
2467 | // Check if it's an authentication challenge
2468 | if (response &&
2469 | response.message &&
2470 | response.message.statusCode === HttpCodes.Unauthorized) {
2471 | let authenticationHandler;
2472 | for (const handler of this.handlers) {
2473 | if (handler.canHandleAuthentication(response)) {
2474 | authenticationHandler = handler;
2475 | break;
2476 | }
2477 | }
2478 | if (authenticationHandler) {
2479 | return authenticationHandler.handleAuthentication(this, info, data);
2480 | }
2481 | else {
2482 | // We have received an unauthorized response but have no handlers to handle it.
2483 | // Let the response return to the caller.
2484 | return response;
2485 | }
2486 | }
2487 | let redirectsRemaining = this._maxRedirects;
2488 | while (response.message.statusCode &&
2489 | HttpRedirectCodes.includes(response.message.statusCode) &&
2490 | this._allowRedirects &&
2491 | redirectsRemaining > 0) {
2492 | const redirectUrl = response.message.headers['location'];
2493 | if (!redirectUrl) {
2494 | // if there's no location to redirect to, we won't
2495 | break;
2496 | }
2497 | const parsedRedirectUrl = new URL(redirectUrl);
2498 | if (parsedUrl.protocol === 'https:' &&
2499 | parsedUrl.protocol !== parsedRedirectUrl.protocol &&
2500 | !this._allowRedirectDowngrade) {
2501 | 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.');
2502 | }
2503 | // we need to finish reading the response before reassigning response
2504 | // which will leak the open socket.
2505 | yield response.readBody();
2506 | // strip authorization header if redirected to a different hostname
2507 | if (parsedRedirectUrl.hostname !== parsedUrl.hostname) {
2508 | for (const header in headers) {
2509 | // header names are case insensitive
2510 | if (header.toLowerCase() === 'authorization') {
2511 | delete headers[header];
2512 | }
2513 | }
2514 | }
2515 | // let's make the request with the new redirectUrl
2516 | info = this._prepareRequest(verb, parsedRedirectUrl, headers);
2517 | response = yield this.requestRaw(info, data);
2518 | redirectsRemaining--;
2519 | }
2520 | if (!response.message.statusCode ||
2521 | !HttpResponseRetryCodes.includes(response.message.statusCode)) {
2522 | // If not a retry code, return immediately instead of retrying
2523 | return response;
2524 | }
2525 | numTries += 1;
2526 | if (numTries < maxTries) {
2527 | yield response.readBody();
2528 | yield this._performExponentialBackoff(numTries);
2529 | }
2530 | } while (numTries < maxTries);
2531 | return response;
2532 | });
2533 | }
2534 | /**
2535 | * Needs to be called if keepAlive is set to true in request options.
2536 | */
2537 | dispose() {
2538 | if (this._agent) {
2539 | this._agent.destroy();
2540 | }
2541 | this._disposed = true;
2542 | }
2543 | /**
2544 | * Raw request.
2545 | * @param info
2546 | * @param data
2547 | */
2548 | requestRaw(info, data) {
2549 | return __awaiter(this, void 0, void 0, function* () {
2550 | return new Promise((resolve, reject) => {
2551 | function callbackForResult(err, res) {
2552 | if (err) {
2553 | reject(err);
2554 | }
2555 | else if (!res) {
2556 | // If `err` is not passed, then `res` must be passed.
2557 | reject(new Error('Unknown error'));
2558 | }
2559 | else {
2560 | resolve(res);
2561 | }
2562 | }
2563 | this.requestRawWithCallback(info, data, callbackForResult);
2564 | });
2565 | });
2566 | }
2567 | /**
2568 | * Raw request with callback.
2569 | * @param info
2570 | * @param data
2571 | * @param onResult
2572 | */
2573 | requestRawWithCallback(info, data, onResult) {
2574 | if (typeof data === 'string') {
2575 | if (!info.options.headers) {
2576 | info.options.headers = {};
2577 | }
2578 | info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
2579 | }
2580 | let callbackCalled = false;
2581 | function handleResult(err, res) {
2582 | if (!callbackCalled) {
2583 | callbackCalled = true;
2584 | onResult(err, res);
2585 | }
2586 | }
2587 | const req = info.httpModule.request(info.options, (msg) => {
2588 | const res = new HttpClientResponse(msg);
2589 | handleResult(undefined, res);
2590 | });
2591 | let socket;
2592 | req.on('socket', sock => {
2593 | socket = sock;
2594 | });
2595 | // If we ever get disconnected, we want the socket to timeout eventually
2596 | req.setTimeout(this._socketTimeout || 3 * 60000, () => {
2597 | if (socket) {
2598 | socket.end();
2599 | }
2600 | handleResult(new Error(`Request timeout: ${info.options.path}`));
2601 | });
2602 | req.on('error', function (err) {
2603 | // err has statusCode property
2604 | // res should have headers
2605 | handleResult(err);
2606 | });
2607 | if (data && typeof data === 'string') {
2608 | req.write(data, 'utf8');
2609 | }
2610 | if (data && typeof data !== 'string') {
2611 | data.on('close', function () {
2612 | req.end();
2613 | });
2614 | data.pipe(req);
2615 | }
2616 | else {
2617 | req.end();
2618 | }
2619 | }
2620 | /**
2621 | * Gets an http agent. This function is useful when you need an http agent that handles
2622 | * routing through a proxy server - depending upon the url and proxy environment variables.
2623 | * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com
2624 | */
2625 | getAgent(serverUrl) {
2626 | const parsedUrl = new URL(serverUrl);
2627 | return this._getAgent(parsedUrl);
2628 | }
2629 | _prepareRequest(method, requestUrl, headers) {
2630 | const info = {};
2631 | info.parsedUrl = requestUrl;
2632 | const usingSsl = info.parsedUrl.protocol === 'https:';
2633 | info.httpModule = usingSsl ? https : http;
2634 | const defaultPort = usingSsl ? 443 : 80;
2635 | info.options = {};
2636 | info.options.host = info.parsedUrl.hostname;
2637 | info.options.port = info.parsedUrl.port
2638 | ? parseInt(info.parsedUrl.port)
2639 | : defaultPort;
2640 | info.options.path =
2641 | (info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');
2642 | info.options.method = method;
2643 | info.options.headers = this._mergeHeaders(headers);
2644 | if (this.userAgent != null) {
2645 | info.options.headers['user-agent'] = this.userAgent;
2646 | }
2647 | info.options.agent = this._getAgent(info.parsedUrl);
2648 | // gives handlers an opportunity to participate
2649 | if (this.handlers) {
2650 | for (const handler of this.handlers) {
2651 | handler.prepareRequest(info.options);
2652 | }
2653 | }
2654 | return info;
2655 | }
2656 | _mergeHeaders(headers) {
2657 | if (this.requestOptions && this.requestOptions.headers) {
2658 | return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {}));
2659 | }
2660 | return lowercaseKeys(headers || {});
2661 | }
2662 | _getExistingOrDefaultHeader(additionalHeaders, header, _default) {
2663 | let clientHeader;
2664 | if (this.requestOptions && this.requestOptions.headers) {
2665 | clientHeader = lowercaseKeys(this.requestOptions.headers)[header];
2666 | }
2667 | return additionalHeaders[header] || clientHeader || _default;
2668 | }
2669 | _getAgent(parsedUrl) {
2670 | let agent;
2671 | const proxyUrl = pm.getProxyUrl(parsedUrl);
2672 | const useProxy = proxyUrl && proxyUrl.hostname;
2673 | if (this._keepAlive && useProxy) {
2674 | agent = this._proxyAgent;
2675 | }
2676 | if (this._keepAlive && !useProxy) {
2677 | agent = this._agent;
2678 | }
2679 | // if agent is already assigned use that agent.
2680 | if (agent) {
2681 | return agent;
2682 | }
2683 | const usingSsl = parsedUrl.protocol === 'https:';
2684 | let maxSockets = 100;
2685 | if (this.requestOptions) {
2686 | maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets;
2687 | }
2688 | // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis.
2689 | if (proxyUrl && proxyUrl.hostname) {
2690 | const agentOptions = {
2691 | maxSockets,
2692 | keepAlive: this._keepAlive,
2693 | proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && {
2694 | proxyAuth: `${proxyUrl.username}:${proxyUrl.password}`
2695 | })), { host: proxyUrl.hostname, port: proxyUrl.port })
2696 | };
2697 | let tunnelAgent;
2698 | const overHttps = proxyUrl.protocol === 'https:';
2699 | if (usingSsl) {
2700 | tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp;
2701 | }
2702 | else {
2703 | tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp;
2704 | }
2705 | agent = tunnelAgent(agentOptions);
2706 | this._proxyAgent = agent;
2707 | }
2708 | // if reusing agent across request and tunneling agent isn't assigned create a new agent
2709 | if (this._keepAlive && !agent) {
2710 | const options = { keepAlive: this._keepAlive, maxSockets };
2711 | agent = usingSsl ? new https.Agent(options) : new http.Agent(options);
2712 | this._agent = agent;
2713 | }
2714 | // if not using private agent and tunnel agent isn't setup then use global agent
2715 | if (!agent) {
2716 | agent = usingSsl ? https.globalAgent : http.globalAgent;
2717 | }
2718 | if (usingSsl && this._ignoreSslError) {
2719 | // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process
2720 | // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options
2721 | // we have to cast it to any and change it directly
2722 | agent.options = Object.assign(agent.options || {}, {
2723 | rejectUnauthorized: false
2724 | });
2725 | }
2726 | return agent;
2727 | }
2728 | _performExponentialBackoff(retryNumber) {
2729 | return __awaiter(this, void 0, void 0, function* () {
2730 | retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);
2731 | const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber);
2732 | return new Promise(resolve => setTimeout(() => resolve(), ms));
2733 | });
2734 | }
2735 | _processResponse(res, options) {
2736 | return __awaiter(this, void 0, void 0, function* () {
2737 | return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
2738 | const statusCode = res.message.statusCode || 0;
2739 | const response = {
2740 | statusCode,
2741 | result: null,
2742 | headers: {}
2743 | };
2744 | // not found leads to null obj returned
2745 | if (statusCode === HttpCodes.NotFound) {
2746 | resolve(response);
2747 | }
2748 | // get the result from the body
2749 | function dateTimeDeserializer(key, value) {
2750 | if (typeof value === 'string') {
2751 | const a = new Date(value);
2752 | if (!isNaN(a.valueOf())) {
2753 | return a;
2754 | }
2755 | }
2756 | return value;
2757 | }
2758 | let obj;
2759 | let contents;
2760 | try {
2761 | contents = yield res.readBody();
2762 | if (contents && contents.length > 0) {
2763 | if (options && options.deserializeDates) {
2764 | obj = JSON.parse(contents, dateTimeDeserializer);
2765 | }
2766 | else {
2767 | obj = JSON.parse(contents);
2768 | }
2769 | response.result = obj;
2770 | }
2771 | response.headers = res.message.headers;
2772 | }
2773 | catch (err) {
2774 | // Invalid resource (contents not json); leaving result obj null
2775 | }
2776 | // note that 3xx redirects are handled by the http layer.
2777 | if (statusCode > 299) {
2778 | let msg;
2779 | // if exception/error in body, attempt to get better error
2780 | if (obj && obj.message) {
2781 | msg = obj.message;
2782 | }
2783 | else if (contents && contents.length > 0) {
2784 | // it may be the case that the exception is in the body message as string
2785 | msg = contents;
2786 | }
2787 | else {
2788 | msg = `Failed request: (${statusCode})`;
2789 | }
2790 | const err = new HttpClientError(msg, statusCode);
2791 | err.result = response.result;
2792 | reject(err);
2793 | }
2794 | else {
2795 | resolve(response);
2796 | }
2797 | }));
2798 | });
2799 | }
2800 | }
2801 | exports.HttpClient = HttpClient;
2802 | const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {});
2803 | //# sourceMappingURL=index.js.map
2804 |
2805 | /***/ }),
2806 |
2807 | /***/ 988:
2808 | /***/ ((__unused_webpack_module, exports) => {
2809 |
2810 | "use strict";
2811 |
2812 | Object.defineProperty(exports, "__esModule", ({ value: true }));
2813 | exports.checkBypass = exports.getProxyUrl = void 0;
2814 | function getProxyUrl(reqUrl) {
2815 | const usingSsl = reqUrl.protocol === 'https:';
2816 | if (checkBypass(reqUrl)) {
2817 | return undefined;
2818 | }
2819 | const proxyVar = (() => {
2820 | if (usingSsl) {
2821 | return process.env['https_proxy'] || process.env['HTTPS_PROXY'];
2822 | }
2823 | else {
2824 | return process.env['http_proxy'] || process.env['HTTP_PROXY'];
2825 | }
2826 | })();
2827 | if (proxyVar) {
2828 | return new URL(proxyVar);
2829 | }
2830 | else {
2831 | return undefined;
2832 | }
2833 | }
2834 | exports.getProxyUrl = getProxyUrl;
2835 | function checkBypass(reqUrl) {
2836 | if (!reqUrl.hostname) {
2837 | return false;
2838 | }
2839 | const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
2840 | if (!noProxy) {
2841 | return false;
2842 | }
2843 | // Determine the request port
2844 | let reqPort;
2845 | if (reqUrl.port) {
2846 | reqPort = Number(reqUrl.port);
2847 | }
2848 | else if (reqUrl.protocol === 'http:') {
2849 | reqPort = 80;
2850 | }
2851 | else if (reqUrl.protocol === 'https:') {
2852 | reqPort = 443;
2853 | }
2854 | // Format the request hostname and hostname with port
2855 | const upperReqHosts = [reqUrl.hostname.toUpperCase()];
2856 | if (typeof reqPort === 'number') {
2857 | upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`);
2858 | }
2859 | // Compare request host against noproxy
2860 | for (const upperNoProxyItem of noProxy
2861 | .split(',')
2862 | .map(x => x.trim().toUpperCase())
2863 | .filter(x => x)) {
2864 | if (upperReqHosts.some(x => x === upperNoProxyItem)) {
2865 | return true;
2866 | }
2867 | }
2868 | return false;
2869 | }
2870 | exports.checkBypass = checkBypass;
2871 | //# sourceMappingURL=proxy.js.map
2872 |
2873 | /***/ }),
2874 |
2875 | /***/ 207:
2876 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
2877 |
2878 | "use strict";
2879 |
2880 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
2881 | if (k2 === undefined) k2 = k;
2882 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
2883 | }) : (function(o, m, k, k2) {
2884 | if (k2 === undefined) k2 = k;
2885 | o[k2] = m[k];
2886 | }));
2887 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
2888 | Object.defineProperty(o, "default", { enumerable: true, value: v });
2889 | }) : function(o, v) {
2890 | o["default"] = v;
2891 | });
2892 | var __importStar = (this && this.__importStar) || function (mod) {
2893 | if (mod && mod.__esModule) return mod;
2894 | var result = {};
2895 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
2896 | __setModuleDefault(result, mod);
2897 | return result;
2898 | };
2899 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2900 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2901 | return new (P || (P = Promise))(function (resolve, reject) {
2902 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2903 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2904 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2905 | step((generator = generator.apply(thisArg, _arguments || [])).next());
2906 | });
2907 | };
2908 | var _a;
2909 | Object.defineProperty(exports, "__esModule", ({ value: true }));
2910 | exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0;
2911 | const fs = __importStar(__nccwpck_require__(896));
2912 | const path = __importStar(__nccwpck_require__(928));
2913 | _a = fs.promises
2914 | // export const {open} = 'fs'
2915 | , exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink;
2916 | // export const {open} = 'fs'
2917 | exports.IS_WINDOWS = process.platform === 'win32';
2918 | // See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691
2919 | exports.UV_FS_O_EXLOCK = 0x10000000;
2920 | exports.READONLY = fs.constants.O_RDONLY;
2921 | function exists(fsPath) {
2922 | return __awaiter(this, void 0, void 0, function* () {
2923 | try {
2924 | yield exports.stat(fsPath);
2925 | }
2926 | catch (err) {
2927 | if (err.code === 'ENOENT') {
2928 | return false;
2929 | }
2930 | throw err;
2931 | }
2932 | return true;
2933 | });
2934 | }
2935 | exports.exists = exists;
2936 | function isDirectory(fsPath, useStat = false) {
2937 | return __awaiter(this, void 0, void 0, function* () {
2938 | const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);
2939 | return stats.isDirectory();
2940 | });
2941 | }
2942 | exports.isDirectory = isDirectory;
2943 | /**
2944 | * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
2945 | * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
2946 | */
2947 | function isRooted(p) {
2948 | p = normalizeSeparators(p);
2949 | if (!p) {
2950 | throw new Error('isRooted() parameter "p" cannot be empty');
2951 | }
2952 | if (exports.IS_WINDOWS) {
2953 | return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello
2954 | ); // e.g. C: or C:\hello
2955 | }
2956 | return p.startsWith('/');
2957 | }
2958 | exports.isRooted = isRooted;
2959 | /**
2960 | * Best effort attempt to determine whether a file exists and is executable.
2961 | * @param filePath file path to check
2962 | * @param extensions additional file extensions to try
2963 | * @return if file exists and is executable, returns the file path. otherwise empty string.
2964 | */
2965 | function tryGetExecutablePath(filePath, extensions) {
2966 | return __awaiter(this, void 0, void 0, function* () {
2967 | let stats = undefined;
2968 | try {
2969 | // test file exists
2970 | stats = yield exports.stat(filePath);
2971 | }
2972 | catch (err) {
2973 | if (err.code !== 'ENOENT') {
2974 | // eslint-disable-next-line no-console
2975 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
2976 | }
2977 | }
2978 | if (stats && stats.isFile()) {
2979 | if (exports.IS_WINDOWS) {
2980 | // on Windows, test for valid extension
2981 | const upperExt = path.extname(filePath).toUpperCase();
2982 | if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {
2983 | return filePath;
2984 | }
2985 | }
2986 | else {
2987 | if (isUnixExecutable(stats)) {
2988 | return filePath;
2989 | }
2990 | }
2991 | }
2992 | // try each extension
2993 | const originalFilePath = filePath;
2994 | for (const extension of extensions) {
2995 | filePath = originalFilePath + extension;
2996 | stats = undefined;
2997 | try {
2998 | stats = yield exports.stat(filePath);
2999 | }
3000 | catch (err) {
3001 | if (err.code !== 'ENOENT') {
3002 | // eslint-disable-next-line no-console
3003 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
3004 | }
3005 | }
3006 | if (stats && stats.isFile()) {
3007 | if (exports.IS_WINDOWS) {
3008 | // preserve the case of the actual file (since an extension was appended)
3009 | try {
3010 | const directory = path.dirname(filePath);
3011 | const upperName = path.basename(filePath).toUpperCase();
3012 | for (const actualName of yield exports.readdir(directory)) {
3013 | if (upperName === actualName.toUpperCase()) {
3014 | filePath = path.join(directory, actualName);
3015 | break;
3016 | }
3017 | }
3018 | }
3019 | catch (err) {
3020 | // eslint-disable-next-line no-console
3021 | console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);
3022 | }
3023 | return filePath;
3024 | }
3025 | else {
3026 | if (isUnixExecutable(stats)) {
3027 | return filePath;
3028 | }
3029 | }
3030 | }
3031 | }
3032 | return '';
3033 | });
3034 | }
3035 | exports.tryGetExecutablePath = tryGetExecutablePath;
3036 | function normalizeSeparators(p) {
3037 | p = p || '';
3038 | if (exports.IS_WINDOWS) {
3039 | // convert slashes on Windows
3040 | p = p.replace(/\//g, '\\');
3041 | // remove redundant slashes
3042 | return p.replace(/\\\\+/g, '\\');
3043 | }
3044 | // remove redundant slashes
3045 | return p.replace(/\/\/+/g, '/');
3046 | }
3047 | // on Mac/Linux, test the execute bit
3048 | // R W X R W X R W X
3049 | // 256 128 64 32 16 8 4 2 1
3050 | function isUnixExecutable(stats) {
3051 | return ((stats.mode & 1) > 0 ||
3052 | ((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||
3053 | ((stats.mode & 64) > 0 && stats.uid === process.getuid()));
3054 | }
3055 | // Get the path of cmd.exe in windows
3056 | function getCmdPath() {
3057 | var _a;
3058 | return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`;
3059 | }
3060 | exports.getCmdPath = getCmdPath;
3061 | //# sourceMappingURL=io-util.js.map
3062 |
3063 | /***/ }),
3064 |
3065 | /***/ 994:
3066 | /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
3067 |
3068 | "use strict";
3069 |
3070 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3071 | if (k2 === undefined) k2 = k;
3072 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
3073 | }) : (function(o, m, k, k2) {
3074 | if (k2 === undefined) k2 = k;
3075 | o[k2] = m[k];
3076 | }));
3077 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
3078 | Object.defineProperty(o, "default", { enumerable: true, value: v });
3079 | }) : function(o, v) {
3080 | o["default"] = v;
3081 | });
3082 | var __importStar = (this && this.__importStar) || function (mod) {
3083 | if (mod && mod.__esModule) return mod;
3084 | var result = {};
3085 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
3086 | __setModuleDefault(result, mod);
3087 | return result;
3088 | };
3089 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3090 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3091 | return new (P || (P = Promise))(function (resolve, reject) {
3092 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
3093 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3094 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
3095 | step((generator = generator.apply(thisArg, _arguments || [])).next());
3096 | });
3097 | };
3098 | Object.defineProperty(exports, "__esModule", ({ value: true }));
3099 | exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0;
3100 | const assert_1 = __nccwpck_require__(613);
3101 | const path = __importStar(__nccwpck_require__(928));
3102 | const ioUtil = __importStar(__nccwpck_require__(207));
3103 | /**
3104 | * Copies a file or folder.
3105 | * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js
3106 | *
3107 | * @param source source path
3108 | * @param dest destination path
3109 | * @param options optional. See CopyOptions.
3110 | */
3111 | function cp(source, dest, options = {}) {
3112 | return __awaiter(this, void 0, void 0, function* () {
3113 | const { force, recursive, copySourceDirectory } = readCopyOptions(options);
3114 | const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null;
3115 | // Dest is an existing file, but not forcing
3116 | if (destStat && destStat.isFile() && !force) {
3117 | return;
3118 | }
3119 | // If dest is an existing directory, should copy inside.
3120 | const newDest = destStat && destStat.isDirectory() && copySourceDirectory
3121 | ? path.join(dest, path.basename(source))
3122 | : dest;
3123 | if (!(yield ioUtil.exists(source))) {
3124 | throw new Error(`no such file or directory: ${source}`);
3125 | }
3126 | const sourceStat = yield ioUtil.stat(source);
3127 | if (sourceStat.isDirectory()) {
3128 | if (!recursive) {
3129 | throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);
3130 | }
3131 | else {
3132 | yield cpDirRecursive(source, newDest, 0, force);
3133 | }
3134 | }
3135 | else {
3136 | if (path.relative(source, newDest) === '') {
3137 | // a file cannot be copied to itself
3138 | throw new Error(`'${newDest}' and '${source}' are the same file`);
3139 | }
3140 | yield copyFile(source, newDest, force);
3141 | }
3142 | });
3143 | }
3144 | exports.cp = cp;
3145 | /**
3146 | * Moves a path.
3147 | *
3148 | * @param source source path
3149 | * @param dest destination path
3150 | * @param options optional. See MoveOptions.
3151 | */
3152 | function mv(source, dest, options = {}) {
3153 | return __awaiter(this, void 0, void 0, function* () {
3154 | if (yield ioUtil.exists(dest)) {
3155 | let destExists = true;
3156 | if (yield ioUtil.isDirectory(dest)) {
3157 | // If dest is directory copy src into dest
3158 | dest = path.join(dest, path.basename(source));
3159 | destExists = yield ioUtil.exists(dest);
3160 | }
3161 | if (destExists) {
3162 | if (options.force == null || options.force) {
3163 | yield rmRF(dest);
3164 | }
3165 | else {
3166 | throw new Error('Destination already exists');
3167 | }
3168 | }
3169 | }
3170 | yield mkdirP(path.dirname(dest));
3171 | yield ioUtil.rename(source, dest);
3172 | });
3173 | }
3174 | exports.mv = mv;
3175 | /**
3176 | * Remove a path recursively with force
3177 | *
3178 | * @param inputPath path to remove
3179 | */
3180 | function rmRF(inputPath) {
3181 | return __awaiter(this, void 0, void 0, function* () {
3182 | if (ioUtil.IS_WINDOWS) {
3183 | // Check for invalid characters
3184 | // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
3185 | if (/[*"<>|]/.test(inputPath)) {
3186 | throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows');
3187 | }
3188 | }
3189 | try {
3190 | // note if path does not exist, error is silent
3191 | yield ioUtil.rm(inputPath, {
3192 | force: true,
3193 | maxRetries: 3,
3194 | recursive: true,
3195 | retryDelay: 300
3196 | });
3197 | }
3198 | catch (err) {
3199 | throw new Error(`File was unable to be removed ${err}`);
3200 | }
3201 | });
3202 | }
3203 | exports.rmRF = rmRF;
3204 | /**
3205 | * Make a directory. Creates the full path with folders in between
3206 | * Will throw if it fails
3207 | *
3208 | * @param fsPath path to create
3209 | * @returns Promise
3210 | */
3211 | function mkdirP(fsPath) {
3212 | return __awaiter(this, void 0, void 0, function* () {
3213 | assert_1.ok(fsPath, 'a path argument must be provided');
3214 | yield ioUtil.mkdir(fsPath, { recursive: true });
3215 | });
3216 | }
3217 | exports.mkdirP = mkdirP;
3218 | /**
3219 | * Returns path of a tool had the tool actually been invoked. Resolves via paths.
3220 | * If you check and the tool does not exist, it will throw.
3221 | *
3222 | * @param tool name of the tool
3223 | * @param check whether to check if tool exists
3224 | * @returns Promise path to tool
3225 | */
3226 | function which(tool, check) {
3227 | return __awaiter(this, void 0, void 0, function* () {
3228 | if (!tool) {
3229 | throw new Error("parameter 'tool' is required");
3230 | }
3231 | // recursive when check=true
3232 | if (check) {
3233 | const result = yield which(tool, false);
3234 | if (!result) {
3235 | if (ioUtil.IS_WINDOWS) {
3236 | 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.`);
3237 | }
3238 | else {
3239 | 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.`);
3240 | }
3241 | }
3242 | return result;
3243 | }
3244 | const matches = yield findInPath(tool);
3245 | if (matches && matches.length > 0) {
3246 | return matches[0];
3247 | }
3248 | return '';
3249 | });
3250 | }
3251 | exports.which = which;
3252 | /**
3253 | * Returns a list of all occurrences of the given tool on the system path.
3254 | *
3255 | * @returns Promise the paths of the tool
3256 | */
3257 | function findInPath(tool) {
3258 | return __awaiter(this, void 0, void 0, function* () {
3259 | if (!tool) {
3260 | throw new Error("parameter 'tool' is required");
3261 | }
3262 | // build the list of extensions to try
3263 | const extensions = [];
3264 | if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) {
3265 | for (const extension of process.env['PATHEXT'].split(path.delimiter)) {
3266 | if (extension) {
3267 | extensions.push(extension);
3268 | }
3269 | }
3270 | }
3271 | // if it's rooted, return it if exists. otherwise return empty.
3272 | if (ioUtil.isRooted(tool)) {
3273 | const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);
3274 | if (filePath) {
3275 | return [filePath];
3276 | }
3277 | return [];
3278 | }
3279 | // if any path separators, return empty
3280 | if (tool.includes(path.sep)) {
3281 | return [];
3282 | }
3283 | // build the list of directories
3284 | //
3285 | // Note, technically "where" checks the current directory on Windows. From a toolkit perspective,
3286 | // it feels like we should not do this. Checking the current directory seems like more of a use
3287 | // case of a shell, and the which() function exposed by the toolkit should strive for consistency
3288 | // across platforms.
3289 | const directories = [];
3290 | if (process.env.PATH) {
3291 | for (const p of process.env.PATH.split(path.delimiter)) {
3292 | if (p) {
3293 | directories.push(p);
3294 | }
3295 | }
3296 | }
3297 | // find all matches
3298 | const matches = [];
3299 | for (const directory of directories) {
3300 | const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions);
3301 | if (filePath) {
3302 | matches.push(filePath);
3303 | }
3304 | }
3305 | return matches;
3306 | });
3307 | }
3308 | exports.findInPath = findInPath;
3309 | function readCopyOptions(options) {
3310 | const force = options.force == null ? true : options.force;
3311 | const recursive = Boolean(options.recursive);
3312 | const copySourceDirectory = options.copySourceDirectory == null
3313 | ? true
3314 | : Boolean(options.copySourceDirectory);
3315 | return { force, recursive, copySourceDirectory };
3316 | }
3317 | function cpDirRecursive(sourceDir, destDir, currentDepth, force) {
3318 | return __awaiter(this, void 0, void 0, function* () {
3319 | // Ensure there is not a run away recursive copy
3320 | if (currentDepth >= 255)
3321 | return;
3322 | currentDepth++;
3323 | yield mkdirP(destDir);
3324 | const files = yield ioUtil.readdir(sourceDir);
3325 | for (const fileName of files) {
3326 | const srcFile = `${sourceDir}/${fileName}`;
3327 | const destFile = `${destDir}/${fileName}`;
3328 | const srcFileStat = yield ioUtil.lstat(srcFile);
3329 | if (srcFileStat.isDirectory()) {
3330 | // Recurse
3331 | yield cpDirRecursive(srcFile, destFile, currentDepth, force);
3332 | }
3333 | else {
3334 | yield copyFile(srcFile, destFile, force);
3335 | }
3336 | }
3337 | // Change the mode for the newly created directory
3338 | yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode);
3339 | });
3340 | }
3341 | // Buffered file copy
3342 | function copyFile(srcFile, destFile, force) {
3343 | return __awaiter(this, void 0, void 0, function* () {
3344 | if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) {
3345 | // unlink/re-link it
3346 | try {
3347 | yield ioUtil.lstat(destFile);
3348 | yield ioUtil.unlink(destFile);
3349 | }
3350 | catch (e) {
3351 | // Try to override file permission
3352 | if (e.code === 'EPERM') {
3353 | yield ioUtil.chmod(destFile, '0666');
3354 | yield ioUtil.unlink(destFile);
3355 | }
3356 | // other errors = it doesn't exist, no work to do
3357 | }
3358 | // Copy over symlink
3359 | const symlinkFull = yield ioUtil.readlink(srcFile);
3360 | yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null);
3361 | }
3362 | else if (!(yield ioUtil.exists(destFile)) || force) {
3363 | yield ioUtil.copyFile(srcFile, destFile);
3364 | }
3365 | });
3366 | }
3367 | //# sourceMappingURL=io.js.map
3368 |
3369 | /***/ }),
3370 |
3371 | /***/ 770:
3372 | /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
3373 |
3374 | module.exports = __nccwpck_require__(218);
3375 |
3376 |
3377 | /***/ }),
3378 |
3379 | /***/ 218:
3380 | /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
3381 |
3382 | "use strict";
3383 |
3384 |
3385 | var net = __nccwpck_require__(278);
3386 | var tls = __nccwpck_require__(756);
3387 | var http = __nccwpck_require__(611);
3388 | var https = __nccwpck_require__(692);
3389 | var events = __nccwpck_require__(434);
3390 | var assert = __nccwpck_require__(613);
3391 | var util = __nccwpck_require__(23);
3392 |
3393 |
3394 | exports.httpOverHttp = httpOverHttp;
3395 | exports.httpsOverHttp = httpsOverHttp;
3396 | exports.httpOverHttps = httpOverHttps;
3397 | exports.httpsOverHttps = httpsOverHttps;
3398 |
3399 |
3400 | function httpOverHttp(options) {
3401 | var agent = new TunnelingAgent(options);
3402 | agent.request = http.request;
3403 | return agent;
3404 | }
3405 |
3406 | function httpsOverHttp(options) {
3407 | var agent = new TunnelingAgent(options);
3408 | agent.request = http.request;
3409 | agent.createSocket = createSecureSocket;
3410 | agent.defaultPort = 443;
3411 | return agent;
3412 | }
3413 |
3414 | function httpOverHttps(options) {
3415 | var agent = new TunnelingAgent(options);
3416 | agent.request = https.request;
3417 | return agent;
3418 | }
3419 |
3420 | function httpsOverHttps(options) {
3421 | var agent = new TunnelingAgent(options);
3422 | agent.request = https.request;
3423 | agent.createSocket = createSecureSocket;
3424 | agent.defaultPort = 443;
3425 | return agent;
3426 | }
3427 |
3428 |
3429 | function TunnelingAgent(options) {
3430 | var self = this;
3431 | self.options = options || {};
3432 | self.proxyOptions = self.options.proxy || {};
3433 | self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets;
3434 | self.requests = [];
3435 | self.sockets = [];
3436 |
3437 | self.on('free', function onFree(socket, host, port, localAddress) {
3438 | var options = toOptions(host, port, localAddress);
3439 | for (var i = 0, len = self.requests.length; i < len; ++i) {
3440 | var pending = self.requests[i];
3441 | if (pending.host === options.host && pending.port === options.port) {
3442 | // Detect the request to connect same origin server,
3443 | // reuse the connection.
3444 | self.requests.splice(i, 1);
3445 | pending.request.onSocket(socket);
3446 | return;
3447 | }
3448 | }
3449 | socket.destroy();
3450 | self.removeSocket(socket);
3451 | });
3452 | }
3453 | util.inherits(TunnelingAgent, events.EventEmitter);
3454 |
3455 | TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) {
3456 | var self = this;
3457 | var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress));
3458 |
3459 | if (self.sockets.length >= this.maxSockets) {
3460 | // We are over limit so we'll add it to the queue.
3461 | self.requests.push(options);
3462 | return;
3463 | }
3464 |
3465 | // If we are under maxSockets create a new one.
3466 | self.createSocket(options, function(socket) {
3467 | socket.on('free', onFree);
3468 | socket.on('close', onCloseOrRemove);
3469 | socket.on('agentRemove', onCloseOrRemove);
3470 | req.onSocket(socket);
3471 |
3472 | function onFree() {
3473 | self.emit('free', socket, options);
3474 | }
3475 |
3476 | function onCloseOrRemove(err) {
3477 | self.removeSocket(socket);
3478 | socket.removeListener('free', onFree);
3479 | socket.removeListener('close', onCloseOrRemove);
3480 | socket.removeListener('agentRemove', onCloseOrRemove);
3481 | }
3482 | });
3483 | };
3484 |
3485 | TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
3486 | var self = this;
3487 | var placeholder = {};
3488 | self.sockets.push(placeholder);
3489 |
3490 | var connectOptions = mergeOptions({}, self.proxyOptions, {
3491 | method: 'CONNECT',
3492 | path: options.host + ':' + options.port,
3493 | agent: false,
3494 | headers: {
3495 | host: options.host + ':' + options.port
3496 | }
3497 | });
3498 | if (options.localAddress) {
3499 | connectOptions.localAddress = options.localAddress;
3500 | }
3501 | if (connectOptions.proxyAuth) {
3502 | connectOptions.headers = connectOptions.headers || {};
3503 | connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
3504 | new Buffer(connectOptions.proxyAuth).toString('base64');
3505 | }
3506 |
3507 | debug('making CONNECT request');
3508 | var connectReq = self.request(connectOptions);
3509 | connectReq.useChunkedEncodingByDefault = false; // for v0.6
3510 | connectReq.once('response', onResponse); // for v0.6
3511 | connectReq.once('upgrade', onUpgrade); // for v0.6
3512 | connectReq.once('connect', onConnect); // for v0.7 or later
3513 | connectReq.once('error', onError);
3514 | connectReq.end();
3515 |
3516 | function onResponse(res) {
3517 | // Very hacky. This is necessary to avoid http-parser leaks.
3518 | res.upgrade = true;
3519 | }
3520 |
3521 | function onUpgrade(res, socket, head) {
3522 | // Hacky.
3523 | process.nextTick(function() {
3524 | onConnect(res, socket, head);
3525 | });
3526 | }
3527 |
3528 | function onConnect(res, socket, head) {
3529 | connectReq.removeAllListeners();
3530 | socket.removeAllListeners();
3531 |
3532 | if (res.statusCode !== 200) {
3533 | debug('tunneling socket could not be established, statusCode=%d',
3534 | res.statusCode);
3535 | socket.destroy();
3536 | var error = new Error('tunneling socket could not be established, ' +
3537 | 'statusCode=' + res.statusCode);
3538 | error.code = 'ECONNRESET';
3539 | options.request.emit('error', error);
3540 | self.removeSocket(placeholder);
3541 | return;
3542 | }
3543 | if (head.length > 0) {
3544 | debug('got illegal response body from proxy');
3545 | socket.destroy();
3546 | var error = new Error('got illegal response body from proxy');
3547 | error.code = 'ECONNRESET';
3548 | options.request.emit('error', error);
3549 | self.removeSocket(placeholder);
3550 | return;
3551 | }
3552 | debug('tunneling connection has established');
3553 | self.sockets[self.sockets.indexOf(placeholder)] = socket;
3554 | return cb(socket);
3555 | }
3556 |
3557 | function onError(cause) {
3558 | connectReq.removeAllListeners();
3559 |
3560 | debug('tunneling socket could not be established, cause=%s\n',
3561 | cause.message, cause.stack);
3562 | var error = new Error('tunneling socket could not be established, ' +
3563 | 'cause=' + cause.message);
3564 | error.code = 'ECONNRESET';
3565 | options.request.emit('error', error);
3566 | self.removeSocket(placeholder);
3567 | }
3568 | };
3569 |
3570 | TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
3571 | var pos = this.sockets.indexOf(socket)
3572 | if (pos === -1) {
3573 | return;
3574 | }
3575 | this.sockets.splice(pos, 1);
3576 |
3577 | var pending = this.requests.shift();
3578 | if (pending) {
3579 | // If we have pending requests and a socket gets closed a new one
3580 | // needs to be created to take over in the pool for the one that closed.
3581 | this.createSocket(pending, function(socket) {
3582 | pending.request.onSocket(socket);
3583 | });
3584 | }
3585 | };
3586 |
3587 | function createSecureSocket(options, cb) {
3588 | var self = this;
3589 | TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
3590 | var hostHeader = options.request.getHeader('host');
3591 | var tlsOptions = mergeOptions({}, self.options, {
3592 | socket: socket,
3593 | servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host
3594 | });
3595 |
3596 | // 0 is dummy port for v0.6
3597 | var secureSocket = tls.connect(0, tlsOptions);
3598 | self.sockets[self.sockets.indexOf(socket)] = secureSocket;
3599 | cb(secureSocket);
3600 | });
3601 | }
3602 |
3603 |
3604 | function toOptions(host, port, localAddress) {
3605 | if (typeof host === 'string') { // since v0.10
3606 | return {
3607 | host: host,
3608 | port: port,
3609 | localAddress: localAddress
3610 | };
3611 | }
3612 | return host; // for v0.11 or later
3613 | }
3614 |
3615 | function mergeOptions(target) {
3616 | for (var i = 1, len = arguments.length; i < len; ++i) {
3617 | var overrides = arguments[i];
3618 | if (typeof overrides === 'object') {
3619 | var keys = Object.keys(overrides);
3620 | for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
3621 | var k = keys[j];
3622 | if (overrides[k] !== undefined) {
3623 | target[k] = overrides[k];
3624 | }
3625 | }
3626 | }
3627 | }
3628 | return target;
3629 | }
3630 |
3631 |
3632 | var debug;
3633 | if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
3634 | debug = function() {
3635 | var args = Array.prototype.slice.call(arguments);
3636 | if (typeof args[0] === 'string') {
3637 | args[0] = 'TUNNEL: ' + args[0];
3638 | } else {
3639 | args.unshift('TUNNEL:');
3640 | }
3641 | console.error.apply(console, args);
3642 | }
3643 | } else {
3644 | debug = function() {};
3645 | }
3646 | exports.debug = debug; // for test
3647 |
3648 |
3649 | /***/ }),
3650 |
3651 | /***/ 613:
3652 | /***/ ((module) => {
3653 |
3654 | "use strict";
3655 | module.exports = require("assert");
3656 |
3657 | /***/ }),
3658 |
3659 | /***/ 317:
3660 | /***/ ((module) => {
3661 |
3662 | "use strict";
3663 | module.exports = require("child_process");
3664 |
3665 | /***/ }),
3666 |
3667 | /***/ 982:
3668 | /***/ ((module) => {
3669 |
3670 | "use strict";
3671 | module.exports = require("crypto");
3672 |
3673 | /***/ }),
3674 |
3675 | /***/ 434:
3676 | /***/ ((module) => {
3677 |
3678 | "use strict";
3679 | module.exports = require("events");
3680 |
3681 | /***/ }),
3682 |
3683 | /***/ 896:
3684 | /***/ ((module) => {
3685 |
3686 | "use strict";
3687 | module.exports = require("fs");
3688 |
3689 | /***/ }),
3690 |
3691 | /***/ 611:
3692 | /***/ ((module) => {
3693 |
3694 | "use strict";
3695 | module.exports = require("http");
3696 |
3697 | /***/ }),
3698 |
3699 | /***/ 692:
3700 | /***/ ((module) => {
3701 |
3702 | "use strict";
3703 | module.exports = require("https");
3704 |
3705 | /***/ }),
3706 |
3707 | /***/ 278:
3708 | /***/ ((module) => {
3709 |
3710 | "use strict";
3711 | module.exports = require("net");
3712 |
3713 | /***/ }),
3714 |
3715 | /***/ 857:
3716 | /***/ ((module) => {
3717 |
3718 | "use strict";
3719 | module.exports = require("os");
3720 |
3721 | /***/ }),
3722 |
3723 | /***/ 928:
3724 | /***/ ((module) => {
3725 |
3726 | "use strict";
3727 | module.exports = require("path");
3728 |
3729 | /***/ }),
3730 |
3731 | /***/ 193:
3732 | /***/ ((module) => {
3733 |
3734 | "use strict";
3735 | module.exports = require("string_decoder");
3736 |
3737 | /***/ }),
3738 |
3739 | /***/ 557:
3740 | /***/ ((module) => {
3741 |
3742 | "use strict";
3743 | module.exports = require("timers");
3744 |
3745 | /***/ }),
3746 |
3747 | /***/ 756:
3748 | /***/ ((module) => {
3749 |
3750 | "use strict";
3751 | module.exports = require("tls");
3752 |
3753 | /***/ }),
3754 |
3755 | /***/ 23:
3756 | /***/ ((module) => {
3757 |
3758 | "use strict";
3759 | module.exports = require("util");
3760 |
3761 | /***/ })
3762 |
3763 | /******/ });
3764 | /************************************************************************/
3765 | /******/ // The module cache
3766 | /******/ var __webpack_module_cache__ = {};
3767 | /******/
3768 | /******/ // The require function
3769 | /******/ function __nccwpck_require__(moduleId) {
3770 | /******/ // Check if module is in cache
3771 | /******/ var cachedModule = __webpack_module_cache__[moduleId];
3772 | /******/ if (cachedModule !== undefined) {
3773 | /******/ return cachedModule.exports;
3774 | /******/ }
3775 | /******/ // Create a new module (and put it into the cache)
3776 | /******/ var module = __webpack_module_cache__[moduleId] = {
3777 | /******/ // no module.id needed
3778 | /******/ // no module.loaded needed
3779 | /******/ exports: {}
3780 | /******/ };
3781 | /******/
3782 | /******/ // Execute the module function
3783 | /******/ var threw = true;
3784 | /******/ try {
3785 | /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__);
3786 | /******/ threw = false;
3787 | /******/ } finally {
3788 | /******/ if(threw) delete __webpack_module_cache__[moduleId];
3789 | /******/ }
3790 | /******/
3791 | /******/ // Return the exports of the module
3792 | /******/ return module.exports;
3793 | /******/ }
3794 | /******/
3795 | /************************************************************************/
3796 | /******/ /* webpack/runtime/compat */
3797 | /******/
3798 | /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
3799 | /******/
3800 | /************************************************************************/
3801 | /******/
3802 | /******/ // startup
3803 | /******/ // Load entry module and return exports
3804 | /******/ // This entry module is referenced by other modules so it can't be inlined
3805 | /******/ var __webpack_exports__ = __nccwpck_require__(915);
3806 | /******/ module.exports = __webpack_exports__;
3807 | /******/
3808 | /******/ })()
3809 | ;
--------------------------------------------------------------------------------
/dist/license.txt:
--------------------------------------------------------------------------------
1 | @actions/core
2 | MIT
3 | The MIT License (MIT)
4 |
5 | Copyright 2019 GitHub
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | @actions/exec
14 | MIT
15 | The MIT License (MIT)
16 |
17 | Copyright 2019 GitHub
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | @actions/http-client
26 | MIT
27 | Actions Http Client for Node.js
28 |
29 | Copyright (c) GitHub, Inc.
30 |
31 | All rights reserved.
32 |
33 | MIT License
34 |
35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
36 | associated documentation files (the "Software"), to deal in the Software without restriction,
37 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
38 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
39 | subject to the following conditions:
40 |
41 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
42 |
43 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
44 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
45 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
46 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 |
49 |
50 | @actions/io
51 | MIT
52 | The MIT License (MIT)
53 |
54 | Copyright 2019 GitHub
55 |
56 | 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:
57 |
58 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
59 |
60 | 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.
61 |
62 | tunnel
63 | MIT
64 | The MIT License (MIT)
65 |
66 | Copyright (c) 2012 Koichi Kobayashi
67 |
68 | Permission is hereby granted, free of charge, to any person obtaining a copy
69 | of this software and associated documentation files (the "Software"), to deal
70 | in the Software without restriction, including without limitation the rights
71 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
72 | copies of the Software, and to permit persons to whom the Software is
73 | furnished to do so, subject to the following conditions:
74 |
75 | The above copyright notice and this permission notice shall be included in
76 | all copies or substantial portions of the Software.
77 |
78 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
82 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
83 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
84 | THE SOFTWARE.
85 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "swift-coverage-action",
3 | "version": "4.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "swift-coverage-action",
9 | "version": "4.0.0",
10 | "license": "Apache-2.0",
11 | "dependencies": {
12 | "@actions/core": "^1.11.1",
13 | "@actions/exec": "^1.1.1",
14 | "@actions/io": "^1.1.3"
15 | },
16 | "devDependencies": {
17 | "@tsconfig/node20": "^20.1.5",
18 | "@types/node": "^20.19.0",
19 | "@vercel/ncc": "^0.38.3",
20 | "typescript": "^5.8.3"
21 | },
22 | "engines": {
23 | "node": ">=20"
24 | }
25 | },
26 | "node_modules/@actions/core": {
27 | "version": "1.11.1",
28 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
29 | "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
30 | "dependencies": {
31 | "@actions/exec": "^1.1.1",
32 | "@actions/http-client": "^2.0.1"
33 | }
34 | },
35 | "node_modules/@actions/exec": {
36 | "version": "1.1.1",
37 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
38 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
39 | "dependencies": {
40 | "@actions/io": "^1.0.1"
41 | }
42 | },
43 | "node_modules/@actions/http-client": {
44 | "version": "2.0.1",
45 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
46 | "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
47 | "dependencies": {
48 | "tunnel": "^0.0.6"
49 | }
50 | },
51 | "node_modules/@actions/io": {
52 | "version": "1.1.3",
53 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
54 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
55 | },
56 | "node_modules/@tsconfig/node20": {
57 | "version": "20.1.5",
58 | "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.5.tgz",
59 | "integrity": "sha512-Vm8e3WxDTqMGPU4GATF9keQAIy1Drd7bPwlgzKJnZtoOsTm1tduUTbDjg0W5qERvGuxPI2h9RbMufH0YdfBylA==",
60 | "dev": true,
61 | "license": "MIT"
62 | },
63 | "node_modules/@types/node": {
64 | "version": "20.19.0",
65 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.0.tgz",
66 | "integrity": "sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==",
67 | "dev": true,
68 | "license": "MIT",
69 | "dependencies": {
70 | "undici-types": "~6.21.0"
71 | }
72 | },
73 | "node_modules/@vercel/ncc": {
74 | "version": "0.38.3",
75 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz",
76 | "integrity": "sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA==",
77 | "dev": true,
78 | "bin": {
79 | "ncc": "dist/ncc/cli.js"
80 | }
81 | },
82 | "node_modules/tunnel": {
83 | "version": "0.0.6",
84 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
85 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
86 | "engines": {
87 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
88 | }
89 | },
90 | "node_modules/typescript": {
91 | "version": "5.8.3",
92 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
93 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
94 | "dev": true,
95 | "license": "Apache-2.0",
96 | "bin": {
97 | "tsc": "bin/tsc",
98 | "tsserver": "bin/tsserver"
99 | },
100 | "engines": {
101 | "node": ">=14.17"
102 | }
103 | },
104 | "node_modules/undici-types": {
105 | "version": "6.21.0",
106 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
107 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
108 | "dev": true,
109 | "license": "MIT"
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "swift-coverage-action",
3 | "version": "4.0.0",
4 | "description": "A GitHub action that converts Swift / Xcode code coverage files.",
5 | "engines": {
6 | "node": ">=20"
7 | },
8 | "exports": {
9 | ".": "./dist/index.js"
10 | },
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1",
13 | "build": "tsc",
14 | "pack": "rm -rf dist && ncc build lib/main.js -o dist --license license.txt --target es2022"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/sersoft-gmbh/swift-coverage-action.git"
19 | },
20 | "keywords": [
21 | "Swift",
22 | "Xcode",
23 | "LLVM",
24 | "Coverage",
25 | "Codecov"
26 | ],
27 | "author": "ser.soft GmbH",
28 | "license": "Apache-2.0",
29 | "bugs": {
30 | "url": "https://github.com/sersoft-gmbh/swift-coverage-action/issues"
31 | },
32 | "homepage": "https://github.com/sersoft-gmbh/swift-coverage-action#readme",
33 | "dependencies": {
34 | "@actions/core": "^1.11.1",
35 | "@actions/exec": "^1.1.1",
36 | "@actions/io": "^1.1.3"
37 | },
38 | "devDependencies": {
39 | "@tsconfig/node20": "^20.1.5",
40 | "@types/node": "^20.19.0",
41 | "@vercel/ncc": "^0.38.3",
42 | "typescript": "^5.8.3"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 | import { getExecOutput } from '@actions/exec';
3 | import * as io from '@actions/io';
4 | import { existsSync as exists, PathLike, promises as fs } from 'fs';
5 | import * as path from 'path';
6 | import * as os from 'os';
7 |
8 | async function runCmd(cmd: string, ...args: string[]): Promise {
9 | const output = await getExecOutput(cmd, args.length <= 0 ? undefined : args, { silent: !core.isDebug() });
10 | if (output.stderr.length > 0)
11 | core.warning(`Command execution wrote lines to stderr:\n${output.stderr}`);
12 | return output.stdout;
13 | }
14 |
15 | enum CovFormat {
16 | txt = 'txt',
17 | lcov = 'lcov',
18 | }
19 |
20 | declare type WalkEntry = {
21 | path: string;
22 | isDirectory: boolean;
23 |
24 | skipDescendants(): void;
25 | };
26 |
27 | // Taken and adjusted from https://stackoverflow.com/a/65415138/1388842
28 | async function* walk(dir: string, onlyFiles: boolean = true): AsyncGenerator {
29 | const entries = await fs.readdir(dir, { withFileTypes: true });
30 | for (const entry of entries) {
31 | const res = path.resolve(dir, entry.name);
32 | if (entry.isDirectory()) {
33 | let skipDesc = false;
34 | if (!onlyFiles)
35 | yield { path: res, isDirectory: true, skipDescendants: () => skipDesc = true };
36 | if (!skipDesc)
37 | yield* walk(res, onlyFiles);
38 | } else {
39 | yield { path: res, isDirectory: false, skipDescendants: () => {} };
40 | }
41 | }
42 | }
43 |
44 | async function directoryExists(path: PathLike): Promise {
45 | if (!exists(path)) return false;
46 | const stat = await fs.stat(path);
47 | return stat.isDirectory();
48 | }
49 |
50 | async function fileExists(path: PathLike): Promise {
51 | if (!exists(path)) return false;
52 | const stat = await fs.stat(path);
53 | return stat.isFile();
54 | }
55 |
56 | async function main() {
57 | switch (process.platform) {
58 | case 'darwin': break;
59 | case 'linux': break;
60 | default: throw new Error('This action only supports macOS and Linux!');
61 | }
62 |
63 | core.startGroup('Validating input');
64 | const searchPaths = core.getMultilineInput('search-paths', { required: true })
65 | .map(p => path.resolve(p.replace(/(~|\$HOME|\${HOME})/g, os.homedir)));
66 | const outputFolder = path.resolve(core.getInput('output', { required: true })
67 | .replace(/(~|\$HOME|\${HOME})/g, os.homedir));
68 | const _format = core.getInput('format', { required: true })
69 | const format = CovFormat[_format as keyof typeof CovFormat];
70 | if (!format) throw new Error(`Invalid format: ${_format}`);
71 | const _targetNameFilter = core.getInput('target-name-filter');
72 | const targetNameFilter = _targetNameFilter ? new RegExp(_targetNameFilter) : null;
73 | const ignoreConversionFailures = core.getBooleanInput('ignore-conversion-failures');
74 | const failOnEmptyOutput = core.getBooleanInput('fail-on-empty-output');
75 | core.endGroup();
76 |
77 | await core.group('Setting up paths', async () => {
78 | await io.rmRF(outputFolder);
79 | await io.mkdirP(outputFolder);
80 | });
81 |
82 | const profDataFiles = await core.group('Finding coverage files', async () => {
83 | let profDataFiles: string[] = [];
84 | for (const searchPath of searchPaths) {
85 | if (!await directoryExists(searchPath)) {
86 | core.info(`Skipping non-existent search path ${searchPath}...`);
87 | continue;
88 | }
89 | for await (const entry of walk(searchPath, true)) {
90 | if (/.*\.profdata$/.test(entry.path)) {
91 | profDataFiles.push(entry.path);
92 | core.debug(`Found profdata file: ${entry.path}`);
93 | }
94 | }
95 | }
96 | core.info(`Found ${profDataFiles.length} profiling data file(s):\n${profDataFiles.join('\n')}`);
97 | return profDataFiles;
98 | });
99 |
100 | let convertedFiles: string[] = [];
101 | if (profDataFiles.length > 0) {
102 | convertedFiles = await core.group('Converting files', async () => {
103 | let outFiles: string[] = [];
104 | let conversionFailures: Error[] = [];
105 | let processedTargets = new Set();
106 | for (const profDataFile of profDataFiles) {
107 | const profDataDir = path.dirname(profDataFile);
108 | const xcodeRegex = /(Build).*/;
109 | let buildDir: string;
110 | let isXcode: boolean;
111 | if (xcodeRegex.test(profDataDir)) {
112 | buildDir = profDataDir.replace(xcodeRegex, '$1');
113 | isXcode = true;
114 | } else { // SPM
115 | buildDir = path.dirname(profDataDir);
116 | isXcode = false;
117 | }
118 | core.debug(`Checking contents of build dir ${buildDir} of prof data file ${profDataFile}`);
119 | for await (const entry of walk(buildDir, false)) {
120 | const typesRegex = /.*\.(app|framework|xctest)$/;
121 | if (!typesRegex.test(entry.path)) continue;
122 | entry.skipDescendants(); // Don't process any further files inside this container.
123 | if (isXcode && !/\/Build[^/]*\/Products\//.test(entry.path)) {
124 | core.info(`Skipping ${entry.path} because it is not in a Xcode build products directory...`);
125 | continue;
126 | }
127 | const type = entry.path.replace(typesRegex, '$1');
128 | core.debug(`Found match of type ${type}: ${entry.path}`);
129 | const proj = entry.path
130 | .replace(/.*\//, '')
131 | .replace(`.${type}`, '');
132 | core.debug(`Project name: ${proj}`);
133 | if (processedTargets.has(`${proj}.${type}`)) {
134 | core.info(`Skipping ${proj} with type ${type} because it has already been converted...`);
135 | continue;
136 | }
137 | if (targetNameFilter && !targetNameFilter.test(proj)) {
138 | core.info(`Skipping ${proj} due to target name filter...`);
139 | continue;
140 | }
141 |
142 | let dest: string;
143 | let cmd: string;
144 | let args: string[];
145 | if (process.platform === 'darwin') {
146 | dest = path.join(entry.path, proj);
147 | if (!await fileExists(dest)) {
148 | const macOSPath = path.join(entry.path, 'Contents', 'MacOS');
149 | dest = path.join(macOSPath, proj);
150 | if (!await fileExists(dest)) {
151 | // Try again with whitespaces removed.
152 | dest = path.join(macOSPath, proj.replace(' ', ''));
153 | }
154 | if (!await fileExists(dest)) {
155 | core.warning(`Couldn't find a suitable target file in ${entry.path}. Using the path itself...`);
156 | dest = entry.path;
157 | }
158 | }
159 | cmd = 'xcrun';
160 | args = ['llvm-cov'];
161 | } else {
162 | dest = entry.path;
163 | cmd = 'llvm-cov';
164 | args = [];
165 | }
166 | let fileEnding: string;
167 | switch (format) {
168 | case CovFormat.txt:
169 | args.push('show');
170 | fileEnding = 'txt';
171 | break;
172 | case CovFormat.lcov:
173 | args.push('export', '-format=lcov');
174 | fileEnding = 'lcov';
175 | break;
176 | }
177 | args.push('-instr-profile', profDataFile, dest);
178 | let converted: string;
179 | try {
180 | converted = await runCmd(cmd, ...args);
181 | } catch (error: any) {
182 | const msg = `Failed to convert ${dest}: ${error}`;
183 | if (error instanceof Error)
184 | conversionFailures.push(error);
185 | else
186 | conversionFailures.push(new Error(msg));
187 | if (ignoreConversionFailures) core.info(msg);
188 | else core.error(msg);
189 | continue;
190 | }
191 | const projFileName = proj.replace(/\s/g, '');
192 | const outFile = path.join(outputFolder, `${projFileName}.${type}.coverage.${fileEnding}`);
193 | core.debug(`Writing coverage report to ${outFile}`);
194 | await fs.writeFile(outFile, converted);
195 | outFiles.push(outFile);
196 | processedTargets.add(`${proj}.${type}`);
197 | }
198 | }
199 | if (conversionFailures.length > 0) {
200 | if (ignoreConversionFailures)
201 | core.info(`Failed to convert ${conversionFailures.length} file(s)...`);
202 | else
203 | throw new Error('Conversion failures:\n' + conversionFailures.map(e => e.toString()).join('\n'));
204 | }
205 | core.info(`Processed ${outFiles.length} file(s):\n${outFiles.join('\n')}`);
206 | return outFiles;
207 | });
208 | }
209 | core.setOutput('files', JSON.stringify(convertedFiles));
210 | if (convertedFiles.length <= 0 && failOnEmptyOutput)
211 | throw new Error('No coverage files found (or none succeeded to convert)!');
212 | }
213 |
214 | try {
215 | main().catch(error => core.setFailed(error.message));
216 | } catch (error: any) {
217 | core.setFailed(error.message);
218 | }
219 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node20/tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "lib",
5 | "rootDir": "src",
6 | },
7 | "include": ["src/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------