5 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
14 changed files with 60181 additions and 8824 deletions

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@v6
- uses: actions/stale@v9
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@v6
- uses: actions/stale@v9
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@v3
uses: actions/checkout@v4
- name: npm install and build
id: action-npm-build
run: |
@@ -63,3 +63,25 @@ 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@v3
uses: actions/checkout@v4
- name: Enforce Prettier
uses: actionsx/prettier@v2
uses: actionsx/prettier@v3
with:
args: --check .

View File

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

View File

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

3
.gitignore vendored
View File

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

@@ -14,7 +14,8 @@ Acceptable values are latest or any semantic version string like v3.5.0 Use this
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.11.1). If you rely on a certain version higher than the default, you should use that version instead of latest.
> [!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.
Refer to the action metadata file for details about all the inputs https://github.com/Azure/setup-helm/blob/master/action.yml

View File

@@ -8,11 +8,16 @@ inputs:
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:
helm-path:
description: 'Path to the cached helm binary'
branding:
color: 'blue'
runs:
using: 'node16'
using: 'node20'
main: 'lib/index.js'

58492
lib/index.js Normal file

File diff suppressed because one or more lines are too long

10210
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,12 +10,13 @@
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.2",
"@actions/tool-cache": "2.0.1",
"@octokit/auth-action": "^2.0.0",
"@octokit/graphql": "^4.6.1",
"semver": "^6.1.0"
"@octokit/action": "^6.0.7",
"ncc": "^0.3.6",
"semver": "^7.5.4"
},
"main": "lib/index.js",
"scripts": {
"prebuild": "npm i ncc",
"build": "ncc build src/run.ts -o lib",
"test": "jest",
"test-coverage": "jest --coverage",
@@ -23,11 +24,12 @@
"format-check": "prettier --check ."
},
"devDependencies": {
"@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"
"@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"
}
}

View File

@@ -10,54 +10,64 @@ describe('run.ts', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
expect(run.getExecutableExtension()).toBe('.exe')
expect(os.type).toBeCalled()
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).toBeCalled()
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://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(helmLinuxUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
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://get.helm.sh/helm-v3.8.0-linux-arm64.zip'
const helmLinuxArm64Url = 'https://test.tld/helm-v3.8.0-linux-arm64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(helmLinuxArm64Url)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
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://get.helm.sh/helm-v3.8.0-darwin-amd64.zip'
const helmDarwinUrl = 'https://test.tld/helm-v3.8.0-darwin-amd64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(helmDarwinUrl)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
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://get.helm.sh/helm-v3.8.0-darwin-arm64.zip'
const helmDarwinArm64Url = 'https://test.tld/helm-v3.8.0-darwin-arm64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(helmDarwinArm64Url)
expect(os.type).toBeCalled()
expect(os.arch).toBeCalled()
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmDarwinArm64Url
)
expect(os.type).toHaveBeenCalled()
expect(os.arch).toHaveBeenCalled()
})
test('getValidVersion() - return version with v prepended', () => {
@@ -65,15 +75,19 @@ 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://get.helm.sh/helm-v3.8.0-windows-amd64.zip'
expect(run.getHelmDownloadURL('v3.8.0')).toBe(helmWindowsUrl)
expect(os.type).toBeCalled()
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.11.1')
expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
})
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
@@ -106,8 +120,8 @@ describe('run.ts', () => {
expect(run.walkSync('mainFolder', null, 'file21')).toEqual([
path.join('mainFolder', 'folder2', 'file21')
])
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toHaveBeenCalledTimes(8)
})
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
@@ -138,8 +152,8 @@ describe('run.ts', () => {
})
expect(run.walkSync('mainFolder', null, 'helm.exe')).toEqual([])
expect(fs.readdirSync).toBeCalledTimes(3)
expect(fs.statSync).toBeCalledTimes(8)
expect(fs.readdirSync).toHaveBeenCalledTimes(3)
expect(fs.statSync).toHaveBeenCalledTimes(8)
})
test('findHelm() - change access permissions and find the helm in given directory', () => {
@@ -193,16 +207,18 @@ describe('run.ts', () => {
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')
)
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0')
expect(toolCache.downloadTool).toBeCalledWith(
'https://get.helm.sh/helm-v4.0.0-windows-amd64.zip'
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).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
expect(fs.chmodSync).toBeCalledWith(
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
expect(fs.chmodSync).toHaveBeenCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
@@ -215,12 +231,14 @@ describe('run.ts', () => {
})
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'
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).toBeCalledWith('helm', 'v3.2.1')
expect(toolCache.downloadTool).toBeCalledWith(
'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'
)
})
@@ -228,11 +246,13 @@ describe('run.ts', () => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
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')
)
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1')
expect(fs.chmodSync).toBeCalledWith(
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
expect(fs.chmodSync).toHaveBeenCalledWith(
path.join('pathToCachedDir', 'helm.exe'),
'777'
)
@@ -254,14 +274,16 @@ describe('run.ts', () => {
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'
)
expect(toolCache.find).toBeCalledWith('helm', 'v3.2.1')
expect(toolCache.downloadTool).toBeCalledWith(
'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(fs.chmodSync).toBeCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
expect(fs.chmodSync).toHaveBeenCalledWith('pathToTool', '777')
expect(toolCache.extractZip).toHaveBeenCalledWith('pathToTool')
})
})

