mirror of
https://github.com/Azure/setup-helm.git
synced 2025-11-07 13:06:56 +00:00
Merge 2da3d27d8f into 0400c1212d
This commit is contained in:
commit
4a94aef191
6 changed files with 139 additions and 18 deletions
|
|
@ -1,5 +1,11 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## [4.4.0] - 2025-10-29
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add fallback URL support via optional `downloadBaseURLFallback` input for improved download reliability
|
||||||
|
|
||||||
## [4.3.1] - 2025-08-12
|
## [4.3.1] - 2025-08-12
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Install a specific version of helm binary on the runner.
|
||||||
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+ of this action only support Helm3.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: azure/setup-helm@v4.3.0
|
- uses: azure/setup-helm@v4.4.0
|
||||||
with:
|
with:
|
||||||
version: '<version>' # default is latest (stable)
|
version: '<version>' # default is latest (stable)
|
||||||
id: install
|
id: install
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ inputs:
|
||||||
description: 'Set the download base URL'
|
description: 'Set the download base URL'
|
||||||
required: false
|
required: false
|
||||||
default: 'https://get.helm.sh'
|
default: 'https://get.helm.sh'
|
||||||
|
downloadBaseURLFallback:
|
||||||
|
description: 'Fallback base URL if primary download fails'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
outputs:
|
outputs:
|
||||||
helm-path:
|
helm-path:
|
||||||
description: 'Path to the cached helm binary'
|
description: 'Path to the cached helm binary'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "setuphelm",
|
"name": "setuphelm",
|
||||||
"version": "4.3.1",
|
"version": "4.4.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Setup helm",
|
"description": "Setup helm",
|
||||||
"author": "Anumita Shenoy",
|
"author": "Anumita Shenoy",
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ describe('run.ts', () => {
|
||||||
return {isDirectory: () => isDirectory} as fs.Stats
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(await run.downloadHelm(downloadBaseURL, 'v4.0.0')).toBe(
|
expect(await run.downloadHelm(downloadBaseURL, 'v4.0.0', '')).toBe(
|
||||||
path.join('pathToCachedDir', 'helm.exe')
|
path.join('pathToCachedDir', 'helm.exe')
|
||||||
)
|
)
|
||||||
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v4.0.0')
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v4.0.0')
|
||||||
|
|
@ -252,9 +252,9 @@ describe('run.ts', () => {
|
||||||
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||||
|
|
||||||
const downloadUrl = 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
const downloadUrl = 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
await expect(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
|
await expect(
|
||||||
`Failed to download Helm from location ${downloadUrl}`
|
run.downloadHelm(downloadBaseURL, 'v3.2.1', '')
|
||||||
)
|
).rejects.toThrow(`Failed to download Helm from location ${downloadUrl}`)
|
||||||
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
expect(toolCache.downloadTool).toHaveBeenCalledWith(`${downloadUrl}`)
|
expect(toolCache.downloadTool).toHaveBeenCalledWith(`${downloadUrl}`)
|
||||||
})
|
})
|
||||||
|
|
@ -278,7 +278,7 @@ describe('run.ts', () => {
|
||||||
return {isDirectory: () => isDirectory} as fs.Stats
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(await run.downloadHelm(downloadBaseURL, 'v3.2.1')).toBe(
|
expect(await run.downloadHelm(downloadBaseURL, 'v3.2.1', '')).toBe(
|
||||||
path.join('pathToCachedDir', 'helm.exe')
|
path.join('pathToCachedDir', 'helm.exe')
|
||||||
)
|
)
|
||||||
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
|
|
@ -304,9 +304,9 @@ describe('run.ts', () => {
|
||||||
return {isDirectory: () => isDirectory} as fs.Stats
|
return {isDirectory: () => isDirectory} as fs.Stats
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
|
await expect(
|
||||||
'Helm executable not found in path pathToCachedDir'
|
run.downloadHelm(downloadBaseURL, 'v3.2.1', '')
|
||||||
)
|
).rejects.toThrow('Helm executable not found in path pathToCachedDir')
|
||||||
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
|
||||||
expect(toolCache.downloadTool).toHaveBeenCalledWith(
|
expect(toolCache.downloadTool).toHaveBeenCalledWith(
|
||||||
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
|
@ -314,4 +314,86 @@ describe('run.ts', () => {
|
||||||
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
|
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
|
||||||
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
|
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - use fallback URL when primary download fails', async () => {
|
||||||
|
const fallbackBaseURL = 'https://fallback.tld'
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest
|
||||||
|
.spyOn(toolCache, 'downloadTool')
|
||||||
|
.mockRejectedValueOnce(new Error('Primary download failed'))
|
||||||
|
.mockResolvedValueOnce('pathToTool')
|
||||||
|
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
|
||||||
|
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||||
|
jest.spyOn(os, 'platform').mockReturnValue('win32')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||||
|
jest.spyOn(core, 'warning').mockImplementation()
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readdirSync')
|
||||||
|
.mockImplementation((file, _) => [
|
||||||
|
'helm.exe' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
|
||||||
|
])
|
||||||
|
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(downloadBaseURL, 'v3.2.1', fallbackBaseURL)
|
||||||
|
).toBe(path.join('pathToCachedDir', 'helm.exe'))
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledTimes(2)
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
'https://fallback.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(core.warning).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - throw error if both primary and fallback downloads fail', async () => {
|
||||||
|
const fallbackBaseURL = 'https://fallback.tld'
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest
|
||||||
|
.spyOn(toolCache, 'downloadTool')
|
||||||
|
.mockRejectedValueOnce(new Error('Primary download failed'))
|
||||||
|
.mockRejectedValueOnce(new Error('Fallback download failed'))
|
||||||
|
jest.spyOn(os, 'platform').mockReturnValue('win32')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
run.downloadHelm(downloadBaseURL, 'v3.2.1', fallbackBaseURL)
|
||||||
|
).rejects.toThrow(
|
||||||
|
'Failed to download Helm from location https://test.tld/helm-v3.2.1-windows-amd64.zip or https://fallback.tld/helm-v3.2.1-windows-amd64.zip'
|
||||||
|
)
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('downloadHelm() - work without fallback URL (backwards compatibility)', async () => {
|
||||||
|
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||||
|
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||||
|
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
|
||||||
|
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||||
|
jest.spyOn(os, 'platform').mockReturnValue('win32')
|
||||||
|
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||||
|
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readdirSync')
|
||||||
|
.mockImplementation((file, _) => [
|
||||||
|
'helm.exe' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
|
||||||
|
])
|
||||||
|
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(downloadBaseURL, 'v3.2.1')).toBe(
|
||||||
|
path.join('pathToCachedDir', 'helm.exe')
|
||||||
|
)
|
||||||
|
expect(toolCache.downloadTool).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
33
src/run.ts
33
src/run.ts
|
|
@ -24,9 +24,16 @@ export async function run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadBaseURL = core.getInput('downloadBaseURL', {required: false})
|
const downloadBaseURL = core.getInput('downloadBaseURL', {required: false})
|
||||||
|
const downloadBaseURLFallback = core.getInput('downloadBaseURLFallback', {
|
||||||
|
required: false
|
||||||
|
})
|
||||||
|
|
||||||
core.startGroup(`Installing ${version}`)
|
core.startGroup(`Installing ${version}`)
|
||||||
const cachedPath = await downloadHelm(downloadBaseURL, version)
|
const cachedPath = await downloadHelm(
|
||||||
|
downloadBaseURL,
|
||||||
|
version,
|
||||||
|
downloadBaseURLFallback
|
||||||
|
)
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -84,7 +91,8 @@ export function getHelmDownloadURL(baseURL: string, version: string): string {
|
||||||
|
|
||||||
export async function downloadHelm(
|
export async function downloadHelm(
|
||||||
baseURL: string,
|
baseURL: string,
|
||||||
version: string
|
version: string,
|
||||||
|
fallbackBaseURL?: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
let cachedToolpath = toolCache.find(helmToolName, version)
|
let cachedToolpath = toolCache.find(helmToolName, version)
|
||||||
if (cachedToolpath) {
|
if (cachedToolpath) {
|
||||||
|
|
@ -97,6 +105,26 @@ export async function downloadHelm(
|
||||||
getHelmDownloadURL(baseURL, version)
|
getHelmDownloadURL(baseURL, version)
|
||||||
)
|
)
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
|
if (fallbackBaseURL) {
|
||||||
|
core.warning(
|
||||||
|
`Failed to download Helm from location ${getHelmDownloadURL(
|
||||||
|
baseURL,
|
||||||
|
version
|
||||||
|
)}. Attempting to download from fallback URL: ${fallbackBaseURL}`
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
helmDownloadPath = await toolCache.downloadTool(
|
||||||
|
getHelmDownloadURL(fallbackBaseURL, version)
|
||||||
|
)
|
||||||
|
} catch (fallbackException) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to download Helm from location ${getHelmDownloadURL(
|
||||||
|
baseURL,
|
||||||
|
version
|
||||||
|
)} or ${getHelmDownloadURL(fallbackBaseURL, version)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to download Helm from location ${getHelmDownloadURL(
|
`Failed to download Helm from location ${getHelmDownloadURL(
|
||||||
baseURL,
|
baseURL,
|
||||||
|
|
@ -104,6 +132,7 @@ export async function downloadHelm(
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fs.chmodSync(helmDownloadPath, '777')
|
fs.chmodSync(helmDownloadPath, '777')
|
||||||
const extractedPath =
|
const extractedPath =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue