Compare commits

..

3 Commits

Author SHA1 Message Date
David Gamero
812d38ec42 Update README.md 2024-04-15 13:23:57 -04:00
David Gamero
4ebd10de59 Update package.json 2024-04-15 13:23:17 -04:00
David Gamero
8808eff8a7 Update CHANGELOG.md 2024-04-15 13:22:13 -04:00
22 changed files with 3886 additions and 2125 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1 +1 @@
* @Azure/cloud-native-github-action-owners
* @Azure/aks-atlanta

View File

@@ -1,18 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
groups:
actions:
patterns:
- '*'
- package-ecosystem: github-actions
directory: .github/workflows
schedule:
interval: weekly
groups:
actions:
patterns:
- '*'

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@b5d41d4e1d5dceea10e7104786b73624c18a190f #v10.2.0
- 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@b5d41d4e1d5dceea10e7104786b73624c18a190f #v10.2.0
- uses: actions/stale@v9
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,22 +7,15 @@ on:
jobs:
trigger-integration-tests:
name: Trigger Integration tests
strategy:
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- macos-latest # arm
fail-fast: false
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
env:
HELM_3_18_4: 'v3.18.4'
HELM_3_18_0: 'v3.18.0'
HELM_NO_V: '3.18.4'
HELM_3_8_0: 'v3.8.0'
HELM_3_7_2: 'v3.7.2'
HELM_NO_V: '3.5.0'
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v4
- name: npm install and build
id: action-npm-build
run: |
@@ -34,41 +27,41 @@ jobs:
- name: Setup helm
uses: ./
with:
version: ${{ env.HELM_3_18_4 }}
- name: Validate helm 3.18.4
version: ${{ env.HELM_3_8_0 }}
- name: Validate helm 3.8.0
run: |
if [[ $(helm version) != *$HELM_3_18_4* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.18.4"
if [[ $(helm version) != *$HELM_3_8_0* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.8.0"
echo "HELM VERSION OUTPUT: $(helm version)"
exit 1
else
echo "HELM VERSION $HELM_3_18_4 INSTALLED SUCCESSFULLY"
echo "HELM VERSION $HELM_3_8_0 INSTALLED SUCCESSFULLY"
fi
- name: Setup helm 3.18.0
- name: Setup helm 3.7.2
uses: ./
with:
version: ${{ env.HELM_3_18_0 }}
- name: Validate 3.18.0
version: ${{ env.HELM_3_7_2 }}
- name: Validate 3.7.2
run: |
if [[ $(helm version) != *$HELM_3_18_0* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.18.0"
if [[ $(helm version) != *$HELM_3_7_2* ]]; then
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN v3.7.2"
echo "HELM VERSION OUTPUT: $(helm version)"
exit 1
else
echo "HELM VERSION $HELM_3_18_0 INSTALLED SUCCESSFULLY"
echo "HELM VERSION $HELM_3_7_2 INSTALLED SUCCESSFULLY"
fi
- name: Setup helm 3.18.4 with no v in version
- name: Setup helm 3.5.0 with no v in version
uses: ./
with:
version: ${{ env.HELM_NO_V }}
- name: Validate 3.18.4 without v in version
- name: Validate 3.5.0 without v in version
run: |
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)"
exit 1
else
echo "HELM VERSION $HELM_NO_V INSTALLED SUCCESSFULLY"
echo "HELM VERSION $HELM_3_5_0 INSTALLED SUCCESSFULLY"
fi
- name: Setup helm latest version
uses: ./
@@ -79,7 +72,11 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
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
echo "HELM VERSION INCORRECT: HELM VERSION DOES NOT CONTAIN $HELM_LATEST"

View File

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

View File

@@ -13,6 +13,6 @@ jobs:
permissions:
actions: read
contents: write
uses: Azure/action-release-workflows/.github/workflows/release_js_project.yaml@3c677ba5ab58f5c5c1a6f0cfb176b333b1f27405 # v1.0.3
uses: Azure/action-release-workflows/.github/workflows/release_js_project.yaml@v1
with:
changelogPath: ./CHANGELOG.md

View File

@@ -7,4 +7,4 @@ on:
jobs:
tag-and-release:
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@c753e1545b144562237cd1177a95bab21a785cff # main
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main

View File

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

View File

@@ -1,7 +0,0 @@
npm test
npm run format-check || {
echo ""
echo "❌ Formatting check failed."
echo "💡 Run 'npm run format' or 'prettier --write .' to fix formatting issues."
exit 1
}

View File

@@ -1,60 +1,13 @@
# 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
- #152 feat: log when restoring from cache
- #157 Dependencies Update
- #137 Add dependabot
## [4.2.0] - 2024-04-15
- #124 Fix OS detection and download OS-native archive extension
- #124 Fix OS detection and download OS-native archive extension
## [4.1.0] - 2024-03-01
- #130 switches to use Helm published file to read latest version instead of using GitHub releases
- #130 switches to use Helm published file to read latest version instead of using GitHub releases
## [4.0.0] - 2024-02-12
- #121 update to node20 as node16 is deprecated
- #121 update to node20 as node16 is deprecated

View File

@@ -4,6 +4,6 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns

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.
```yaml
- uses: azure/setup-helm@v5.0.0
- uses: azure/setup-helm@v4.2.0
with:
version: '<version>' # default is latest (stable)
id: install
```
> [!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.
Refer to the action metadata file for details about all the inputs https://github.com/Azure/setup-helm/blob/master/action.yml

View File

@@ -18,13 +18,13 @@ You should receive a response within 24 hours. If for some reason you do not, pl
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.

View File

@@ -20,5 +20,5 @@ outputs:
branding:
color: 'blue'
runs:
using: 'node24'
using: 'node20'
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
}
}
}

5431
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,34 @@
{
"name": "setuphelm",
"version": "5.0.0",
"version": "4.2.0",
"private": true,
"description": "Setup helm",
"author": "Anumita Shenoy",
"license": "MIT",
"type": "module",
"dependencies": {
"@actions/core": "^3.0.0",
"@actions/exec": "^3.0.0",
"@actions/io": "^3.0.2",
"@actions/tool-cache": "4.0.0",
"@octokit/action": "^8.0.4",
"semver": "^7.7.4"
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.2",
"@actions/tool-cache": "2.0.1",
"@octokit/action": "^6.0.7",
"semver": "^7.5.4"
},
"main": "lib/index.js",
"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);\"",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test-coverage": "vitest run --coverage",
"prebuild": "npm i ncc",
"build": "ncc build src/run.ts -o lib",
"test": "jest",
"test-coverage": "jest --coverage",
"format": "prettier --write .",
"format-check": "prettier --check .",
"prepare": "husky"
"format-check": "prettier --check ."
},
"devDependencies": {
"@types/node": "^25.5.2",
"esbuild": "^0.28",
"husky": "^9.1.7",
"prettier": "^3.8.1",
"typescript": "^6.0.2",
"vitest": "^4"
"@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

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

View File

@@ -1,62 +1,8 @@
import {vi, describe, test, expect, afterEach} from 'vitest'
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 run from './run'
import * as os from 'os'
import * as toolCache from '@actions/tool-cache'
import * as fs from 'fs'
import * as path from 'path'
import * as core from '@actions/core'
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.
afterEach(() => {
vi.restoreAllMocks()
jest.restoreAllMocks()
})
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(os.platform).toHaveBeenCalled()
})
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(os.platform).toHaveBeenCalled()
})
test('getHelmDownloadURL() - return the URL to download helm for Linux amd64', () => {
vi.mocked(os.platform).mockReturnValue('linux')
vi.mocked(os.arch).mockReturnValue('x64')
jest.spyOn(os, 'platform').mockReturnValue('linux')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-linux-amd64.tar.gz'
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', () => {
vi.mocked(os.platform).mockReturnValue('linux')
vi.mocked(os.arch).mockReturnValue('arm64')
jest.spyOn(os, 'platform').mockReturnValue('linux')
jest.spyOn(os, 'arch').mockReturnValue('arm64')
const expected = 'https://test.tld/helm-v3.8.0-linux-arm64.tar.gz'
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', () => {
vi.mocked(os.platform).mockReturnValue('darwin')
vi.mocked(os.arch).mockReturnValue('x64')
jest.spyOn(os, 'platform').mockReturnValue('darwin')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-darwin-amd64.tar.gz'
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', () => {
vi.mocked(os.platform).mockReturnValue('darwin')
vi.mocked(os.arch).mockReturnValue('arm64')
jest.spyOn(os, 'platform').mockReturnValue('darwin')
jest.spyOn(os, 'arch').mockReturnValue('arm64')
const expected = 'https://test.tld/helm-v3.8.0-darwin-arm64.tar.gz'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
@@ -121,40 +67,28 @@ describe('run.ts', () => {
expect(os.arch).toHaveBeenCalled()
})
test('getHelmDownloadURL() - return the URL to download helm for Windows x64', () => {
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64')
test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
jest.spyOn(os, 'platform').mockReturnValue('win32')
jest.spyOn(os, 'arch').mockReturnValue('x64')
const expected = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
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 () => {
const res = {
status: 200,
text: async () => 'v9.99.999'
} as Response
vi.stubGlobal('fetch', vi.fn().mockReturnValue(res))
global.fetch = jest.fn().mockReturnValue(res)
expect(await run.getLatestHelmVersion()).toBe('v9.99.999')
})
test('getLatestHelmVersion() - return the stable version of HELM when simulating a network error', async () => {
const errorMessage: string = 'Network Error'
vi.stubGlobal(
'fetch',
vi.fn().mockRejectedValueOnce(new Error(errorMessage))
)
expect(await run.getLatestHelmVersion()).toBe(run.stableHelmVersion)
global.fetch = jest.fn().mockRejectedValueOnce(new Error(errorMessage))
expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
})
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', () => {
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder')
return [
'file1' as unknown as fs.Dirent<NonSharedBuffer>,
'file2' as unknown as fs.Dirent<NonSharedBuffer>,
'folder1' as unknown as fs.Dirent<NonSharedBuffer>,
'folder2' as unknown as fs.Dirent<NonSharedBuffer>
'file1' as unknown as fs.Dirent,
'file2' as unknown as fs.Dirent,
'folder1' as unknown as fs.Dirent,
'folder2' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder1'))
return [
'file11' as unknown as fs.Dirent<NonSharedBuffer>,
'file12' as unknown as fs.Dirent<NonSharedBuffer>
'file11' as unknown as fs.Dirent,
'file12' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder2'))
return [
'file21' as unknown as fs.Dirent<NonSharedBuffer>,
'file22' as unknown as fs.Dirent<NonSharedBuffer>
'file21' as unknown as fs.Dirent,
'file22' as unknown as fs.Dirent
]
return []
})
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
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', () => {
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => {
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder')
return [
'file1' as unknown as fs.Dirent<NonSharedBuffer>,
'file2' as unknown as fs.Dirent<NonSharedBuffer>,
'folder1' as unknown as fs.Dirent<NonSharedBuffer>,
'folder2' as unknown as fs.Dirent<NonSharedBuffer>
'file1' as unknown as fs.Dirent,
'file2' as unknown as fs.Dirent,
'folder1' as unknown as fs.Dirent,
'folder2' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder1'))
return [
'file11' as unknown as fs.Dirent<NonSharedBuffer>,
'file12' as unknown as fs.Dirent<NonSharedBuffer>
'file11' as unknown as fs.Dirent,
'file12' as unknown as fs.Dirent
]
if (file == path.join('mainFolder', 'folder2'))
return [
'file21' as unknown as fs.Dirent<NonSharedBuffer>,
'file22' as unknown as fs.Dirent<NonSharedBuffer>
'file21' as unknown as fs.Dirent,
'file22' as unknown as fs.Dirent
]
return []
})
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(core, 'debug').mockImplementation()
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
return {isDirectory: () => isDirectory} as fs.Stats
@@ -228,18 +164,17 @@ describe('run.ts', () => {
})
test('findHelm() - change access permissions and find the helm in given directory', () => {
vi.mocked(fs.chmodSync).mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => {
if (file == 'mainFolder')
return ['helm.exe' as unknown as fs.Dirent<NonSharedBuffer>]
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') return ['helm.exe' as unknown as fs.Dirent]
return []
})
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
})
vi.mocked(os.platform).mockReturnValue('win32')
jest.spyOn(os, 'platform').mockReturnValue('win32')
expect(run.findHelm('mainFolder')).toBe(
path.join('mainFolder', 'helm.exe')
@@ -247,15 +182,15 @@ describe('run.ts', () => {
})
test('findHelm() - throw error if executable not found', () => {
vi.mocked(fs.chmodSync).mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => {
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
if (file == 'mainFolder') return []
return []
})
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
return {isDirectory: () => true} as fs.Stats
})
vi.mocked(os.platform).mockReturnValue('win32')
jest.spyOn(os, 'platform').mockReturnValue('win32')
expect(() => run.findHelm('mainFolder')).toThrow(
'Helm executable not found in path mainFolder'
@@ -263,19 +198,18 @@ describe('run.ts', () => {
})
test('downloadHelm() - download helm and return path to it', async () => {
vi.mocked(toolCache.find).mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
const response = JSON.stringify([{tag_name: 'v4.0.0'}])
vi.mocked(fs.readFileSync).mockReturnValue(response)
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64')
vi.mocked(fs.chmodSync).mockImplementation(() => {})
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir')
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => [
'helm.exe' as unknown as fs.Dirent<NonSharedBuffer>
])
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
jest.spyOn(os, 'platform').mockReturnValue('win32')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest
.spyOn(fs, 'readdirSync')
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
@@ -297,12 +231,11 @@ describe('run.ts', () => {
})
test('downloadHelm() - throw error if unable to download', async () => {
vi.mocked(toolCache.find).mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockImplementation(async () => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
throw 'Unable to download'
})
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64')
jest.spyOn(os, 'platform').mockReturnValue('win32')
const downloadUrl = 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
await expect(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
@@ -313,17 +246,16 @@ describe('run.ts', () => {
})
test('downloadHelm() - return path to helm tool with same version from toolCache', async () => {
vi.mocked(toolCache.find).mockReturnValue('pathToCachedDir')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool')
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath')
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64')
vi.mocked(fs.chmodSync).mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockReturnValue([
'helm.exe' as unknown as fs.Dirent<NonSharedBuffer>
])
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
jest.spyOn(os, 'platform').mockReturnValue('win32')
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest
.spyOn(fs, 'readdirSync')
.mockReturnValue(['helm.exe' as unknown as fs.Dirent])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats
@@ -340,16 +272,15 @@ describe('run.ts', () => {
})
test('downloadHelm() - throw error is helm is not found in path', async () => {
vi.mocked(toolCache.find).mockReturnValue('')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool')
vi.mocked(toolCache.cacheDir).mockResolvedValue('pathToCachedDir')
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool')
vi.mocked(toolCache.extractZip).mockResolvedValue('extractedPath')
vi.mocked(os.platform).mockReturnValue('win32')
vi.mocked(os.arch).mockReturnValue('x64')
vi.mocked(fs.chmodSync).mockImplementation(() => {})
vi.mocked(fs.readdirSync).mockImplementation((file, _?) => [])
vi.mocked(fs.statSync).mockImplementation((file) => {
jest.spyOn(toolCache, 'find').mockReturnValue('')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
jest.spyOn(os, 'platform').mockReturnValue('win32')
jest.spyOn(fs, 'chmodSync').mockImplementation()
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
const isDirectory =
(file as string).indexOf('folder') == -1 ? false : true
return {isDirectory: () => isDirectory} as fs.Stats

View File

@@ -1,4 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as os from 'os'
@@ -10,7 +11,7 @@ import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
const helmToolName = 'helm'
export const stableHelmVersion = 'v3.18.4'
const stableHelmVersion = 'v3.13.3'
export async function run() {
let version = core.getInput('version', {required: true})
@@ -25,7 +26,7 @@ export async function run() {
const downloadBaseURL = core.getInput('downloadBaseURL', {required: false})
core.startGroup(`Installing ${version}`)
core.startGroup(`Downloading ${version}`)
const cachedPath = await downloadHelm(downloadBaseURL, version)
core.endGroup()
@@ -87,10 +88,7 @@ export async function downloadHelm(
version: string
): Promise<string> {
let cachedToolpath = toolCache.find(helmToolName, version)
if (cachedToolpath) {
core.info(`Restoring '${version}' from cache`)
} else {
core.info(`Downloading '${version}' from '${baseURL}'`)
if (!cachedToolpath) {
let helmDownloadPath
try {
helmDownloadPath = await toolCache.downloadTool(
@@ -131,7 +129,7 @@ export async function downloadHelm(
export function findHelm(rootFolder: string): string {
fs.chmodSync(rootFolder, '777')
let filelist: string[] = []
var filelist: string[] = []
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension())
if (!filelist || filelist.length == 0) {
throw new Error(
@@ -142,8 +140,8 @@ export function findHelm(rootFolder: string): string {
}
}
export function walkSync(dir, filelist, fileToFind) {
const files = fs.readdirSync(dir)
export var walkSync = function (dir, filelist, fileToFind) {
var files = fs.readdirSync(dir)
filelist = filelist || []
files.forEach(function (file) {
if (fs.statSync(path.join(dir, file)).isDirectory()) {
@@ -157,3 +155,5 @@ export function walkSync(dir, filelist, fileToFind) {
})
return filelist
}
run().catch(core.setFailed)

View File

@@ -1,14 +1,64 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./lib",
"noImplicitAny": false,
"skipLibCheck": true,
"noEmit": true,
"types": ["node", "vitest/globals"]
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "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
}
})