Compare commits

..

1 Commits

Author SHA1 Message Date
David Gamero
e3e6f7311c Update CODEOWNERS 2025-07-22 15:17:27 -04:00
15 changed files with 4339 additions and 1801 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@b5d41d4e1d5dceea10e7104786b73624c18a190f #v10.2.0 - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0
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@b5d41d4e1d5dceea10e7104786b73624c18a190f #v10.2.0 - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0
name: Setting PR as idle name: Setting PR as idle
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,22 +7,15 @@ on:
jobs: jobs:
trigger-integration-tests: trigger-integration-tests:
name: Trigger Integration tests name: Trigger Integration tests
strategy: runs-on: ubuntu-latest
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- macos-latest # arm
fail-fast: false
runs-on: ${{ matrix.os }}
env: env:
HELM_3_18_4: 'v3.18.4' HELM_3_8_0: 'v3.8.0'
HELM_3_18_0: 'v3.18.0' HELM_3_7_2: 'v3.7.2'
HELM_NO_V: '3.18.4' HELM_NO_V: '3.5.0'
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: npm install and build - name: npm install and build
id: action-npm-build id: action-npm-build
run: | run: |
@@ -34,41 +27,41 @@ jobs:
- name: Setup helm - name: Setup helm
uses: ./ uses: ./
with: with:
version: ${{ env.HELM_3_18_4 }} version: ${{ env.HELM_3_8_0 }}
- name: Validate helm 3.18.4 - name: Validate helm 3.8.0
run: | run: |
if [[ $(helm version) != *$HELM_3_18_4* ]]; then if [[ $(helm version) != *$HELM_3_8_0* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.18.4" echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.8.0"
echo "HELM VERSION OUTPUT: $(helm version)" echo "HELM VERSION OUTPUT: $(helm version)"
exit 1 exit 1
else else
echo "HELM VERSION $HELM_3_18_4 INSTALLED SUCCESSFULLY" echo "HELM VERSION $HELM_3_8_0 INSTALLED SUCCESSFULLY"
fi fi
- name: Setup helm 3.18.0 - name: Setup helm 3.7.2
uses: ./ uses: ./
with: with:
version: ${{ env.HELM_3_18_0 }} version: ${{ env.HELM_3_7_2 }}
- name: Validate 3.18.0 - name: Validate 3.7.2
run: | run: |
if [[ $(helm version) != *$HELM_3_18_0* ]]; then if [[ $(helm version) != *$HELM_3_7_2* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.18.0" echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.7.2"
echo "HELM VERSION OUTPUT: $(helm version)" echo "HELM VERSION OUTPUT: $(helm version)"
exit 1 exit 1
else else
echo "HELM VERSION $HELM_3_18_0 INSTALLED SUCCESSFULLY" echo "HELM VERSION $HELM_3_7_2 INSTALLED SUCCESSFULLY"
fi fi
- name: Setup helm 3.18.4 with no v in version - name: Setup helm 3.5.0 with no v in version
uses: ./ uses: ./
with: with:
version: ${{ env.HELM_NO_V }} version: ${{ env.HELM_NO_V }}
- name: Validate 3.18.4 without v in version - name: Validate 3.5.0 without v in version
run: | run: |
if [[ $(helm version) != *$HELM_NO_V* ]]; then if [[ $(helm version) != *$HELM_NO_V* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN 3.18.4" echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.5.0"
echo "HELM VERSION OUTPUT: $(helm version)" echo "HELM VERSION OUTPUT: $(helm version)"
exit 1 exit 1
else else
echo "HELM VERSION $HELM_NO_V INSTALLED SUCCESSFULLY" echo "HELM VERSION $HELM_3_5_0 INSTALLED SUCCESSFULLY"
fi fi
- name: Setup helm latest version - name: Setup helm latest version
uses: ./ uses: ./
@@ -79,7 +72,11 @@ jobs:
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
HELM_LATEST=$(curl -s https://get.helm.sh/helm-latest-version) HELM_LATEST=$(gh release list \
--repo helm/helm \
--exclude-drafts \
--exclude-pre-releases \
--limit 1 | awk '{print $4}')
if [[ $(helm version) != *$HELM_LATEST* ]]; then if [[ $(helm version) != *$HELM_LATEST* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN $HELM_LATEST" echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN $HELM_LATEST"

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Enforce Prettier - name: Enforce Prettier
run: npx prettier --check . run: npx prettier --check .

View File

@@ -11,18 +11,9 @@ on: # rebuild any PRs and main branch changes
jobs: jobs:
build: # make sure build/ci works properly build: # make sure build/ci works properly
strategy: runs-on: ubuntu-latest
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- windows-latest
- windows-11-arm
- macos-latest # arm
fail-fast: false
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run L0 tests. - name: Run L0 tests.
run: | run: |

View File

@@ -1,46 +1,5 @@
# Change Log # Change Log
## [5.0.0] - 2026-03-23
### Changed
- #259 [Update Node.js runtime from node20 to node24](https://github.com/Azure/setup-helm/pull/259)
- #263 [Bump undici](https://github.com/Azure/setup-helm/pull/263)
- #257 [Bump undici and @actions/http-client](https://github.com/Azure/setup-helm/pull/257)
- #256 [Bump minimatch](https://github.com/Azure/setup-helm/pull/256)
- #248 [Bump the actions group with 2 updates](https://github.com/Azure/setup-helm/pull/248)
- #247 [Bump the actions group with 3 updates](https://github.com/Azure/setup-helm/pull/247)
- #246 [Bump @types/node from 25.0.2 to 25.0.3 in the actions group](https://github.com/Azure/setup-helm/pull/246)
- #245 [Bump the actions group with 3 updates](https://github.com/Azure/setup-helm/pull/245)
- #243 [Bump the actions group with 2 updates](https://github.com/Azure/setup-helm/pull/243)
- #240 [Bump prettier from 3.6.2 to 3.7.3 in the actions group](https://github.com/Azure/setup-helm/pull/240)
- #229 [Bump the actions group across 1 directory with 3 updates](https://github.com/Azure/setup-helm/pull/229)
- #231 [Bump js-yaml from 3.14.1 to 3.14.2](https://github.com/Azure/setup-helm/pull/231)
- #234 [Bump glob from 10.4.5 to 10.5.0](https://github.com/Azure/setup-helm/pull/234)
- #225 [Fix build error](https://github.com/Azure/setup-helm/pull/225)
- #222 [Bump @types/node from 24.7.2 to 24.8.1 in the actions group](https://github.com/Azure/setup-helm/pull/222)
- #220 [Bump the actions group across 1 directory with 4 updates](https://github.com/Azure/setup-helm/pull/220)
- #216 [Bump the actions group across 1 directory with 4 updates](https://github.com/Azure/setup-helm/pull/216)
- #213 [Bump the actions group with 2 updates](https://github.com/Azure/setup-helm/pull/213)
- #211 [Bump undici](https://github.com/Azure/setup-helm/pull/211)
- #212 [Bump jest from 30.0.5 to 30.1.2 in the actions group](https://github.com/Azure/setup-helm/pull/212)
- #210 [Bump @types/node from 24.2.1 to 24.3.0 in the actions group](https://github.com/Azure/setup-helm/pull/210)
## [4.3.1] - 2025-08-12
### Changed
- #167 [Pinning Action Dependencies for Security and Reliability](https://github.com/Azure/setup-helm/pull/167)
- #181 [Fix types, and update node version.](https://github.com/Azure/setup-helm/pull/181)
- #191 [chore(tests): Mock arch to make tests pass on arm host](https://github.com/Azure/setup-helm/pull/191)
- #192 [chore: remove unnecessary prebuild script](https://github.com/Azure/setup-helm/pull/192)
- #203 [Update helm version retrieval to use JSON output for latest version](https://github.com/Azure/setup-helm/pull/203)
- #207 [ci(workflows): update helm version to v3.18.4 and add matrix for tests](https://github.com/Azure/setup-helm/pull/207)
### Added
- #197 [Add pre-commit hook](https://github.com/Azure/setup-helm/pull/197)
## [4.3.0] - 2025-02-15 ## [4.3.0] - 2025-02-15
- #152 feat: log when restoring from cache - #152 feat: log when restoring from cache

View File

@@ -7,14 +7,14 @@ 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@v5.0.0 - uses: azure/setup-helm@v4.3.0
with: with:
version: '<version>' # default is latest (stable) version: '<version>' # default is latest (stable)
id: install id: install
``` ```
> [!NOTE] > [!NOTE]
> If something goes wrong with fetching the latest version the action will use the hardcoded default version (currently v3.18.3). If you rely on a certain version higher than the default, you should explicitly use that version instead of latest. > 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. 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

@@ -20,5 +20,5 @@ outputs:
branding: branding:
color: 'blue' color: 'blue'
runs: runs:
using: 'node24' using: 'node20'
main: 'lib/index.js' main: 'lib/index.js'

18
jest.config.js Normal file
View File

@@ -0,0 +1,18 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true,
coverageThreshold: {
global: {
branches: 0,
functions: 14,
lines: 27,
statements: 27
}
}
}

5640
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,36 @@
{ {
"name": "setuphelm", "name": "setuphelm",
"version": "5.0.0", "version": "4.3.0",
"private": true, "private": true,
"description": "Setup helm", "description": "Setup helm",
"author": "Anumita Shenoy", "author": "Anumita Shenoy",
"license": "MIT", "license": "MIT",
"type": "module",
"dependencies": { "dependencies": {
"@actions/core": "^3.0.0", "@actions/core": "^1.11.1",
"@actions/exec": "^3.0.0", "@actions/exec": "^1.1.1",
"@actions/io": "^3.0.2", "@actions/io": "^1.1.2",
"@actions/tool-cache": "4.0.0", "@actions/tool-cache": "2.0.2",
"@octokit/action": "^8.0.4", "@octokit/action": "^8.0.2",
"semver": "^7.7.4" "semver": "^7.7.2"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
"build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --target=node20 --format=esm --outfile=lib/index.js --banner:js=\"import { createRequire } from 'module';const require = createRequire(import.meta.url);\"", "prebuild": "npm i ncc",
"typecheck": "tsc --noEmit", "build": "ncc build src/index.ts -o lib",
"test": "vitest run", "test": "jest",
"test-coverage": "vitest run --coverage", "test-coverage": "jest --coverage",
"format": "prettier --write .", "format": "prettier --write .",
"format-check": "prettier --check .", "format-check": "prettier --check .",
"prepare": "husky" "prepare": "husky"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^25.5.2", "@types/jest": "^30.0.0",
"esbuild": "^0.28", "@types/node": "^24.0.13",
"@vercel/ncc": "^0.38.3",
"husky": "^9.1.7", "husky": "^9.1.7",
"prettier": "^3.8.1", "jest": "^30.0.4",
"typescript": "^6.0.2", "prettier": "^3.6.2",
"vitest": "^4" "ts-jest": "^29.4.0",
"typescript": "^5.8.3"
} }
} }

View File

@@ -1,4 +1,4 @@
import {run} from './run.js' import {run} from './run'
import * as core from '@actions/core' import * as core from '@actions/core'
run().catch(core.setFailed) run().catch(core.setFailed)

View File

@@ -1,62 +1,8 @@
import {vi, describe, test, expect, afterEach} from 'vitest' import * as run from './run'
import * as path from 'path'
// Mock os module
vi.mock('os', async (importOriginal) => {
const actual = await importOriginal<typeof import('os')>()
return {
...actual,
platform: vi.fn(),
arch: vi.fn()
}
})
// Mock fs module
vi.mock('fs', async (importOriginal) => {
const actual = await importOriginal<typeof import('fs')>()
return {
...actual,
readdirSync: vi.fn(),
statSync: vi.fn(),
chmodSync: vi.fn(),
readFileSync: vi.fn()
}
})
// Mock @actions/core
vi.mock('@actions/core', async (importOriginal) => {
const actual = await importOriginal<typeof import('@actions/core')>()
return {
...actual,
getInput: vi.fn(),
info: vi.fn(),
debug: vi.fn(),
warning: vi.fn(),
startGroup: vi.fn(),
endGroup: vi.fn(),
addPath: vi.fn(),
setOutput: vi.fn(),
setFailed: vi.fn()
}
})
// Mock @actions/tool-cache
vi.mock('@actions/tool-cache', async (importOriginal) => {
const actual = await importOriginal<typeof import('@actions/tool-cache')>()
return {
...actual,
find: vi.fn(),
downloadTool: vi.fn(),
extractZip: vi.fn(),
extractTar: vi.fn(),
cacheDir: vi.fn()
}
})
import * as run from './run.js'
import * as os from 'os' import * as os from 'os'
import * as toolCache from '@actions/tool-cache' import * as toolCache from '@actions/tool-cache'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path'
import * as core from '@actions/core' import * as core from '@actions/core'
describe('run.ts', () => { describe('run.ts', () => {
@@ -64,26 +10,26 @@ describe('run.ts', () => {
// Cleanup mocks after each test to ensure that subsequent tests are not affected by the mocks. // Cleanup mocks after each test to ensure that subsequent tests are not affected by the mocks.
afterEach(() => { afterEach(() => {
vi.restoreAllMocks() jest.restoreAllMocks()
}) })
test('getExecutableExtension() - return .exe when os is Windows', () => { test('getExecutableExtension() - return .exe when os is Windows', () => {
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
expect(run.getExecutableExtension()).toBe('.exe') expect(run.getExecutableExtension()).toBe('.exe')
expect(os.platform).toHaveBeenCalled() expect(os.platform).toHaveBeenCalled()
}) })
test('getExecutableExtension() - return empty string for non-windows OS', () => { test('getExecutableExtension() - return empty string for non-windows OS', () => {
vi.mocked(os.platform).mockReturnValue('darwin') jest.spyOn(os, 'platform').mockReturnValue('darwin')
expect(run.getExecutableExtension()).toBe('') expect(run.getExecutableExtension()).toBe('')
expect(os.platform).toHaveBeenCalled() expect(os.platform).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Linux amd64', () => { test('getHelmDownloadURL() - return the URL to download helm for Linux amd64', () => {
vi.mocked(os.platform).mockReturnValue('linux') jest.spyOn(os, 'platform').mockReturnValue('linux')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-linux-amd64.tar.gz' const expected = 'https://test.tld/helm-v3.8.0-linux-amd64.tar.gz'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
@@ -92,8 +38,8 @@ describe('run.ts', () => {
}) })
test('getHelmDownloadURL() - return the URL to download helm for Linux arm64', () => { test('getHelmDownloadURL() - return the URL to download helm for Linux arm64', () => {
vi.mocked(os.platform).mockReturnValue('linux') jest.spyOn(os, 'platform').mockReturnValue('linux')
vi.mocked(os.arch).mockReturnValue('arm64') jest.spyOn(os, 'arch').mockReturnValue('arm64')
const expected = 'https://test.tld/helm-v3.8.0-linux-arm64.tar.gz' const expected = 'https://test.tld/helm-v3.8.0-linux-arm64.tar.gz'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
@@ -102,8 +48,8 @@ describe('run.ts', () => {
}) })
test('getHelmDownloadURL() - return the URL to download helm for Darwin x64', () => { test('getHelmDownloadURL() - return the URL to download helm for Darwin x64', () => {
vi.mocked(os.platform).mockReturnValue('darwin') jest.spyOn(os, 'platform').mockReturnValue('darwin')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-darwin-amd64.tar.gz' const expected = 'https://test.tld/helm-v3.8.0-darwin-amd64.tar.gz'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
@@ -112,8 +58,8 @@ describe('run.ts', () => {
}) })
test('getHelmDownloadURL() - return the URL to download helm for Darwin arm64', () => { test('getHelmDownloadURL() - return the URL to download helm for Darwin arm64', () => {
vi.mocked(os.platform).mockReturnValue('darwin') jest.spyOn(os, 'platform').mockReturnValue('darwin')
vi.mocked(os.arch).mockReturnValue('arm64') jest.spyOn(os, 'arch').mockReturnValue('arm64')
const expected = 'https://test.tld/helm-v3.8.0-darwin-arm64.tar.gz' const expected = 'https://test.tld/helm-v3.8.0-darwin-arm64.tar.gz'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
@@ -121,40 +67,28 @@ describe('run.ts', () => {
expect(os.arch).toHaveBeenCalled() expect(os.arch).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Windows x64', () => { test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-windows-amd64.zip' const expected = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected) expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
expect(os.platform).toHaveBeenCalled() expect(os.platform).toHaveBeenCalled()
}) })
test('getHelmDownloadURL() - return the URL to download helm for Windows arm64', () => {
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('arm64')
const expected = 'https://test.tld/helm-v3.8.0-windows-arm64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
expect(os.platform).toHaveBeenCalled()
})
test('getLatestHelmVersion() - return the latest version of HELM', async () => { test('getLatestHelmVersion() - return the latest version of HELM', async () => {
const res = { const res = {
status: 200, status: 200,
text: async () => 'v9.99.999' text: async () => 'v9.99.999'
} as Response } as Response
vi.stubGlobal('fetch', vi.fn().mockReturnValue(res)) global.fetch = jest.fn().mockReturnValue(res)
expect(await run.getLatestHelmVersion()).toBe('v9.99.999') expect(await run.getLatestHelmVersion()).toBe('v9.99.999')
}) })
test('getLatestHelmVersion() - return the stable version of HELM when simulating a network error', async () => { test('getLatestHelmVersion() - return the stable version of HELM when simulating a network error', async () => {
const errorMessage: string = 'Network Error' const errorMessage: string = 'Network Error'
vi.stubGlobal( global.fetch = jest.fn().mockRejectedValueOnce(new Error(errorMessage))
'fetch', expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
vi.fn().mockRejectedValueOnce(new Error(errorMessage))
)
expect(await run.getLatestHelmVersion()).toBe(run.stableHelmVersion)
}) })
test('getValidVersion() - return version with v prepended', () => { test('getValidVersion() - return version with v prepended', () => {
@@ -162,27 +96,28 @@ describe('run.ts', () => {
}) })
test('walkSync() - return path to the all files matching fileToFind in dir', () => { test('walkSync() - return path to the all files matching fileToFind in dir', () => {
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => { jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') if (file == 'mainFolder')
return [ return [
'file1' as unknown as fs.Dirent<NonSharedBuffer>, 'file1' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file2' as unknown as fs.Dirent<NonSharedBuffer>, 'file2' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'folder1' as unknown as fs.Dirent<NonSharedBuffer>, 'folder1' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'folder2' as unknown as fs.Dirent<NonSharedBuffer> 'folder2' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
if (file == path.join('mainFolder', 'folder1')) if (file == path.join('mainFolder', 'folder1'))
return [ return [
'file11' as unknown as fs.Dirent<NonSharedBuffer>, 'file11' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file12' as unknown as fs.Dirent<NonSharedBuffer> 'file12' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
if (file == path.join('mainFolder', 'folder2')) if (file == path.join('mainFolder', 'folder2'))
return [ return [
'file21' as unknown as fs.Dirent<NonSharedBuffer>, 'file21' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file22' as unknown as fs.Dirent<NonSharedBuffer> 'file22' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
return [] return []
}) })
vi.mocked(fs.statSync).mockImplementation((file) => { jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false (file as string).toLowerCase().indexOf('file') == -1 ? true : false
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
@@ -196,27 +131,28 @@ describe('run.ts', () => {
}) })
test('walkSync() - return empty array if no file with name fileToFind exists', () => { test('walkSync() - return empty array if no file with name fileToFind exists', () => {
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => { jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') if (file == 'mainFolder')
return [ return [
'file1' as unknown as fs.Dirent<NonSharedBuffer>, 'file1' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file2' as unknown as fs.Dirent<NonSharedBuffer>, 'file2' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'folder1' as unknown as fs.Dirent<NonSharedBuffer>, 'folder1' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'folder2' as unknown as fs.Dirent<NonSharedBuffer> 'folder2' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
if (file == path.join('mainFolder', 'folder1')) if (file == path.join('mainFolder', 'folder1'))
return [ return [
'file11' as unknown as fs.Dirent<NonSharedBuffer>, 'file11' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file12' as unknown as fs.Dirent<NonSharedBuffer> 'file12' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
if (file == path.join('mainFolder', 'folder2')) if (file == path.join('mainFolder', 'folder2'))
return [ return [
'file21' as unknown as fs.Dirent<NonSharedBuffer>, 'file21' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>,
'file22' as unknown as fs.Dirent<NonSharedBuffer> 'file22' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
] ]
return [] return []
}) })
vi.mocked(fs.statSync).mockImplementation((file) => { jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false (file as string).toLowerCase().indexOf('file') == -1 ? true : false
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
@@ -228,18 +164,18 @@ describe('run.ts', () => {
}) })
test('findHelm() - change access permissions and find the helm in given directory', () => { test('findHelm() - change access permissions and find the helm in given directory', () => {
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => { jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') if (file == 'mainFolder')
return ['helm.exe' as unknown as fs.Dirent<NonSharedBuffer>] return ['helm.exe' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>]
return [] return []
}) })
vi.mocked(fs.statSync).mockImplementation((file) => { jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true (file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
}) })
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
expect(run.findHelm('mainFolder')).toBe( expect(run.findHelm('mainFolder')).toBe(
path.join('mainFolder', 'helm.exe') path.join('mainFolder', 'helm.exe')
@@ -247,15 +183,15 @@ describe('run.ts', () => {
}) })
test('findHelm() - throw error if executable not found', () => { test('findHelm() - throw error if executable not found', () => {
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => { jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') return [] if (file == 'mainFolder') return []
return [] return []
}) })
vi.mocked(fs.statSync).mockImplementation((file) => { jest.spyOn(fs, 'statSync').mockImplementation((file) => {
return {isDirectory: () => true} as fs.Stats return {isDirectory: () => true} as fs.Stats
}) })
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
expect(() => run.findHelm('mainFolder')).toThrow( expect(() => run.findHelm('mainFolder')).toThrow(
'Helm executable not found in path mainFolder' 'Helm executable not found in path mainFolder'
@@ -263,19 +199,20 @@ describe('run.ts', () => {
}) })
test('downloadHelm() - download helm and return path to it', async () => { test('downloadHelm() - download helm and return path to it', async () => {
vi.mocked(toolCache.find).mockReturnValue('') jest.spyOn(toolCache, 'find').mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool') jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify([{tag_name: 'v4.0.0'}]) const response = JSON.stringify([{tag_name: 'v4.0.0'}])
vi.mocked(fs.readFileSync).mockReturnValue(response) jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath') jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir') jest
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => [ .spyOn(fs, 'readdirSync')
'helm.exe' as unknown as fs.Dirent<NonSharedBuffer> .mockImplementation((file, _) => [
]) 'helm.exe' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
vi.mocked(fs.statSync).mockImplementation((file) => { ])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true (file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
@@ -297,12 +234,11 @@ describe('run.ts', () => {
}) })
test('downloadHelm() - throw error if unable to download', async () => { test('downloadHelm() - throw error if unable to download', async () => {
vi.mocked(toolCache.find).mockReturnValue('') jest.spyOn(toolCache, 'find').mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockImplementation(async () => { jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Unable to download' throw 'Unable to download'
}) })
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
vi.mocked(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(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
@@ -313,17 +249,18 @@ describe('run.ts', () => {
}) })
test('downloadHelm() - return path to helm tool with same version from toolCache', async () => { test('downloadHelm() - return path to helm tool with same version from toolCache', async () => {
vi.mocked(toolCache.find).mockReturnValue('pathToCachedDir') jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir') jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool') jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath') jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest
vi.mocked(fs.readdirSync).mockReturnValue([ .spyOn(fs, 'readdirSync')
'helm.exe' as unknown as fs.Dirent<NonSharedBuffer> .mockReturnValue([
]) 'helm.exe' as unknown as fs.Dirent<Buffer<ArrayBufferLike>>
vi.mocked(fs.statSync).mockImplementation((file) => { ])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true (file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats
@@ -340,16 +277,15 @@ describe('run.ts', () => {
}) })
test('downloadHelm() - throw error is helm is not found in path', async () => { test('downloadHelm() - throw error is helm is not found in path', async () => {
vi.mocked(toolCache.find).mockReturnValue('') jest.spyOn(toolCache, 'find').mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool') jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir') jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool') jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath') jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
vi.mocked(os.platform).mockReturnValue('win32') jest.spyOn(os, 'platform').mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64') jest.spyOn(fs, 'chmodSync').mockImplementation()
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => []) jest.spyOn(fs, 'statSync').mockImplementation((file) => {
vi.mocked(fs.statSync).mockImplementation((file) => {
const isDirectory = const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true (file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats return {isDirectory: () => isDirectory} as fs.Stats

View File

@@ -10,7 +10,7 @@ import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core' import * as core from '@actions/core'
const helmToolName = 'helm' const helmToolName = 'helm'
export const stableHelmVersion = 'v3.18.4' 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})
@@ -131,7 +131,7 @@ export async function downloadHelm(
export function findHelm(rootFolder: string): string { export function findHelm(rootFolder: string): string {
fs.chmodSync(rootFolder, '777') fs.chmodSync(rootFolder, '777')
let filelist: string[] = [] var filelist: string[] = []
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension()) walkSync(rootFolder, filelist, helmToolName + getExecutableExtension())
if (!filelist || filelist.length == 0) { if (!filelist || filelist.length == 0) {
throw new Error( throw new Error(
@@ -142,8 +142,8 @@ export function findHelm(rootFolder: string): string {
} }
} }
export function walkSync(dir, filelist, fileToFind) { export var walkSync = function (dir, filelist, fileToFind) {
const files = fs.readdirSync(dir) var files = fs.readdirSync(dir)
filelist = filelist || [] filelist = filelist || []
files.forEach(function (file) { files.forEach(function (file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) { if (fs.statSync(path.join(dir, file)).isDirectory()) {

View File

@@ -1,14 +1,64 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2020", /* Basic Options */
"module": "NodeNext", // "incremental": true, /* Enable incremental compilation */
"moduleResolution": "NodeNext", "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"rootDir": "./src", "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"outDir": "./lib", // "allowJs": true, /* Allow javascript files to be compiled. */
"noImplicitAny": false, // "checkJs": true, /* Report errors in .js files. */
"skipLibCheck": true, // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
"noEmit": true, // "declaration": true, /* Generates corresponding '.d.ts' file. */
"types": ["node", "vitest/globals"] // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib" /* Redirect output structure to the directory. */,
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
//"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
"skipLibCheck": true
}, },
"exclude": ["node_modules", "**/*.test.ts", "vitest.config.ts"] "exclude": ["node_modules", "**/*.test.ts"]
} }

View File

@@ -1,10 +0,0 @@
import {defineConfig} from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['**/*.test.ts'],
clearMocks: true
}
})