Compare commits

..

2 Commits

Author SHA1 Message Date
83902c34cd Clear and verify npm cache 2022-07-01 14:48:58 -07:00
7b23fe67ac upgrade ncc version 2022-07-01 14:45:18 -07:00
17 changed files with 8975 additions and 32460 deletions

View File

@ -1,36 +0,0 @@
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

View File

@ -1,6 +0,0 @@
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.

View File

@ -1,13 +0,0 @@
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

View File

@ -13,7 +13,7 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/stale@v9
- uses: actions/stale@v3
name: Setting issue as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
@ -24,7 +24,7 @@ jobs:
operations-per-run: 100
exempt-issue-labels: 'backlog'
- uses: actions/stale@v9
- uses: actions/stale@v3
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -15,7 +15,7 @@ jobs:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: npm install and build
id: action-npm-build
run: |
@ -63,25 +63,3 @@ jobs:
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

View File

@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Enforce Prettier
uses: actionsx/prettier@v3
uses: actionsx/prettier@v2
with:
args: --check .

View File

@ -1,18 +1,14 @@
name: Release Project
name: Create release PR
on:
push:
branches:
- main
paths:
- CHANGELOG.md
workflow_dispatch:
inputs:
release:
description: 'Define release version (ex: v1, v2, v3)'
required: true
jobs:
release:
permissions:
actions: read
contents: write
uses: Azure/action-release-workflows/.github/workflows/release_js_project.yaml@a705b2ab6a3ee889f2b0d925ad0bd2f9eb733ce6
release-pr:
uses: OliverMKing/javascript-release-workflow/.github/workflows/release-pr.yml@main
with:
changelogPath: ./CHANGELOG.md
release: ${{ github.event.inputs.release }}

View File

@ -13,7 +13,7 @@ jobs:
build: # make sure build/ci works properly
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v1
- name: Run L0 tests.
run: |

3
.gitignore vendored
View File

@ -11,6 +11,8 @@ pids
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
@ -62,3 +64,4 @@ node_modules
coverage
# Transpiled JS
lib/

View File

@ -1,9 +0,0 @@
# Change Log
## [4.1.0] - 2024-03-01
- #130 switches to use Helm published file to read latest version instead of using GitHub releases
## [4.0.0] - 2024-02-12
- #121 update to node20 as node16 is deprecated

View File

@ -4,22 +4,19 @@ Install a specific version of helm binary on the runner.
## Example
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+ of this action only support Helm3.
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 supports Helm3.
```yaml
- uses: azure/setup-helm@v4.1.0
- uses: azure/setup-helm@v3
with:
version: '<version>' # default is latest (stable)
version: '<version>' # default is latest stable
id: install
```
> [!NOTE]
> If something goes wrong with fetching the latest version the action will use the hardcoded default stable version (currently v3.13.3). If you rely on a certain version higher than the default, you should explicitly use that version instead of latest.
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
## Contributing
# Contributing
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
@ -32,7 +29,3 @@ provided by the bot. You will only need to do this once across all repos using o
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.

View File

@ -5,20 +5,11 @@ inputs:
description: 'Version of helm'
required: true
default: 'latest'
token:
description: GitHub token. Used to be required to fetch the latest version
required: false
deprecationMessage: 'GitHub token is no longer required'
default: '${{ github.token }}'
downloadBaseURL:
description: 'Set the download base URL'
required: false
default: 'https://get.helm.sh'
outputs:
helm-path:
description: 'Path to the cached helm binary'
branding:
color: 'blue'
runs:
using: 'node20'
using: 'node16'
main: 'lib/index.js'

30640
lib/index.js

File diff suppressed because one or more lines are too long

