mirror of
https://github.com/Azure/setup-helm.git
synced 2025-07-16 10:50:38 +00:00
Compare commits
35 Commits
updating-r
...
v4.0.0
Author | SHA1 | Date | |
---|---|---|---|
29960d0f5f | |||
0788eb3317 | |||
208de6bd49 | |||
1f87a575d0 | |||
d336b89352 | |||
ac5ee1fca8 | |||
638a523e0c | |||
0a7ec47357 | |||
3419a8fa8f | |||
f77071b246 | |||
a4617735aa | |||
2dafda840c | |||
b70d33f56d | |||
3c00c0152f | |||
22d14750db | |||
a22741c887 | |||
f850d12cb3 | |||
17cd77473c | |||
484a64052d | |||
6e32762c2e | |||
17c21ab68c | |||
7f0153c54c | |||
a14110f6e6 | |||
a767c8d3a1 | |||
97c3a3f138 | |||
0a86c98d61 | |||
39f78708c2 | |||
fa870ea9a2 | |||
e00756a00e | |||
2998c83e16 | |||
5876560d6c | |||
7e6f48e5b4 | |||
da63a48ad7 | |||
cc2c85bd7e | |||
7e3c8fd604 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
|||||||
* @ds-ms
|
* @Azure/aks-atlanta
|
||||||
|
36
.github/ISSUE_TEMPLATE/bugReportForm.yml
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bugReportForm.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug report specifying all inputs you provided for the action, we will respond to this thread with any questions.
|
||||||
|
title: 'Bug: '
|
||||||
|
labels: ['bug', 'triage']
|
||||||
|
assignees: '@Azure/aks-atlanta'
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: What-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: Tell us what happened and how is it different from the expected?
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: Version
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
options:
|
||||||
|
- label: I am using the latest version
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: Runner
|
||||||
|
attributes:
|
||||||
|
label: Runner
|
||||||
|
description: What runner are you using?
|
||||||
|
placeholder: Mention the runner info (self-hosted, operating system)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: Logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant log output
|
||||||
|
description: Run in debug mode for the most verbose logs. Please feel free to attach a screenshot of the logs
|
||||||
|
validations:
|
||||||
|
required: true
|
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: GitHub Action "setup-helm" Support
|
||||||
|
url: https://github.com/Azure/setup-helm
|
||||||
|
security: https://github.com/Azure/setup-helm/blob/main/SECURITY.md
|
||||||
|
about: Please ask and answer questions here.
|
13
.github/ISSUE_TEMPLATE/featureRequestForm.yml
vendored
Normal file
13
.github/ISSUE_TEMPLATE/featureRequestForm.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: File a Feature Request form, we will respond to this thread with any questions.
|
||||||
|
title: 'Feature Request: '
|
||||||
|
labels: ['Feature']
|
||||||
|
assignees: '@Azure/aks-atlanta'
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: Feature_request
|
||||||
|
attributes:
|
||||||
|
label: Feature request
|
||||||
|
description: Provide example functionality and links to relevant docs
|
||||||
|
validations:
|
||||||
|
required: true
|
@ -4,7 +4,4 @@ about: Create a report to help us improve
|
|||||||
title: ''
|
title: ''
|
||||||
labels: need-to-triage
|
labels: need-to-triage
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
33
.github/workflows/TriggerIntegrationTests.sh
vendored
33
.github/workflows/TriggerIntegrationTests.sh
vendored
@ -1,33 +0,0 @@
|
|||||||
token=$1
|
|
||||||
commit=$2
|
|
||||||
repository=$3
|
|
||||||
prNumber=$4
|
|
||||||
frombranch=$5
|
|
||||||
tobranch=$6
|
|
||||||
patUser=$7
|
|
||||||
|
|
||||||
getPayLoad() {
|
|
||||||
cat <<EOF
|
|
||||||
{
|
|
||||||
"event_type": "SetupHelmActionPR",
|
|
||||||
"client_payload":
|
|
||||||
{
|
|
||||||
"action": "SetupHelm",
|
|
||||||
"commit": "$commit",
|
|
||||||
"repository": "$repository",
|
|
||||||
"prNumber": "$prNumber",
|
|
||||||
"tobranch": "$tobranch",
|
|
||||||
"frombranch": "$frombranch"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
response=$(curl -u $patUser:$token -X POST https://api.github.com/repos/Azure/azure-actions-integration-tests/dispatches --data "$(getPayLoad)")
|
|
||||||
|
|
||||||
if [ "$response" == "" ]; then
|
|
||||||
echo "Integration tests triggered successfully"
|
|
||||||
else
|
|
||||||
echo "Triggering integration tests failed with: '$response'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
57
.github/workflows/defaultLabels.yml
vendored
57
.github/workflows/defaultLabels.yml
vendored
@ -1,36 +1,35 @@
|
|||||||
name: setting-default-labels
|
name: setting-default-labels
|
||||||
|
|
||||||
# Controls when the action will run.
|
# Controls when the action will run.
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0/3 * * *"
|
- cron: '0 0/3 * * *'
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# The type of runner that the job will run on
|
# The type of runner that the job will run on
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
- uses: actions/stale@v3
|
name: Setting issue as idle
|
||||||
name: Setting issue as idle
|
with:
|
||||||
with:
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
|
||||||
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
|
stale-issue-label: 'idle'
|
||||||
stale-issue-label: 'idle'
|
days-before-stale: 14
|
||||||
days-before-stale: 14
|
days-before-close: -1
|
||||||
days-before-close: -1
|
operations-per-run: 100
|
||||||
operations-per-run: 100
|
exempt-issue-labels: 'backlog'
|
||||||
exempt-issue-labels: 'backlog'
|
|
||||||
|
- uses: actions/stale@v9
|
||||||
- uses: actions/stale@v3
|
name: Setting PR as idle
|
||||||
name: Setting PR as idle
|
with:
|
||||||
with:
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
|
||||||
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
|
stale-pr-label: 'idle'
|
||||||
stale-pr-label: 'idle'
|
days-before-stale: 14
|
||||||
days-before-stale: 14
|
days-before-close: -1
|
||||||
days-before-close: -1
|
operations-per-run: 100
|
||||||
operations-per-run: 100
|
|
||||||
|
98
.github/workflows/integration-tests.yml
vendored
98
.github/workflows/integration-tests.yml
vendored
@ -1,19 +1,87 @@
|
|||||||
name: "Trigger Integration tests"
|
name: 'Trigger Integration tests'
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
- 'releases/*'
|
- 'releases/*'
|
||||||
jobs:
|
jobs:
|
||||||
trigger-integration-tests:
|
trigger-integration-tests:
|
||||||
name: Trigger Integration tests
|
name: Trigger Integration tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
HELM_3_8_0: 'v3.8.0'
|
||||||
|
HELM_3_7_2: 'v3.7.2'
|
||||||
|
HELM_NO_V: '3.5.0'
|
||||||
|
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
- name: npm install and build
|
||||||
path: IntegrationTests
|
id: action-npm-build
|
||||||
|
run: |
|
||||||
- name: Trigger Test run
|
echo $PR_BASE_REF
|
||||||
run: |
|
if [[ $PR_BASE_REF != releases/* ]]; then
|
||||||
bash ./IntegrationTests/.github/workflows/TriggerIntegrationTests.sh ${{ secrets.L2_REPO_TOKEN }} ${{ github.event.pull_request.head.sha }} ${{ github.repository }} ${{ github.event.pull_request.number }} ${{ github.event.pull_request.head.ref }} ${{ github.event.pull_request.base.ref }} ${{ secrets.L2_REPO_USER }}
|
npm install
|
||||||
|
npm run build
|
||||||
|
fi
|
||||||
|
- name: Setup helm
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
version: ${{ env.HELM_3_8_0 }}
|
||||||
|
- name: Validate helm 3.8.0
|
||||||
|
run: |
|
||||||
|
if [[ $(helm version) != *$HELM_3_8_0* ]]; then
|
||||||
|
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.8.0"
|
||||||
|
echo "HELM VERSION OUTPUT: $(helm version)"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "HELM VERSION $HELM_3_8_0 INSTALLED SUCCESSFULLY"
|
||||||
|
fi
|
||||||
|
- name: Setup helm 3.7.2
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
version: ${{ env.HELM_3_7_2 }}
|
||||||
|
- name: Validate 3.7.2
|
||||||
|
run: |
|
||||||
|
if [[ $(helm version) != *$HELM_3_7_2* ]]; then
|
||||||
|
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.7.2"
|
||||||
|
echo "HELM VERSION OUTPUT: $(helm version)"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "HELM VERSION $HELM_3_7_2 INSTALLED SUCCESSFULLY"
|
||||||
|
fi
|
||||||
|
- name: Setup helm 3.5.0 with no v in version
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
version: ${{ env.HELM_NO_V }}
|
||||||
|
- name: Validate 3.5.0 without v in version
|
||||||
|
run: |
|
||||||
|
if [[ $(helm version) != *$HELM_NO_V* ]]; then
|
||||||
|
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.5.0"
|
||||||
|
echo "HELM VERSION OUTPUT: $(helm version)"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "HELM VERSION $HELM_3_5_0 INSTALLED SUCCESSFULLY"
|
||||||
|
fi
|
||||||
|
- name: Setup helm latest version
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Validate latest
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
HELM_LATEST=$(gh release list \
|
||||||
|
--repo helm/helm \
|
||||||
|
--exclude-drafts \
|
||||||
|
--exclude-pre-releases \
|
||||||
|
--limit 1 | awk '{print $4}')
|
||||||
|
|
||||||
|
if [[ $(helm version) != *$HELM_LATEST* ]]; then
|
||||||
|
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN $HELM_LATEST"
|
||||||
|
echo "HELM VERSION OUTPUT: $(helm version)"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "HELM VERSION $HELM_LATEST INSTALLED SUCCESSFULLY"
|
||||||
|
fi
|
||||||
|
18
.github/workflows/prettify-code.yml
vendored
Normal file
18
.github/workflows/prettify-code.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: 'Run prettify'
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prettier:
|
||||||
|
name: Prettier Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Enforce Prettier
|
||||||
|
uses: actionsx/prettier@v3
|
||||||
|
with:
|
||||||
|
args: --check .
|
18
.github/workflows/release-pr.yml
vendored
Normal file
18
.github/workflows/release-pr.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: Release Project
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- CHANGELOG.md
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: write
|
||||||
|
uses: Azure/action-release-workflows/.github/workflows/release_js_project.yaml@a705b2ab6a3ee889f2b0d925ad0bd2f9eb733ce6
|
||||||
|
with:
|
||||||
|
changelogPath: ./CHANGELOG.md
|
10
.github/workflows/tag-and-draft.yml
vendored
Normal file
10
.github/workflows/tag-and-draft.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
name: Tag and create release draft
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- releases/*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tag-and-release:
|
||||||
|
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main
|
36
.github/workflows/unit-tests.yml
vendored
36
.github/workflows/unit-tests.yml
vendored
@ -1,21 +1,21 @@
|
|||||||
name: "Run unit tests."
|
name: 'Run unit tests.'
|
||||||
on: # rebuild any PRs and main branch changes
|
on: # rebuild any PRs and main branch changes
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
- 'releases/*'
|
- 'releases/*'
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
- 'releases/*'
|
- 'releases/*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build: # make sure build/ci works properly
|
build: # make sure build/ci works properly
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Run L0 tests.
|
- name: Run L0 tests.
|
||||||
run: |
|
run: |
|
||||||
npm install
|
npm install
|
||||||
npm test
|
npm test
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,8 +11,6 @@ pids
|
|||||||
*.seed
|
*.seed
|
||||||
*.pid.lock
|
*.pid.lock
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
# Coverage directory used by tools like istanbul
|
||||||
coverage
|
coverage
|
||||||
@ -62,3 +60,5 @@ typings/
|
|||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
coverage
|
coverage
|
||||||
|
|
||||||
|
# Transpiled JS
|
||||||
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
coverage
|
||||||
|
/lib
|
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"semi": false,
|
||||||
|
"tabWidth": 3,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 80
|
||||||
|
}
|
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
## [4.0.0] - 2024-02-12
|
||||||
|
|
||||||
|
- #121 update to node20 as node16 is deprecated
|
@ -1,9 +1,9 @@
|
|||||||
# Microsoft Open Source Code of Conduct
|
# Microsoft Open Source Code of Conduct
|
||||||
|
|
||||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||||
|
|
||||||
Resources:
|
Resources:
|
||||||
|
|
||||||
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
||||||
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||||
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
|
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||||
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||||
|
|
||||||
|
67
README.md
67
README.md
@ -1,28 +1,39 @@
|
|||||||
# Setup Helm
|
# Setup Helm
|
||||||
#### Install a specific version of helm binary on the runner.
|
|
||||||
|
Install a specific version of helm binary on the runner.
|
||||||
Acceptable values are latest or any semantic version string like v2.16.7 Use this action in workflow to define which version of helm will be used.
|
|
||||||
|
## Example
|
||||||
```yaml
|
|
||||||
- uses: azure/setup-helm@v1
|
Acceptable values are latest or any semantic version string like v3.5.0 Use this action in workflow to define which version of helm will be used. v2 and v3 of this action only support Helm3.
|
||||||
with:
|
|
||||||
version: '<version>' # default is latest stable
|
```yaml
|
||||||
id: install
|
- uses: azure/setup-helm@v3
|
||||||
```
|
with:
|
||||||
|
version: '<version>' # default is latest (stable)
|
||||||
The cached helm binary path is prepended to the PATH environment variable as well as stored in the helm-path output variable.
|
token: ${{ secrets.GITHUB_TOKEN }} # only needed if version is 'latest'
|
||||||
Refer to the action metadata file for details about all the inputs https://github.com/Azure/setup-helm/blob/master/action.yml
|
id: install
|
||||||
|
```
|
||||||
# Contributing
|
|
||||||
|
> [!NOTE]
|
||||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
> When using latest version you might hit the GitHub GraphQL API hourly rate limit of 5,000. The action will then return the hardcoded default stable version (currently v3.13.3). If you rely on a certain version higher than the default, you should use that version instead of latest.
|
||||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
|
||||||
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
The cached helm binary path is prepended to the PATH environment variable as well as stored in the helm-path output variable.
|
||||||
|
Refer to the action metadata file for details about all the inputs https://github.com/Azure/setup-helm/blob/master/action.yml
|
||||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
|
|
||||||
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
## Contributing
|
||||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
|
||||||
|
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
||||||
|
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
|
||||||
|
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
||||||
|
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||||
|
|
||||||
|
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||||
|
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||||
|
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
setup-helm is an open source project that is [**not** covered by the Microsoft Azure support policy](https://support.microsoft.com/en-us/help/2941892/support-for-linux-and-open-source-technology-in-azure). [Please search open issues here](https://github.com/Azure/setup-helm/issues), and if your issue isn't already represented please [open a new one](https://github.com/Azure/setup-helm/issues/new/choose). The project maintainers will respond to the best of their abilities.
|
||||||
|
82
SECURITY.md
82
SECURITY.md
@ -1,41 +1,41 @@
|
|||||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.2 BLOCK -->
|
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.2 BLOCK -->
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/).
|
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/).
|
||||||
|
|
||||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
|
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)>) of a security vulnerability, please report it to us as described below.
|
||||||
|
|
||||||
## Reporting Security Issues
|
## Reporting Security Issues
|
||||||
|
|
||||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
||||||
|
|
||||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
||||||
|
|
||||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||||
|
|
||||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||||
|
|
||||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||||
* Full paths of source file(s) related to the manifestation of the issue
|
- Full paths of source file(s) related to the manifestation of the issue
|
||||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
- The location of the affected source code (tag/branch/commit or direct URL)
|
||||||
* Any special configuration required to reproduce the issue
|
- Any special configuration required to reproduce the issue
|
||||||
* Step-by-step instructions to reproduce the issue
|
- Step-by-step instructions to reproduce the issue
|
||||||
* Proof-of-concept or exploit code (if possible)
|
- Proof-of-concept or exploit code (if possible)
|
||||||
* Impact of the issue, including how an attacker might exploit the issue
|
- Impact of the issue, including how an attacker might exploit the issue
|
||||||
|
|
||||||
This information will help us triage your report more quickly.
|
This information will help us triage your report more quickly.
|
||||||
|
|
||||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
|
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
|
||||||
|
|
||||||
## Preferred Languages
|
## Preferred Languages
|
||||||
|
|
||||||
We prefer all communications to be in English.
|
We prefer all communications to be in English.
|
||||||
|
|
||||||
## Policy
|
## Policy
|
||||||
|
|
||||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
||||||
|
|
||||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||||
|
@ -1,195 +0,0 @@
|
|||||||
import * as run from '../src/run'
|
|
||||||
import * as os from 'os';
|
|
||||||
import * as toolCache from '@actions/tool-cache';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as core from '@actions/core';
|
|
||||||
|
|
||||||
describe('run.ts', () => {
|
|
||||||
test('getExecutableExtension() - return .exe when os is Windows', () => {
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
|
|
||||||
expect(run.getExecutableExtension()).toBe('.exe');
|
|
||||||
expect(os.type).toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getExecutableExtension() - return empty string for non-windows OS', () => {
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
|
||||||
|
|
||||||
expect(run.getExecutableExtension()).toBe('');
|
|
||||||
expect(os.type).toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getHelmDownloadURL() - return the URL to download helm for Linux', () => {
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
|
||||||
const kubectlLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip'
|
|
||||||
|
|
||||||
expect(run.getHelmDownloadURL('v3.2.1')).toBe(kubectlLinuxUrl);
|
|
||||||
expect(os.type).toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => {
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
|
||||||
const kubectlDarwinUrl = 'https://get.helm.sh/helm-v3.2.1-darwin-amd64.zip'
|
|
||||||
|
|
||||||
expect(run.getHelmDownloadURL('v3.2.1')).toBe(kubectlDarwinUrl);
|
|
||||||
expect(os.type).toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
|
|
||||||
const kubectlWindowsUrl = 'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
|
|
||||||
expect(run.getHelmDownloadURL('v3.2.1')).toBe(kubectlWindowsUrl);
|
|
||||||
expect(os.type).toBeCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getStableHelmVersion() - download stable version file, read version and return it', async () => {
|
|
||||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
|
||||||
const response = JSON.stringify(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
'tag_name': 'v4.0.0'
|
|
||||||
}, {
|
|
||||||
'tag_name': 'v3.0.0'
|
|
||||||
}, {
|
|
||||||
'tag_name': 'v2.0.0'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
);
|
|
||||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
|
||||||
|
|
||||||
expect(await run.getStableHelmVersion()).toBe('v4.0.0');
|
|
||||||
expect(toolCache.downloadTool).toBeCalled();
|
|
||||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('getStableHelmVersion() - return default version if error occurs while getting latest version', async () => {
|
|
||||||
jest.spyOn(toolCache, 'downloadTool').mockRejectedValue('Unable to download');
|
|
||||||
jest.spyOn(core, 'warning').mockImplementation();
|
|
||||||
|
|
||||||
expect(await run.getStableHelmVersion()).toBe('v3.2.1');
|
|
||||||
expect(toolCache.downloadTool).toBeCalled();
|
|
||||||
expect(core.warning).toBeCalledWith("Cannot get the latest Helm info from https://api.github.com/repos/helm/helm/releases. Error Unable to download. Using default Helm version v3.2.1.");
|
|
||||||
});
|
|
||||||
|
|
||||||
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
|
||||||
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
|
|
||||||
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
|
|
||||||
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
|
|
||||||
});
|
|
||||||
jest.spyOn(core, 'debug').mockImplementation();
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
|
||||||
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
|
|
||||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(run.walkSync('mainFolder', null, 'file21')).toEqual([path.join('mainFolder', 'folder2', 'file21')]);
|
|
||||||
expect(fs.readdirSync).toBeCalledTimes(3);
|
|
||||||
expect(fs.statSync).toBeCalledTimes(8);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
|
||||||
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
|
|
||||||
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
|
|
||||||
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
|
|
||||||
});
|
|
||||||
jest.spyOn(core, 'debug').mockImplementation();
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
|
||||||
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
|
|
||||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([]);
|
|
||||||
expect(fs.readdirSync).toBeCalledTimes(3);
|
|
||||||
expect(fs.statSync).toBeCalledTimes(8);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('findHelm() - change access permissions and find the helm in given directory', () => {
|
|
||||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
|
||||||
if (file == 'mainFolder') return ['helm.exe' as unknown as fs.Dirent];
|
|
||||||
});
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
|
||||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
|
||||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
|
||||||
});
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
|
|
||||||
expect(run.findHelm('mainFolder')).toBe(path.join('mainFolder', 'helm.exe'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('findHelm() - throw error if executable not found', () => {
|
|
||||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
|
||||||
if (file == 'mainFolder') return [];
|
|
||||||
});
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => { return { isDirectory: () => true } as fs.Stats});
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
expect(() => run.findHelm('mainFolder')).toThrow('Helm executable not found in path mainFolder');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('downloadHelm() - download helm and return path to it', async () => {
|
|
||||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
|
||||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
|
||||||
const response = JSON.stringify([{'tag_name': 'v4.0.0'}]);
|
|
||||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
|
||||||
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
|
|
||||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
|
||||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
|
||||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(await run.downloadHelm(null)).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
|
||||||
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0');
|
|
||||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v4.0.0-windows-amd64.zip');
|
|
||||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
|
|
||||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
|
|
||||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('downloadHelm() - throw error if unable to download', async () => {
|
|
||||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
|
||||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download'});
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
|
|
||||||
await expect(run.downloadHelm('v3.2.1')).rejects.toThrow('Failed to download Helm from location https://get.helm.sh/helm-v3.2.1-windows-amd64.zip');
|
|
||||||
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1');
|
|
||||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v3.2.1-windows-amd64.zip');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('downloadHelm() - return path to helm tool with same version from toolCache', async () => {
|
|
||||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
|
|
||||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
|
||||||
|
|
||||||
expect(await run.downloadHelm('v3.2.1')).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
|
||||||
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1');
|
|
||||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('downloadHelm() - throw error is helm is not found in path', async () => {
|
|
||||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
|
||||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
|
||||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
|
||||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
|
||||||
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
|
|
||||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
|
|
||||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => []);
|
|
||||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
|
||||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
|
||||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
|
||||||
});
|
|
||||||
|
|
||||||
await expect(run.downloadHelm('v3.2.1')).rejects.toThrow('Helm executable not found in path pathToCachedDir');
|
|
||||||
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1');
|
|
||||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v3.2.1-windows-amd64.zip');
|
|
||||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
|
|
||||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
|
|
||||||
});
|
|
||||||
});
|
|
30
action.yml
30
action.yml
@ -1,19 +1,23 @@
|
|||||||
name: 'Helm tool installer'
|
name: 'Helm tool installer'
|
||||||
description: 'Install a specific version of helm binary. Acceptable values are latest or any semantic version string like 1.15.0'
|
description: 'Install a specific version of helm binary. Acceptable values are latest or any semantic version string like 1.15.0'
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: 'Version of helm'
|
description: 'Version of helm'
|
||||||
required: true
|
required: true
|
||||||
default: 'latest'
|
default: 'latest'
|
||||||
token:
|
token:
|
||||||
description: 'Github token'
|
description: GitHub token. Required only if 'version' == 'latest'
|
||||||
default: ${{ github.token }}
|
required: false
|
||||||
required: true
|
default: '${{ github.token }}'
|
||||||
|
downloadBaseURL:
|
||||||
|
description: 'Set the download base URL'
|
||||||
|
required: false
|
||||||
|
default: 'https://get.helm.sh'
|
||||||
outputs:
|
outputs:
|
||||||
helm-path:
|
helm-path:
|
||||||
description: 'Path to the cached helm binary'
|
description: 'Path to the cached helm binary'
|
||||||
branding:
|
branding:
|
||||||
color: 'blue'
|
color: 'blue'
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node20'
|
||||||
main: 'lib/run.js'
|
main: 'lib/index.js'
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
clearMocks: true,
|
clearMocks: true,
|
||||||
moduleFileExtensions: ['js', 'ts'],
|
moduleFileExtensions: ['js', 'ts'],
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
testMatch: ['**/*.test.ts'],
|
testMatch: ['**/*.test.ts'],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.ts$': 'ts-jest'
|
'^.+\\.ts$': 'ts-jest'
|
||||||
},
|
},
|
||||||
verbose: true,
|
verbose: true,
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
"global": {
|
global: {
|
||||||
"branches": 0,
|
branches: 0,
|
||||||
"functions": 14,
|
functions: 14,
|
||||||
"lines": 27,
|
lines: 27,
|
||||||
"statements": 27
|
statements: 27
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
58492
lib/index.js
Normal file
58492
lib/index.js
Normal file
File diff suppressed because one or more lines are too long
222
lib/run.js
222
lib/run.js
@ -1,222 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
// Copyright (c) Microsoft Corporation.
|
|
||||||
// Copyright (c) Microsoft Corporation.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.getStableHelmVersion = void 0;
|
|
||||||
const os = __importStar(require("os"));
|
|
||||||
const path = __importStar(require("path"));
|
|
||||||
const util = __importStar(require("util"));
|
|
||||||
const fs = __importStar(require("fs"));
|
|
||||||
const semver = __importStar(require("semver"));
|
|
||||||
const toolCache = __importStar(require("@actions/tool-cache"));
|
|
||||||
const core = __importStar(require("@actions/core"));
|
|
||||||
const graphql_1 = require("@octokit/graphql");
|
|
||||||
const helmToolName = 'helm';
|
|
||||||
const stableHelmVersion = 'v3.2.1';
|
|
||||||
const stableHelm3Version = 'v3.5.3';
|
|
||||||
const stableHelm2Version = 'v2.17.0';
|
|
||||||
const LATEST_HELM2_VERSION = '2.*';
|
|
||||||
const LATEST_HELM3_VERSION = '3.*';
|
|
||||||
const helmAllReleasesUrl = 'https://api.github.com/repos/helm/helm/releases';
|
|
||||||
function getExecutableExtension() {
|
|
||||||
if (os.type().match(/^Win/)) {
|
|
||||||
return '.exe';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
function getHelmDownloadURL(version) {
|
|
||||||
switch (os.type()) {
|
|
||||||
case 'Linux':
|
|
||||||
return util.format('https://get.helm.sh/helm-%s-linux-amd64.zip', version);
|
|
||||||
case 'Darwin':
|
|
||||||
return util.format('https://get.helm.sh/helm-%s-darwin-amd64.zip', version);
|
|
||||||
case 'Windows_NT':
|
|
||||||
default:
|
|
||||||
return util.format('https://get.helm.sh/helm-%s-windows-amd64.zip', version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getStableHelmVersion() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
|
||||||
const downloadPath = yield toolCache.downloadTool(helmAllReleasesUrl);
|
|
||||||
const responseArray = JSON.parse(fs.readFileSync(downloadPath, 'utf8').toString().trim());
|
|
||||||
let latestHelmVersion = semver.clean(stableHelmVersion);
|
|
||||||
responseArray.forEach(response => {
|
|
||||||
if (response && response.tag_name) {
|
|
||||||
let currentHelmVerison = semver.clean(response.tag_name.toString());
|
|
||||||
if (currentHelmVerison) {
|
|
||||||
if (currentHelmVerison.toString().indexOf('rc') == -1 && semver.gt(currentHelmVerison, latestHelmVersion)) {
|
|
||||||
//If current helm version is not a pre release and is greater than latest helm version
|
|
||||||
latestHelmVersion = currentHelmVerison;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
latestHelmVersion = "v" + latestHelmVersion;
|
|
||||||
return latestHelmVersion;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
core.warning(util.format("Cannot get the latest Helm info from %s. Error %s. Using default Helm version %s.", helmAllReleasesUrl, error, stableHelmVersion));
|
|
||||||
}
|
|
||||||
return stableHelmVersion;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
exports.getStableHelmVersion = getStableHelmVersion;
|
|
||||||
var walkSync = function (dir, filelist, fileToFind) {
|
|
||||||
var files = fs.readdirSync(dir);
|
|
||||||
filelist = filelist || [];
|
|
||||||
files.forEach(function (file) {
|
|
||||||
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
|
||||||
filelist = walkSync(path.join(dir, file), filelist, fileToFind);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
core.debug(file);
|
|
||||||
if (file == fileToFind) {
|
|
||||||
filelist.push(path.join(dir, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return filelist;
|
|
||||||
};
|
|
||||||
function downloadHelm(version) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
if (!version) {
|
|
||||||
version = yield getLatestHelmVersionFor("v3");
|
|
||||||
}
|
|
||||||
let cachedToolpath = toolCache.find(helmToolName, version);
|
|
||||||
if (!cachedToolpath) {
|
|
||||||
let helmDownloadPath;
|
|
||||||
try {
|
|
||||||
helmDownloadPath = yield toolCache.downloadTool(getHelmDownloadURL(version));
|
|
||||||
}
|
|
||||||
catch (exception) {
|
|
||||||
throw new Error(util.format("Failed to download Helm from location ", getHelmDownloadURL(version)));
|
|
||||||
}
|
|
||||||
fs.chmodSync(helmDownloadPath, '777');
|
|
||||||
const unzipedHelmPath = yield toolCache.extractZip(helmDownloadPath);
|
|
||||||
cachedToolpath = yield toolCache.cacheDir(unzipedHelmPath, helmToolName, version);
|
|
||||||
}
|
|
||||||
const helmpath = findHelm(cachedToolpath);
|
|
||||||
if (!helmpath) {
|
|
||||||
throw new Error(util.format("Helm executable not found in path ", cachedToolpath));
|
|
||||||
}
|
|
||||||
fs.chmodSync(helmpath, '777');
|
|
||||||
return helmpath;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function getLatestHelmVersionFor(type) {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
const token = core.getInput('token', { 'required': true });
|
|
||||||
try {
|
|
||||||
const { repository } = yield graphql_1.graphql(`{
|
|
||||||
repository(name: "helm", owner: "helm") {
|
|
||||||
releases(last: 100) {
|
|
||||||
nodes {
|
|
||||||
tagName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`, {
|
|
||||||
headers: {
|
|
||||||
authorization: `token ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const releases = repository.releases.nodes.reverse();
|
|
||||||
let latestValidRelease = releases.find(release => isValidVersion(release.tagName, type));
|
|
||||||
if (latestValidRelease)
|
|
||||||
return latestValidRelease.tagName;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
core.warning(util.format("Error while fetching the latest Helm %s release. Error: %s. Using default Helm version %s.", type, err.toString(), getStableHelmVersionFor(type)));
|
|
||||||
return getStableHelmVersionFor(type);
|
|
||||||
}
|
|
||||||
core.warning(util.format("Could not find stable release for Helm %s. Using default Helm version %s.", type, getStableHelmVersionFor(type)));
|
|
||||||
return getStableHelmVersionFor(type);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function getStableHelmVersionFor(type) {
|
|
||||||
return type === "v2" ? stableHelm2Version : stableHelm3Version;
|
|
||||||
}
|
|
||||||
// isValidVersion checks if verison matches the specified type and is a stable release
|
|
||||||
function isValidVersion(version, type) {
|
|
||||||
if (!version.toLocaleLowerCase().startsWith(type))
|
|
||||||
return false;
|
|
||||||
return version.indexOf('rc') == -1;
|
|
||||||
}
|
|
||||||
function findHelm(rootFolder) {
|
|
||||||
fs.chmodSync(rootFolder, '777');
|
|
||||||
var filelist = [];
|
|
||||||
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension());
|
|
||||||
if (!filelist) {
|
|
||||||
throw new Error(util.format("Helm executable not found in path ", rootFolder));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return filelist[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function run() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
let version = core.getInput('version', { 'required': true });
|
|
||||||
if (process.env['HELM_INSTALLER_LEGACY_VERSIONING'] == 'true') {
|
|
||||||
if (version.toLocaleLowerCase() === 'latest') {
|
|
||||||
version = yield getStableHelmVersion();
|
|
||||||
}
|
|
||||||
else if (!version.toLocaleLowerCase().startsWith('v')) {
|
|
||||||
version = 'v' + version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (version.toLocaleLowerCase() === 'latest' || version === LATEST_HELM3_VERSION) {
|
|
||||||
version = yield getLatestHelmVersionFor("v3");
|
|
||||||
}
|
|
||||||
else if (version === LATEST_HELM2_VERSION) {
|
|
||||||
version = yield getLatestHelmVersionFor("v2");
|
|
||||||
}
|
|
||||||
else if (!version.toLocaleLowerCase().startsWith('v')) {
|
|
||||||
version = 'v' + version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
core.debug(util.format("Downloading %s", version));
|
|
||||||
let cachedPath = yield downloadHelm(version);
|
|
||||||
try {
|
|
||||||
if (!process.env['PATH'].startsWith(path.dirname(cachedPath))) {
|
|
||||||
core.addPath(path.dirname(cachedPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (_a) {
|
|
||||||
//do nothing, set as output variable
|
|
||||||
}
|
|
||||||
console.log(`Helm tool version: '${version}' has been cached at ${cachedPath}`);
|
|
||||||
core.setOutput('helm-path', cachedPath);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
run().catch(core.setFailed);
|
|
4213
package-lock.json
generated
4213
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
60
package.json
60
package.json
@ -1,29 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "setuphelm",
|
"name": "setuphelm",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Setup helm",
|
"description": "Setup helm",
|
||||||
"author": "Anumita Shenoy",
|
"author": "Anumita Shenoy",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.0.0",
|
"@actions/exec": "^1.1.1",
|
||||||
"@actions/io": "^1.0.0",
|
"@actions/io": "^1.1.2",
|
||||||
"@actions/tool-cache": "1.1.2",
|
"@actions/tool-cache": "2.0.1",
|
||||||
"@octokit/graphql": "^4.6.1",
|
"@octokit/action": "^6.0.7",
|
||||||
"semver": "^6.1.0"
|
"ncc": "^0.3.6",
|
||||||
},
|
"semver": "^7.5.4"
|
||||||
"main": "lib/run.js",
|
},
|
||||||
"scripts": {
|
"main": "lib/index.js",
|
||||||
"build": "tsc --outDir ./lib --rootDir ./src",
|
"scripts": {
|
||||||
"test": "jest",
|
"prebuild": "npm i ncc",
|
||||||
"test-coverage": "jest --coverage"
|
"build": "ncc build src/run.ts -o lib",
|
||||||
},
|
"test": "jest",
|
||||||
"devDependencies": {
|
"test-coverage": "jest --coverage",
|
||||||
"@types/node": "^12.0.10",
|
"format": "prettier --write .",
|
||||||
"typescript": "^3.5.2",
|
"format-check": "prettier --check ."
|
||||||
"jest": "^26.0.1",
|
},
|
||||||
"@types/jest": "^25.2.2",
|
"devDependencies": {
|
||||||
"ts-jest": "^25.5.1"
|
"@types/jest": "^29.5.11",
|
||||||
}
|
"@types/node": "^20.11.8",
|
||||||
|
"@vercel/ncc": "^0.38.1",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"ts-jest": "^29.1.2",
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
289
src/run.test.ts
Normal file
289
src/run.test.ts
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
import * as run from './run'
|
||||||
|
import * as os from 'os'
|
||||||
|
import * as toolCache from '@actions/tool-cache'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as core from '@actions/core'
|
||||||
|
|
||||||
|
describe('run.ts', () => {
|
||||||
|
test('getExecutableExtension() - return .exe when os is Windows', () => {
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
|
||||||
|
expect(run.getExecutableExtension()).toBe('.exe')
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getExecutableExtension() - return empty string for non-windows OS', () => {
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||||
|
|
||||||
|
expect(run.getExecutableExtension()).toBe('')
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getHelmDownloadURL() - return the URL to download helm for Linux', () => {
|
||||||
|
const downloadBaseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
|
||||||
|
const helmLinuxUrl = 'https://test.tld/helm-v3.8.0-linux-amd64.zip'
|
||||||
|
|
||||||
|
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
|
||||||
|
helmLinuxUrl
|
||||||
|
)
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
expect(os.arch).toHaveBeenCalled()
|
||||||
|
|
||||||
|
// arm64
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
|
||||||
|
const helmLinuxArm64Url = 'https://test.tld/helm-v3.8.0-linux-arm64.zip'
|
||||||
|
|
||||||
|
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
|
||||||
|
helmLinuxArm64Url
|
||||||
|
)
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
expect(os.arch).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => {
|
||||||
|
const downloadBaseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
|
||||||
|
const helmDarwinUrl = 'https://test.tld/helm-v3.8.0-darwin-amd64.zip'
|
||||||
|
|
||||||
|
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
|
||||||
|
helmDarwinUrl
|
||||||
|
)
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
expect(os.arch).toHaveBeenCalled()
|
||||||
|
|
||||||
|
// arm64
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
|
||||||
|
const helmDarwinArm64Url = 'https://test.tld/helm-v3.8.0-darwin-arm64.zip'
|
||||||
|
|
||||||
|
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
|
||||||
|
helmDarwinArm64Url
|
||||||
|
)
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
expect(os.arch).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getValidVersion() - return version with v prepended', () => {
|
||||||
|
expect(run.getValidVersion('3.8.0')).toBe('v3.8.0')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
|
||||||
|
const downloadBaseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
|
||||||
|
const helmWindowsUrl = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
|
||||||
|
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
|
||||||
|
helmWindowsUrl
|
||||||
|
)
|
||||||
|
expect(os.type).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getLatestHelmVersion() - return the stable version of HELM since its not authenticated', async () => {
|
||||||
|
expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
|
||||||
|
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||||
|
if (file == 'mainFolder')
|
||||||
|
return [
|
||||||
|
'file1' as unknown as fs.Dirent,
|
||||||
|
'file2' as unknown as fs.Dirent,
|
||||||
|
'folder1' as unknown as fs.Dirent,
|
||||||
|
'folder2' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
if (file == path.join('mainFolder', 'folder1'))
|
||||||
|
return [
|
||||||
|
'file11' as unknown as fs.Dirent,
|
||||||
|
'file12' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
if (file == path.join('mainFolder', 'folder2'))
|
||||||
|
return [
|
||||||
|
'file21' as unknown as fs.Dirent,
|
||||||
|
'file22' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
jest.spyOn(core, 'debug').mockImplementation()
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
const isDirectory =
|
||||||
|
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
|
||||||
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(run.walkSync('mainFolder', null, 'file21')).toEqual([
|
||||||
|
path.join('mainFolder', 'folder2', 'file21')
|
||||||
|
])
|
||||||
|
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
|
||||||
|
expect(fs.statSync).toHaveBeenCalledTimes(8)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
|
||||||
|
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||||
|
if (file == 'mainFolder')
|
||||||
|
return [
|
||||||
|
'file1' as unknown as fs.Dirent,
|
||||||
|
'file2' as unknown as fs.Dirent,
|
||||||
|
'folder1' as unknown as fs.Dirent,
|
||||||
|
'folder2' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
if (file == path.join('mainFolder', 'folder1'))
|
||||||
|
return [
|
||||||
|
'file11' as unknown as fs.Dirent,
|
||||||
|
'file12' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
if (file == path.join('mainFolder', 'folder2'))
|
||||||
|
return [
|
||||||
|
'file21' as unknown as fs.Dirent,
|
||||||
|
'file22' as unknown as fs.Dirent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
jest.spyOn(core, 'debug').mockImplementation()
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
const isDirectory =
|
||||||
|
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
|
||||||
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([])
|
||||||
|
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
|
||||||
|
expect(fs.statSync).toHaveBeenCalledTimes(8)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('findHelm() - change access permissions and find the helm in given directory', () => {
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||||
|
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||||
|
if (file == 'mainFolder') return ['helm.exe' as unknown as fs.Dirent]
|
||||||
|
})
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
const isDirectory =
|
||||||
|
(file as string).indexOf('folder') == -1 ? false : true
|
||||||
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
|
})
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
|
||||||
|
expect(run.findHelm('mainFolder')).toBe(
|
||||||
|
path.join('mainFolder', 'helm.exe')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('findHelm() - throw error if executable not found', () => {
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||||
|
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||||
|
if (file == 'mainFolder') return []
|
||||||
|
})
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
return {isDirectory: () => true} as fs.Stats
|
||||||
|
})
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
expect(() => run.findHelm('mainFolder')).toThrow(
|
||||||
|
'Helm executable not found in path mainFolder'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - download helm and return path to it', async () => {
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||||
|
const response = JSON.stringify([{tag_name: 'v4.0.0'}])
|
||||||
|
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||||
|
jest
|
||||||
|
.spyOn(toolCache, 'extractZip')
|
||||||
|
.mockResolvedValue('pathToUnzippedHelm')
|
||||||
|
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readdirSync')
|
||||||
|
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
const isDirectory =
|
||||||
|
(file as string).indexOf('folder') == -1 ? false : true
|
||||||
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
|
})
|
||||||
|
|
||||||
|
const baseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
expect(await run.downloadHelm(baseURL, 'v4.0.0')).toBe(
|
||||||
|
path.join('pathToCachedDir', 'helm.exe')
|
||||||
|
)
|
||||||
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v4.0.0')
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledWith(
|
||||||
|
'https://test.tld/helm-v4.0.0-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
|
||||||
|
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
|
||||||
|
expect(fs.chmodSync).toHaveBeenCalledWith(
|
||||||
|
path.join('pathToCachedDir', 'helm.exe'),
|
||||||
|
'777'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - throw error if unable to download', async () => {
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||||
|
throw 'Unable to download'
|
||||||
|
})
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
|
||||||
|
const baseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
|
||||||
|
'Failed to download Helm from location https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledWith(
|
||||||
|
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - return path to helm tool with same version from toolCache', async () => {
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||||
|
|
||||||
|
const baseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
expect(await run.downloadHelm(baseURL, 'v3.2.1')).toBe(
|
||||||
|
path.join('pathToCachedDir', 'helm.exe')
|
||||||
|
)
|
||||||
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
|
expect(fs.chmodSync).toHaveBeenCalledWith(
|
||||||
|
path.join('pathToCachedDir', 'helm.exe'),
|
||||||
|
'777'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - throw error is helm is not found in path', async () => {
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||||
|
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||||
|
jest
|
||||||
|
.spyOn(toolCache, 'extractZip')
|
||||||
|
.mockResolvedValue('pathToUnzippedHelm')
|
||||||
|
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||||
|
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
|
||||||
|
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||||
|
const isDirectory =
|
||||||
|
(file as string).indexOf('folder') == -1 ? false : true
|
||||||
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
|
})
|
||||||
|
|
||||||
|
const baseURL = 'https://test.tld'
|
||||||
|
|
||||||
|
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
|
||||||
|
'Helm executable not found in path pathToCachedDir'
|
||||||
|
)
|
||||||
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledWith(
|
||||||
|
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
|
||||||
|
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
|
||||||
|
})
|
||||||
|
})
|
350
src/run.ts
350
src/run.ts
@ -2,201 +2,195 @@
|
|||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
import * as os from 'os';
|
import * as os from 'os'
|
||||||
import * as path from 'path';
|
import * as path from 'path'
|
||||||
import * as util from 'util';
|
import * as util from 'util'
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs'
|
||||||
import * as semver from 'semver';
|
|
||||||
|
|
||||||
import * as toolCache from '@actions/tool-cache';
|
import * as toolCache from '@actions/tool-cache'
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core'
|
||||||
import { graphql } from '@octokit/graphql';
|
import {Octokit} from '@octokit/action'
|
||||||
|
|
||||||
const helmToolName = 'helm';
|
const helmToolName = 'helm'
|
||||||
const stableHelmVersion = 'v3.2.1';
|
const stableHelmVersion = 'v3.13.3'
|
||||||
const stableHelm3Version = 'v3.5.3';
|
|
||||||
const stableHelm2Version = 'v2.17.0';
|
export async function run() {
|
||||||
const LATEST_HELM2_VERSION = '2.*';
|
let version = core.getInput('version', {required: true})
|
||||||
const LATEST_HELM3_VERSION = '3.*';
|
|
||||||
const helmAllReleasesUrl = 'https://api.github.com/repos/helm/helm/releases';
|
if (version !== 'latest' && version[0] !== 'v') {
|
||||||
|
core.info('Getting latest Helm version')
|
||||||
|
version = getValidVersion(version)
|
||||||
|
}
|
||||||
|
if (version.toLocaleLowerCase() === 'latest') {
|
||||||
|
version = await getLatestHelmVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadBaseURL = core.getInput('downloadBaseURL', {required: false})
|
||||||
|
|
||||||
|
core.startGroup(`Downloading ${version}`)
|
||||||
|
const cachedPath = await downloadHelm(downloadBaseURL, version)
|
||||||
|
core.endGroup()
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!process.env['PATH'].startsWith(path.dirname(cachedPath))) {
|
||||||
|
core.addPath(path.dirname(cachedPath))
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
//do nothing, set as output variable
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Helm tool version '${version}' has been cached at ${cachedPath}`)
|
||||||
|
core.setOutput('helm-path', cachedPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefixes version with v
|
||||||
|
export function getValidVersion(version: string): string {
|
||||||
|
return 'v' + version
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the latest helm version or returns a default stable if getting latest fails
|
||||||
|
export async function getLatestHelmVersion(): Promise<string> {
|
||||||
|
try {
|
||||||
|
const octokit = new Octokit()
|
||||||
|
const response = await octokit.rest.repos.listReleases({
|
||||||
|
owner: 'helm',
|
||||||
|
repo: 'helm',
|
||||||
|
per_page: 100,
|
||||||
|
order: 'desc',
|
||||||
|
sort: 'created'
|
||||||
|
})
|
||||||
|
|
||||||
|
const releases = response.data
|
||||||
|
const latestValidRelease: string = releases.find(
|
||||||
|
({tag_name, draft, prerelease}) =>
|
||||||
|
isValidVersion(tag_name) && !draft && !prerelease
|
||||||
|
)?.tag_name
|
||||||
|
|
||||||
|
if (latestValidRelease) return latestValidRelease
|
||||||
|
} catch (err) {
|
||||||
|
core.warning(
|
||||||
|
`Error while fetching latest Helm release: ${err.toString()}. Using default version ${stableHelmVersion}`
|
||||||
|
)
|
||||||
|
return stableHelmVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
core.warning(
|
||||||
|
`Could not find valid release. Using default version ${stableHelmVersion}`
|
||||||
|
)
|
||||||
|
return stableHelmVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValidVersion checks if verison is a stable release
|
||||||
|
function isValidVersion(version: string): boolean {
|
||||||
|
return version.indexOf('rc') == -1
|
||||||
|
}
|
||||||
|
|
||||||
export function getExecutableExtension(): string {
|
export function getExecutableExtension(): string {
|
||||||
if (os.type().match(/^Win/)) {
|
if (os.type().match(/^Win/)) {
|
||||||
return '.exe';
|
return '.exe'
|
||||||
}
|
}
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getHelmDownloadURL(version: string): string {
|
const LINUX = 'Linux'
|
||||||
switch (os.type()) {
|
const MAC_OS = 'Darwin'
|
||||||
case 'Linux':
|
const WINDOWS = 'Windows_NT'
|
||||||
return util.format('https://get.helm.sh/helm-%s-linux-amd64.zip', version);
|
const ARM64 = 'arm64'
|
||||||
|
export function getHelmDownloadURL(baseURL: string, version: string): string {
|
||||||
|
const arch = os.arch()
|
||||||
|
const operatingSystem = os.type()
|
||||||
|
|
||||||
case 'Darwin':
|
let urlPath = ''
|
||||||
return util.format('https://get.helm.sh/helm-%s-darwin-amd64.zip', version);
|
|
||||||
|
|
||||||
case 'Windows_NT':
|
switch (true) {
|
||||||
default:
|
case operatingSystem == LINUX && arch == ARM64:
|
||||||
return util.format('https://get.helm.sh/helm-%s-windows-amd64.zip', version);
|
urlPath = util.format(`/helm-%s-linux-arm64.zip`, version)
|
||||||
}
|
break
|
||||||
|
case operatingSystem == LINUX:
|
||||||
|
urlPath = util.format(`/helm-%s-linux-amd64.zip`, version)
|
||||||
|
break
|
||||||
|
case operatingSystem == MAC_OS && arch == ARM64:
|
||||||
|
urlPath = util.format(`/helm-%s-darwin-arm64.zip`, version)
|
||||||
|
break
|
||||||
|
case operatingSystem == MAC_OS:
|
||||||
|
urlPath = util.format(`/helm-%s-darwin-amd64.zip`, version)
|
||||||
|
break
|
||||||
|
case operatingSystem == WINDOWS:
|
||||||
|
default:
|
||||||
|
urlPath = util.format(`/helm-%s-windows-amd64.zip`, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(urlPath, baseURL)
|
||||||
|
return url.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStableHelmVersion(): Promise<string> {
|
export async function downloadHelm(
|
||||||
try {
|
baseURL: string,
|
||||||
const downloadPath = await toolCache.downloadTool(helmAllReleasesUrl);
|
version: string
|
||||||
const responseArray = JSON.parse(fs.readFileSync(downloadPath, 'utf8').toString().trim());
|
): Promise<string> {
|
||||||
let latestHelmVersion = semver.clean(stableHelmVersion);
|
let cachedToolpath = toolCache.find(helmToolName, version)
|
||||||
responseArray.forEach(response => {
|
if (!cachedToolpath) {
|
||||||
if (response && response.tag_name) {
|
let helmDownloadPath
|
||||||
let currentHelmVerison = semver.clean(response.tag_name.toString());
|
try {
|
||||||
if (currentHelmVerison) {
|
helmDownloadPath = await toolCache.downloadTool(
|
||||||
if (currentHelmVerison.toString().indexOf('rc') == -1 && semver.gt(currentHelmVerison, latestHelmVersion)) {
|
getHelmDownloadURL(baseURL, version)
|
||||||
//If current helm version is not a pre release and is greater than latest helm version
|
)
|
||||||
latestHelmVersion = currentHelmVerison;
|
} catch (exception) {
|
||||||
}
|
throw new Error(
|
||||||
}
|
`Failed to download Helm from location ${getHelmDownloadURL(
|
||||||
}
|
baseURL,
|
||||||
});
|
version
|
||||||
latestHelmVersion = "v" + latestHelmVersion;
|
)}`
|
||||||
return latestHelmVersion;
|
)
|
||||||
} catch (error) {
|
}
|
||||||
core.warning(util.format("Cannot get the latest Helm info from %s. Error %s. Using default Helm version %s.", helmAllReleasesUrl, error, stableHelmVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
return stableHelmVersion;
|
fs.chmodSync(helmDownloadPath, '777')
|
||||||
}
|
const unzipedHelmPath = await toolCache.extractZip(helmDownloadPath)
|
||||||
|
cachedToolpath = await toolCache.cacheDir(
|
||||||
|
unzipedHelmPath,
|
||||||
|
helmToolName,
|
||||||
|
version
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export var walkSync = function (dir, filelist, fileToFind) {
|
const helmpath = findHelm(cachedToolpath)
|
||||||
var files = fs.readdirSync(dir);
|
if (!helmpath) {
|
||||||
filelist = filelist || [];
|
throw new Error(
|
||||||
files.forEach(function (file) {
|
util.format('Helm executable not found in path', cachedToolpath)
|
||||||
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
)
|
||||||
filelist = walkSync(path.join(dir, file), filelist, fileToFind);
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
core.debug(file);
|
|
||||||
if (file == fileToFind) {
|
|
||||||
filelist.push(path.join(dir, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return filelist;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function downloadHelm(version: string): Promise<string> {
|
fs.chmodSync(helmpath, '777')
|
||||||
if (!version) { version = await getStableHelmVersion(); }
|
return helmpath
|
||||||
let cachedToolpath = toolCache.find(helmToolName, version);
|
|
||||||
if (!cachedToolpath) {
|
|
||||||
let helmDownloadPath;
|
|
||||||
try {
|
|
||||||
helmDownloadPath = await toolCache.downloadTool(getHelmDownloadURL(version));
|
|
||||||
} catch (exception) {
|
|
||||||
throw new Error(util.format("Failed to download Helm from location", getHelmDownloadURL(version)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.chmodSync(helmDownloadPath, '777');
|
|
||||||
const unzipedHelmPath = await toolCache.extractZip(helmDownloadPath);
|
|
||||||
cachedToolpath = await toolCache.cacheDir(unzipedHelmPath, helmToolName, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
const helmpath = findHelm(cachedToolpath);
|
|
||||||
if (!helmpath) {
|
|
||||||
throw new Error(util.format("Helm executable not found in path", cachedToolpath));
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.chmodSync(helmpath, '777');
|
|
||||||
return helmpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getLatestHelmVersionFor(type: string): Promise<string> {
|
|
||||||
const token = core.getInput('token', { 'required': true });
|
|
||||||
try {
|
|
||||||
const { repository } = await graphql(
|
|
||||||
`{
|
|
||||||
repository(name: "helm", owner: "helm") {
|
|
||||||
releases(last: 100) {
|
|
||||||
nodes {
|
|
||||||
tagName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
authorization: `token ${token}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const releases = repository.releases.nodes.reverse();
|
|
||||||
let latestValidRelease = releases.find(release => isValidVersion(release.tagName, type));
|
|
||||||
if (latestValidRelease)
|
|
||||||
return latestValidRelease.tagName;
|
|
||||||
} catch (err) {
|
|
||||||
core.warning(util.format("Error while fetching the latest Helm %s release. Error: %s. Using default Helm version %s.", type, err.toString(), getStableHelmVersionFor(type)));
|
|
||||||
return getStableHelmVersionFor(type);
|
|
||||||
}
|
|
||||||
core.warning(util.format("Could not find stable release for Helm %s. Using default Helm version %s.", type, getStableHelmVersionFor(type)));
|
|
||||||
return getStableHelmVersionFor(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStableHelmVersionFor(type: string) {
|
|
||||||
return type === "v2" ? stableHelm2Version : stableHelm3Version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// isValidVersion checks if verison matches the specified type and is a stable release
|
|
||||||
function isValidVersion(version: string, type: string): boolean {
|
|
||||||
if (!version.toLocaleLowerCase().startsWith(type))
|
|
||||||
return false;
|
|
||||||
return version.indexOf('rc') == -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findHelm(rootFolder: string): string {
|
export function findHelm(rootFolder: string): string {
|
||||||
fs.chmodSync(rootFolder, '777');
|
fs.chmodSync(rootFolder, '777')
|
||||||
var filelist: string[] = [];
|
var filelist: string[] = []
|
||||||
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension());
|
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension())
|
||||||
if (!filelist || filelist.length == 0) {
|
if (!filelist || filelist.length == 0) {
|
||||||
throw new Error(util.format("Helm executable not found in path", rootFolder));
|
throw new Error(
|
||||||
}
|
util.format('Helm executable not found in path', rootFolder)
|
||||||
else {
|
)
|
||||||
return filelist[0];
|
} else {
|
||||||
}
|
return filelist[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run() {
|
export var walkSync = function (dir, filelist, fileToFind) {
|
||||||
let version = core.getInput('version', { 'required': true });
|
var files = fs.readdirSync(dir)
|
||||||
|
filelist = filelist || []
|
||||||
if (process.env['HELM_INSTALLER_LEGACY_VERSIONING'] == 'true') {
|
files.forEach(function (file) {
|
||||||
if (version.toLocaleLowerCase() === 'latest') {
|
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
||||||
version = await getStableHelmVersion();
|
filelist = walkSync(path.join(dir, file), filelist, fileToFind)
|
||||||
} else if (!version.toLocaleLowerCase().startsWith('v')) {
|
} else {
|
||||||
version = 'v' + version;
|
core.debug(file)
|
||||||
}
|
if (file == fileToFind) {
|
||||||
} else {
|
filelist.push(path.join(dir, file))
|
||||||
if (version.toLocaleLowerCase() === 'latest' || version === LATEST_HELM3_VERSION) {
|
}
|
||||||
version = await getLatestHelmVersionFor("v3");
|
}
|
||||||
} else if (version === LATEST_HELM2_VERSION) {
|
})
|
||||||
version = await getLatestHelmVersionFor("v2");
|
return filelist
|
||||||
} else if (!version.toLocaleLowerCase().startsWith('v')) {
|
|
||||||
version = 'v' + version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core.debug(util.format("Downloading %s", version));
|
|
||||||
let cachedPath = await downloadHelm(version);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (!process.env['PATH'].startsWith(path.dirname(cachedPath))) {
|
|
||||||
core.addPath(path.dirname(cachedPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
//do nothing, set as output variable
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Helm tool version: '${version}' has been cached at ${cachedPath}`);
|
|
||||||
core.setOutput('helm-path', cachedPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(core.setFailed);
|
run().catch(core.setFailed)
|
||||||
|
114
tsconfig.json
114
tsconfig.json
@ -1,64 +1,64 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||||
// "composite": true, /* Enable project compilation */
|
// "composite": true, /* Enable project compilation */
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
/* Strict Type-Checking Options */
|
||||||
//"strict": true, /* Enable all strict type-checking options. */
|
//"strict": true, /* Enable all strict type-checking options. */
|
||||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
/* Additional Checks */
|
/* Additional Checks */
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
/* Source Map Options */
|
/* Source Map Options */
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
/* Experimental Options */
|
/* Experimental Options */
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "**/*.test.ts"]
|
"exclude": ["node_modules", "**/*.test.ts"]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user