Compare commits

...

21 Commits

Author SHA1 Message Date
GitHub Action
29960d0f5f build 2024-02-12 23:31:28 +00:00
David Gamero
0788eb3317 v4 release and required workflow updates (#125)
* v4 release and workflow update

* Update release-pr.yml

* Update release-pr.yml

* Update package.json

* format
2024-02-12 18:30:35 -05:00
Dmytro Bondar
208de6bd49 Upgrade action to use node20 (#121)
* Action update:

- Bump all dependencies
- Rewrite `getLatestHelmVersion()` function without graphql

* Bump stableHelmVersion

* Update readme and action.yaml

* Revert and rewrite with @octokit/action

* Add latest to integration test

* Bump action's versions

* Set github.token as default input

* Replace deprecated jest methods

* Add prettier to dev dependencies, fix prettier issues
2024-02-08 13:49:56 -05:00
dependabot[bot]
1f87a575d0 Bump @babel/traverse from 7.18.6 to 7.23.2 (#118)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.18.6 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 12:16:17 -05:00
Paul Vollmer
d336b89352 Add action input to set download base url (#113)
* feat: add downloadBaseURL action input

* feat: downloadHelm and getHelmDownloadURL added baseURL function argument

* refactor: building the helm download url

* chore: format code

---------

Co-authored-by: Paul Vollmer <mail@paulvollmer.net>
2024-01-02 09:30:48 -05:00
Teko
ac5ee1fca8 Update helm to v3.11.1 (#108) 2023-02-16 19:41:09 -05:00
dependabot[bot]
638a523e0c Bump decode-uri-component from 0.2.0 to 0.2.2 (#105)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 13:29:26 -05:00
dependabot[bot]
0a7ec47357 Bump json5 from 2.2.1 to 2.2.3 (#107)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 13:29:07 -05:00
Teko
3419a8fa8f Update README to reflect current default helm version (#106) 2023-01-10 13:26:20 -05:00
Ajay Kemparaj
f77071b246 minor nit , upgrade helm and GH action version updates (#102) 2022-12-27 09:28:27 -05:00
Asa Gayle
a4617735aa Added support message (#95) 2022-11-28 13:51:20 -05:00
Joe Previte
2dafda840c refactor: cleanup GH gql query (#100) 2022-10-27 09:44:25 -04:00
Brian Loss
b70d33f56d Update actions/toolkit versions. (#94)
Update actions/core to version 1.10.0 to avoid the warning:
```
The `set-output` command is deprecated and will be disabled soon.
Please upgrade to using Environment Files. For more information see:
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
```
2022-10-17 14:07:50 -04:00
Vidya Reddy
3c00c0152f syntax error fixes (#93) 2022-09-21 11:12:26 -07:00
Vidya Reddy
22d14750db Add the bug report and feature request form (#92) 2022-09-06 13:09:28 -04:00
dependabot[bot]
a22741c887 Bump @actions/core from 1.9.0 to 1.9.1 (#91)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.9.0 to 1.9.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 13:44:48 -04:00
Oliver King
f850d12cb3 Fix [object Object] version bug (#88)
* fix auth

* fix tag bug
2022-07-25 13:53:22 -04:00
Oliver King
17cd77473c fix auth (#86) 2022-07-25 13:13:50 -04:00
Oliver King
484a64052d Swap to GraphQL and add logging (#83)
* swap to graphql

* add logs

* swap to group log

* fix test
2022-07-11 10:12:11 -04:00
Bert Roos
6e32762c2e Minor spelling correction in README.md (#81) 2022-07-06 10:45:43 -04:00
Vidya Reddy
17c21ab68c upgrade ncc version (#82)
* upgrade ncc version

* Clear and verify npm cache

Co-authored-by: Vidya Reddy <vidyareddy@microsoft.com>
2022-07-05 10:17:02 -07:00
17 changed files with 60418 additions and 8941 deletions

View 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
View 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.

View 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

View File

@@ -13,7 +13,7 @@ jobs:
# 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@v3 - uses: actions/stale@v9
name: Setting issue as idle name: Setting issue as idle
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
@@ -24,7 +24,7 @@ jobs:
operations-per-run: 100 operations-per-run: 100
exempt-issue-labels: 'backlog' exempt-issue-labels: 'backlog'
- uses: actions/stale@v3 - uses: actions/stale@v9
name: Setting PR as idle name: Setting PR as idle
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -15,7 +15,7 @@ jobs:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }} 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
- name: npm install and build - name: npm install and build
id: action-npm-build id: action-npm-build
run: | run: |
@@ -63,3 +63,25 @@ jobs:
else else
echo "HELM VERSION $HELM_3_5_0 INSTALLED SUCCESSFULLY" echo "HELM VERSION $HELM_3_5_0 INSTALLED SUCCESSFULLY"
fi 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 runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Enforce Prettier - name: Enforce Prettier
uses: actionsx/prettier@v2 uses: actionsx/prettier@v3
with: with:
args: --check . args: --check .

View File

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

View File

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

3
.gitignore vendored
View File

@@ -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
@@ -64,4 +62,3 @@ node_modules
coverage coverage
# Transpiled JS # Transpiled JS
lib/

5
CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
# Change Log
## [4.0.0] - 2024-02-12
- #121 update to node20 as node16 is deprecated

View File

@@ -4,19 +4,23 @@ Install a specific version of helm binary on the runner.
## Example ## 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 and v3 of this action only supports 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 support Helm3.
```yaml ```yaml
- uses: azure/setup-helm@v3 - uses: azure/setup-helm@v3
with: with:
version: '<version>' # default is latest stable version: '<version>' # default is latest (stable)
token: ${{ secrets.GITHUB_TOKEN }} # only needed if version is 'latest'
id: install id: install
``` ```
> [!NOTE]
> 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.
The cached helm binary path is prepended to the PATH environment variable as well as stored in the helm-path output variable. 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 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 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
@@ -29,3 +33,7 @@ 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/). 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 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. 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,11 +5,19 @@ inputs:
description: 'Version of helm' description: 'Version of helm'
required: true required: true
default: 'latest' default: 'latest'
token:
description: GitHub token. Required only if 'version' == 'latest'
required: false
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: 'node16' using: 'node20'
main: 'lib/index.js' main: 'lib/index.js'

58492
lib/index.js Normal file

File diff suppressed because one or more lines are too long

10463
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,17 @@
"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/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
"prebuild": "npm i ncc",
"build": "ncc build src/run.ts -o lib", "build": "ncc build src/run.ts -o lib",
"test": "jest", "test": "jest",
"test-coverage": "jest --coverage", "test-coverage": "jest --coverage",
@@ -22,11 +24,12 @@
"format-check": "prettier --check ." "format-check": "prettier --check ."
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^26.0.0", "@types/jest": "^29.5.11",
"@types/node": "^12.0.10", "@types/node": "^20.11.8",
"@vercel/ncc": "^0.33.1", "@vercel/ncc": "^0.38.1",
"jest": "^26.0.1", "jest": "^29.7.0",
"ts-jest": "^26.0.0", "prettier": "^3.2.5",
"typescript": "^3.5.2" "ts-jest": "^29.1.2",
"typescript": "^5.3.3"
} }
} }

View File

@@ -10,55 +10,64 @@ describe('run.ts', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT') jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
expect(run.getExecutableExtension()).toBe('.exe') expect(run.getExecutableExtension()).toBe('.exe')
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
}) })
test('getExecutableExtension() - return empty string for non-windows OS', () => { test('getExecutableExtension() - return empty string for non-windows OS', () => {
jest.spyOn(os, 'type').mockReturnValue('Darwin') jest.spyOn(os, 'type').mockReturnValue('Darwin')
expect(run.getExecutableExtension()).toBe('') expect(run.getExecutableExtension()).toBe('')
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Linux', () => { test('getHelmDownloadURL() - return the URL to download helm for Linux', () => {
const downloadBaseURL = 'https://test.tld'
jest.spyOn(os, 'type').mockReturnValue('Linux') jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown') jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
const kubectlLinuxUrl = 'https://get.helm.sh/helm-v3.8.0-linux-amd64.zip' const helmLinuxUrl = 'https://test.tld/helm-v3.8.0-linux-amd64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlLinuxUrl) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
expect(os.type).toBeCalled() helmLinuxUrl
expect(os.arch).toBeCalled() )
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
// arm64 // arm64
jest.spyOn(os, 'type').mockReturnValue('Linux') jest.spyOn(os, 'type').mockReturnValue('Linux')
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64') jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
const kubectlLinuxArm64Url = const helmLinuxArm64Url = 'https://test.tld/helm-v3.8.0-linux-arm64.zip'
'https://get.helm.sh/helm-v3.8.0-linux-arm64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlLinuxArm64Url) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
expect(os.type).toBeCalled() helmLinuxArm64Url
expect(os.arch).toBeCalled() )
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => { test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => {
const downloadBaseURL = 'https://test.tld'
jest.spyOn(os, 'type').mockReturnValue('Darwin') jest.spyOn(os, 'type').mockReturnValue('Darwin')
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown') jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
const kubectlDarwinUrl = const helmDarwinUrl = 'https://test.tld/helm-v3.8.0-darwin-amd64.zip'
'https://get.helm.sh/helm-v3.8.0-darwin-amd64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlDarwinUrl) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
expect(os.type).toBeCalled() helmDarwinUrl
expect(os.arch).toBeCalled() )
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
// arm64 // arm64
jest.spyOn(os, 'type').mockReturnValue('Darwin') jest.spyOn(os, 'type').mockReturnValue('Darwin')
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64') jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
const kubectlDarwinArm64Url = const helmDarwinArm64Url = 'https://test.tld/helm-v3.8.0-darwin-arm64.zip'
'https://get.helm.sh/helm-v3.8.0-darwin-arm64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlDarwinArm64Url) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
expect(os.type).toBeCalled() helmDarwinArm64Url
expect(os.arch).toBeCalled() )
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
}) })
test('getValidVersion() - return version with v prepended', () => { test('getValidVersion() - return version with v prepended', () => {
@@ -66,20 +75,19 @@ describe('run.ts', () => {
}) })
test('getHelmDownloadURL() - return the URL to download helm for Windows', () => { test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
const downloadBaseURL = 'https://test.tld'
jest.spyOn(os, 'type').mockReturnValue('Windows_NT') jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
const kubectlWindowsUrl = const helmWindowsUrl = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
'https://get.helm.sh/helm-v3.8.0-windows-amd64.zip' expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
expect(run.getHelmDownloadURL('v3.8.0')).toBe(kubectlWindowsUrl) helmWindowsUrl
expect(os.type).toBeCalled() )
expect(os.type).toHaveBeenCalled()
}) })
test('getLatestHelmVersion() - return the latest version of HELM', async () => { test('getLatestHelmVersion() - return the stable version of HELM since its not authenticated', async () => {
try { expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
expect(await run.getLatestHelmVersion()).toBe('v3.8.0')
} catch (e) {
return e
}
}) })
test('walkSync() - return path to the all files matching fileToFind in dir', () => { test('walkSync() - return path to the all files matching fileToFind in dir', () => {
@@ -112,8 +120,8 @@ describe('run.ts', () => {
expect(run.walkSync('mainFolder', null, 'file21')).toEqual([ expect(run.walkSync('mainFolder', null, 'file21')).toEqual([
path.join('mainFolder', 'folder2', 'file21') path.join('mainFolder', 'folder2', 'file21')
]) ])
expect(fs.readdirSync).toBeCalledTimes(3) expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8) expect(fs.statSync).toHaveBeenCalledTimes(8)
}) })
test('walkSync() - return empty array if no file with name fileToFind exists', () => { test('walkSync() - return empty array if no file with name fileToFind exists', () => {
@@ -144,8 +152,8 @@ describe('run.ts', () => {
}) })
expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([]) expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([])
expect(fs.readdirSync).toBeCalledTimes(3) expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8) expect(fs.statSync).toHaveBeenCalledTimes(8)
}) })
test('findHelm() - change access permissions and find the helm in given directory', () => { test('findHelm() - change access permissions and find the helm in given directory', () => {
@@ -199,16 +207,18 @@ describe('run.ts', () => {
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
}) })
expect(await run.downloadHelm('v4.0.0')).toBe( const baseURL = 'https://test.tld'
expect(await run.downloadHelm(baseURL, 'v4.0.0')).toBe(
path.join('pathToCachedDir', 'helm.exe') path.join('pathToCachedDir', 'helm.exe')
) )
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0') expect(toolCache.find).toHaveBeenCalledWith('helm', 'v4.0.0')
expect(toolCache.downloadTool).toBeCalledWith( expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://get.helm.sh/helm-v4.0.0-windows-amd64.zip' 'https://test.tld/helm-v4.0.0-windows-amd64.zip'
) )
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777') expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool') expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
expect(fs.chmodSync).toBeCalledWith( expect(fs.chmodSync).toHaveBeenCalledWith(
path.join('pathToCachedDir', 'helm.exe'), path.join('pathToCachedDir', 'helm.exe'),
'777' '777'
) )
@@ -221,12 +231,14 @@ describe('run.ts', () => {
}) })
jest.spyOn(os, 'type').mockReturnValue('Windows_NT') jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
await expect(run.downloadHelm('v3.2.1')).rejects.toThrow( const baseURL = 'https://test.tld'
'Failed to download Helm from location https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
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).toBeCalledWith('helm', 'v3.2.1') expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(toolCache.downloadTool).toBeCalledWith( expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip' 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
) )
}) })
@@ -234,11 +246,13 @@ describe('run.ts', () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir') jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {}) jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
expect(await run.downloadHelm('v3.2.1')).toBe( const baseURL = 'https://test.tld'
expect(await run.downloadHelm(baseURL, 'v3.2.1')).toBe(
path.join('pathToCachedDir', 'helm.exe') path.join('pathToCachedDir', 'helm.exe')
) )
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1') expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(fs.chmodSync).toBeCalledWith( expect(fs.chmodSync).toHaveBeenCalledWith(
path.join('pathToCachedDir', 'helm.exe'), path.join('pathToCachedDir', 'helm.exe'),
'777' '777'
) )
@@ -260,14 +274,16 @@ describe('run.ts', () => {
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
}) })
await expect(run.downloadHelm('v3.2.1')).rejects.toThrow( const baseURL = 'https://test.tld'
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
'Helm executable not found in path pathToCachedDir' 'Helm executable not found in path pathToCachedDir'
) )
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1') expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(toolCache.downloadTool).toBeCalledWith( expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip' 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
) )
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777') expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool') expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
}) })
}) })

View File

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