10384
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,20 @@
{
"name": "setuphelm",
"version": "4.1.0",
"version": "0.0.0",
"private": true,
"description": "Setup helm",
"author": "Anumita Shenoy",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.2",
"@actions/tool-cache": "2.0.1",
"@octokit/action": "^6.0.7",
"ncc": "^0.3.6",
"semver": "^7.5.4"
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/io": "^1.0.0",
"@actions/tool-cache": "1.1.2",
"@octokit/graphql": "^4.6.1",
"semver": "^6.1.0"
},
"main": "lib/index.js",
"scripts": {
"prebuild": "npm i ncc",
"build": "ncc build src/run.ts -o lib",
"test": "jest",
"test-coverage": "jest --coverage",
@ -24,12 +22,11 @@
"format-check": "prettier --check ."
},
"devDependencies": {
"@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"
"@types/jest": "^26.0.0",
"@types/node": "^12.0.10",
"@vercel/ncc": "^0.34.0",
"jest": "^26.0.1",
"ts-jest": "^26.0.0",
"typescript": "^3.5.2"
}
}

View File

@ -10,64 +10,55 @@ describe('run.ts', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
expect(run.getExecutableExtension()).toBe('.exe')
expect(os.type).toHaveBeenCalled()
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).toHaveBeenCalled()
expect(os.type).toBeCalled()
})
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'
const kubectlLinuxUrl = 'https://get.helm.sh/helm-v3.8.0-linux-amd64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmLinuxUrl
)
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
// 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'
const kubectlLinuxArm64Url =
'https://get.helm.sh/helm-v3.8.0-linux-arm64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmLinuxArm64Url
)
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlLinuxArm64Url)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
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'
const kubectlDarwinUrl =
'https://get.helm.sh/helm-v3.8.0-darwin-amd64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmDarwinUrl
)
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlDarwinUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
// 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'
const kubectlDarwinArm64Url =
'https://get.helm.sh/helm-v3.8.0-darwin-arm64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmDarwinArm64Url
)
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlDarwinArm64Url)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
})
test('getValidVersion() - return version with v prepended', () => {
@ -75,30 +66,20 @@ describe('run.ts', () => {
})
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()
const kubectlWindowsUrl =
'https://get.helm.sh/helm-v3.8.0-windows-amd64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlWindowsUrl)
expect(os.type).toBeCalled()
})
test('getLatestHelmVersion() - return the latest version of HELM', async () => {
const res = {
status: 200,
text: async () => 'v9.99.999'
} as Response
global.fetch = jest.fn().mockReturnValue(res)
expect(await run.getLatestHelmVersion()).toBe('v9.99.999')
})
test('getLatestHelmVersion() - return the stable version of HELM when simulating a network error', async () => {
const errorMessage: string = 'Network Error'
global.fetch = jest.fn().mockRejectedValueOnce(new Error(errorMessage))
expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
try {
expect(await run.getLatestHelmVersion()).toBe('v3.8.0')
} catch (e) {
return e
}
})
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
@ -131,8 +112,8 @@ describe('run.ts', () => {
expect(run.walkSync('mainFolder', null, 'file21')).toEqual([
path.join('mainFolder', 'folder2', 'file21')
])
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toHaveBeenCalledTimes(8)
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
})
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
@ -163,8 +144,8 @@ describe('run.ts', () => {
})
expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([])
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toHaveBeenCalledTimes(8)
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
})
test('findHelm() - change access permissions and find the helm in given directory', () => {
@ -218,18 +199,16 @@ describe('run.ts', () => {
return {isDirectory: () => isDirectory} as fs.Stats
})
const baseURL = 'https://test.tld'
expect(await run.downloadHelm(baseURL, 'v4.0.0')).toBe(
expect(await run.downloadHelm('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(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).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
expect(fs.chmodSync).toHaveBeenCalledWith(
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
@ -242,14 +221,12 @@ describe('run.ts', () => {
})
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'
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).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://test.tld/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'
)
})
@ -257,13 +234,11 @@ describe('run.ts', () => {
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(
expect(await run.downloadHelm('v3.2.1')).toBe(
path.join('pathToCachedDir', 'helm.exe')
)
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(fs.chmodSync).toHaveBeenCalledWith(
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1')
expect(fs.chmodSync).toBeCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
@ -285,16 +260,14 @@ describe('run.ts', () => {
return {isDirectory: () => isDirectory} as fs.Stats
})
const baseURL = 'https://test.tld'
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
await expect(run.downloadHelm('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(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).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
})
})

View File

@ -11,24 +11,21 @@ import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
const helmToolName = 'helm'
const stableHelmVersion = 'v3.13.3'
const stableHelmVersion = 'v3.8.0'
const helmAllReleasesUrl = 'https://api.github.com/repos/helm/helm/releases'
export async function run() {
let version = core.getInput('version', {required: true})
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()
core.debug(util.format('Downloading %s', version))
let cachedPath = await downloadHelm(version)
try {
if (!process.env['PATH'].startsWith(path.dirname(cachedPath))) {
@ -38,27 +35,47 @@ export async function run() {
//do nothing, set as output variable
}
core.info(`Helm tool version '${version}' has been cached at ${cachedPath}`)
console.log(
`Helm tool version: '${version}' has been cached at ${cachedPath}`
)
core.setOutput('helm-path', cachedPath)
}
// Prefixes version with v
//Returns version with proper v before it
export function getValidVersion(version: string): string {
return 'v' + version
}
// Gets the latest helm version or returns a default stable if getting latest fails
// Downloads the helm releases JSON and parses all the recent versions of helm from it.
// Defaults to sending stable helm version if none are valid or if it fails
export async function getLatestHelmVersion(): Promise<string> {
const helmJSONPath: string = await toolCache.downloadTool(helmAllReleasesUrl)
try {
const response = await fetch('https://get.helm.sh/helm-latest-version')
const release = (await response.text()).trim()
return release
const helmJSON = JSON.parse(fs.readFileSync(helmJSONPath, 'utf-8'))
for (let i in helmJSON) {
if (isValidVersion(helmJSON[i].tag_name)) {
return helmJSON[i].tag_name
}
}
} catch (err) {
core.warning(
`Error while fetching latest Helm release: ${err.toString()}. Using default version ${stableHelmVersion}`
util.format(
'Error while fetching the latest Helm release. Error: %s. Using default Helm version %s',
err.toString(),
stableHelmVersion
)
)
return 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 {
@ -72,51 +89,56 @@ const LINUX = 'Linux'
const MAC_OS = 'Darwin'
const WINDOWS = 'Windows_NT'
const ARM64 = 'arm64'
export function getHelmDownloadURL(baseURL: string, version: string): string {
export function getHelmDownloadURL(version: string): string {
const arch = os.arch()
const operatingSystem = os.type()
let urlPath = ''
switch (true) {
case operatingSystem == LINUX && arch == ARM64:
urlPath = util.format(`/helm-%s-linux-arm64.zip`, version)
break
return util.format(
'https://get.helm.sh/helm-%s-linux-arm64.zip',
version
)
case operatingSystem == LINUX:
urlPath = util.format(`/helm-%s-linux-amd64.zip`, version)
break
return util.format(
'https://get.helm.sh/helm-%s-linux-amd64.zip',
version
)
case operatingSystem == MAC_OS && arch == ARM64:
urlPath = util.format(`/helm-%s-darwin-arm64.zip`, version)
break
return util.format(
'https://get.helm.sh/helm-%s-darwin-arm64.zip',
version
)
case operatingSystem == MAC_OS:
urlPath = util.format(`/helm-%s-darwin-amd64.zip`, version)
break
return util.format(
'https://get.helm.sh/helm-%s-darwin-amd64.zip',
version
)
case operatingSystem == WINDOWS:
default:
urlPath = util.format(`/helm-%s-windows-amd64.zip`, version)
return util.format(
'https://get.helm.sh/helm-%s-windows-amd64.zip',
version
)
}
const url = new URL(urlPath, baseURL)
return url.toString()
}
export async function downloadHelm(
baseURL: string,
version: string
): Promise<string> {
export async function downloadHelm(version: string): Promise<string> {
let cachedToolpath = toolCache.find(helmToolName, version)
if (!cachedToolpath) {
let helmDownloadPath
try {
helmDownloadPath = await toolCache.downloadTool(
getHelmDownloadURL(baseURL, version)
getHelmDownloadURL(version)
)
} catch (exception) {
throw new Error(
`Failed to download Helm from location ${getHelmDownloadURL(
baseURL,
version
)}`
util.format(
'Failed to download Helm from location',
getHelmDownloadURL(version)
)
)
}