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
This commit is contained in:
Dmytro Bondar
2024-02-08 19:49:56 +01:00
committed by GitHub
parent 1f87a575d0
commit 208de6bd49
10 changed files with 1390 additions and 8797 deletions

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@v6 - 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@v6 - 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@v3 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@v3 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

@ -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@v3 - uses: actions/checkout@v4
- name: Run L0 tests. - name: Run L0 tests.
run: | run: |

View File

@ -14,7 +14,8 @@ Acceptable values are latest or any semantic version string like v3.5.0 Use this
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.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. 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

View File

@ -8,6 +8,7 @@ inputs:
token: token:
description: GitHub token. Required only if 'version' == 'latest' description: GitHub token. Required only if 'version' == 'latest'
required: false required: false
default: '${{ github.token }}'
downloadBaseURL: downloadBaseURL:
description: 'Set the download base URL' description: 'Set the download base URL'
required: false required: false
@ -18,5 +19,5 @@ outputs:
branding: branding:
color: 'blue' color: 'blue'
runs: runs:
using: 'node16' using: 'node20'
main: 'lib/index.js' main: 'lib/index.js'

10020
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,8 @@
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/io": "^1.1.2", "@actions/io": "^1.1.2",
"@actions/tool-cache": "2.0.1", "@actions/tool-cache": "2.0.1",
"@octokit/auth-action": "^2.0.0", "@octokit/action": "^6.0.7",
"@octokit/graphql": "^4.6.1", "semver": "^7.5.4"
"semver": "^6.1.0"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
@ -23,11 +22,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.34.0", "@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,14 +10,14 @@ 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', () => {
@ -30,8 +30,8 @@ describe('run.ts', () => {
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe( expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmLinuxUrl helmLinuxUrl
) )
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
expect(os.arch).toBeCalled() expect(os.arch).toHaveBeenCalled()
// arm64 // arm64
jest.spyOn(os, 'type').mockReturnValue('Linux') jest.spyOn(os, 'type').mockReturnValue('Linux')
@ -41,8 +41,8 @@ describe('run.ts', () => {
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe( expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmLinuxArm64Url helmLinuxArm64Url
) )
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
expect(os.arch).toBeCalled() expect(os.arch).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => { test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => {
@ -55,8 +55,8 @@ describe('run.ts', () => {
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe( expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmDarwinUrl helmDarwinUrl
) )
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
expect(os.arch).toBeCalled() expect(os.arch).toHaveBeenCalled()
// arm64 // arm64
jest.spyOn(os, 'type').mockReturnValue('Darwin') jest.spyOn(os, 'type').mockReturnValue('Darwin')
@ -66,8 +66,8 @@ describe('run.ts', () => {
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe( expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmDarwinArm64Url helmDarwinArm64Url
) )
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
expect(os.arch).toBeCalled() expect(os.arch).toHaveBeenCalled()
}) })
test('getValidVersion() - return version with v prepended', () => { test('getValidVersion() - return version with v prepended', () => {
@ -83,11 +83,11 @@ describe('run.ts', () => {
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe( expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
helmWindowsUrl helmWindowsUrl
) )
expect(os.type).toBeCalled() expect(os.type).toHaveBeenCalled()
}) })
test('getLatestHelmVersion() - return the stable version of HELM since its not authenticated', async () => { 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', () => { test('walkSync() - return path to the all files matching fileToFind in dir', () => {
@ -120,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', () => {
@ -152,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', () => {
@ -212,13 +212,13 @@ describe('run.ts', () => {
expect(await run.downloadHelm(baseURL, 'v4.0.0')).toBe( 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://test.tld/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'
) )
@ -236,8 +236,8 @@ describe('run.ts', () => {
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow( 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' '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://test.tld/helm-v3.2.1-windows-amd64.zip' 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
) )
}) })
@ -251,8 +251,8 @@ describe('run.ts', () => {
expect(await run.downloadHelm(baseURL, 'v3.2.1')).toBe( 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'
) )
@ -279,11 +279,11 @@ describe('run.ts', () => {
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow( 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://test.tld/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,11 +9,10 @@ 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 {graphql} from '@octokit/graphql' import {Octokit} from '@octokit/action'
import {createActionAuth} from '@octokit/auth-action'
const helmToolName = 'helm' const helmToolName = 'helm'
const stableHelmVersion = 'v3.11.1' const stableHelmVersion = 'v3.13.3'
export async function run() { export async function run() {
let version = core.getInput('version', {required: true}) let version = core.getInput('version', {required: true})
@ -52,30 +51,20 @@ export function getValidVersion(version: string): string {
// Gets the latest helm version or returns a default stable if getting latest fails // Gets the latest helm version or returns a default stable if getting latest fails
export async function getLatestHelmVersion(): Promise<string> { export async function getLatestHelmVersion(): Promise<string> {
try { try {
const auth = createActionAuth() const octokit = new Octokit()
const graphqlAuthenticated = graphql.defaults({ const response = await octokit.rest.repos.listReleases({
request: {hook: auth.hook} owner: 'helm',
repo: 'helm',
per_page: 100,
order: 'desc',
sort: 'created'
}) })
const {repository} = await graphqlAuthenticated(
` const releases = response.data
{ const latestValidRelease: string = releases.find(
repository(name: "helm", owner: "helm") { ({tag_name, draft, prerelease}) =>
releases(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) { isValidVersion(tag_name) && !draft && !prerelease
nodes { )?.tag_name
tagName
isLatest
isDraft
isPrerelease
}
}
}
}
`
)
const latestValidRelease: string = repository.releases.nodes.find(
({tagName, isLatest, isDraft, isPreRelease}) =>
isValidVersion(tagName) && isLatest && !isDraft && !isPreRelease
)?.tagName
if (latestValidRelease) return latestValidRelease if (latestValidRelease) return latestValidRelease
} catch (err) { } catch (err) {