View File

@@ -9,11 +9,10 @@ import * as fs from 'fs'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import {graphql} from '@octokit/graphql'
import {createActionAuth} from '@octokit/auth-action'
import {Octokit} from '@octokit/action'
const helmToolName = 'helm'
const stableHelmVersion = 'v3.11.1'
const stableHelmVersion = 'v3.13.3'
export async function run() {
let version = core.getInput('version', {required: true})
@@ -26,8 +25,10 @@ export async function run() {
version = await getLatestHelmVersion()
}
const downloadBaseURL = core.getInput('downloadBaseURL', {required: false})
core.startGroup(`Downloading ${version}`)
const cachedPath = await downloadHelm(version)
const cachedPath = await downloadHelm(downloadBaseURL, version)
core.endGroup()
try {
@@ -50,30 +51,20 @@ export function getValidVersion(version: string): string {
// Gets the latest helm version or returns a default stable if getting latest fails
export async function getLatestHelmVersion(): Promise<string> {
try {
const auth = createActionAuth()
const graphqlAuthenticated = graphql.defaults({
request: {hook: auth.hook}
const octokit = new Octokit()
const response = await octokit.rest.repos.listReleases({
owner: 'helm',
repo: 'helm',
per_page: 100,
order: 'desc',
sort: 'created'
})
const {repository} = await graphqlAuthenticated(
`
{
repository(name: "helm", owner: "helm") {
releases(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
tagName
isLatest
isDraft
isPrerelease
}
}
}
}
`
)
const latestValidRelease: string = repository.releases.nodes.find(
({tagName, isLatest, isDraft, isPreRelease}) =>
isValidVersion(tagName) && isLatest && !isDraft && !isPreRelease
)?.tagName
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) {
@@ -105,53 +96,49 @@ const LINUX = 'Linux'
const MAC_OS = 'Darwin'
const WINDOWS = 'Windows_NT'
const ARM64 = 'arm64'
export function getHelmDownloadURL(version: string): string {
export function getHelmDownloadURL(baseURL: string, version: string): string {
const arch = os.arch()
const operatingSystem = os.type()
let urlPath = ''
switch (true) {
case operatingSystem == LINUX && arch == ARM64:
return util.format(
'https://get.helm.sh/helm-%s-linux-arm64.zip',
version
)
urlPath = util.format(`/helm-%s-linux-arm64.zip`, version)
break
case operatingSystem == LINUX:
return util.format(
'https://get.helm.sh/helm-%s-linux-amd64.zip',
version
)
urlPath = util.format(`/helm-%s-linux-amd64.zip`, version)
break
case operatingSystem == MAC_OS && arch == ARM64:
return util.format(
'https://get.helm.sh/helm-%s-darwin-arm64.zip',
version
)
urlPath = util.format(`/helm-%s-darwin-arm64.zip`, version)
break
case operatingSystem == MAC_OS:
return util.format(
'https://get.helm.sh/helm-%s-darwin-amd64.zip',
version
)
urlPath = util.format(`/helm-%s-darwin-amd64.zip`, version)
break
case operatingSystem == WINDOWS:
default:
return util.format(
'https://get.helm.sh/helm-%s-windows-amd64.zip',
version
)
urlPath = util.format(`/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)
if (!cachedToolpath) {
let helmDownloadPath
try {
helmDownloadPath = await toolCache.downloadTool(
getHelmDownloadURL(version)
getHelmDownloadURL(baseURL, version)
)
} catch (exception) {
throw new Error(
`Failed to download Helm from location ${getHelmDownloadURL(
baseURL,
version
)}`
)