10 Commits

Author SHA1 Message Date
David Gamero
4d6b1eeaab Update CODEOWNERS 2025-07-22 15:16:09 -04:00
dependabot[bot]
83ce790aa0 Bump github/codeql-action in /.github/workflows in the actions group (#179)
Bumps the actions group in /.github/workflows with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.29.2 to 3.29.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](181d5eefc2...d6bbdef45e)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 15:06:41 -04:00
David Gamero
773fd39d5c upgrade failing deps (#168)
* upgrade failing deps

* test with no bin links

* remove --no-bin-links flag
2025-07-15 15:10:20 -04:00
dependabot[bot]
0fec332675 Bump @types/node from 24.0.10 to 24.0.13 in the actions group (#177)
Bumps the actions group with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `@types/node` from 24.0.10 to 24.0.13
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-15 15:06:55 -04:00
Ogheneobukome Ejaife
7500adf963 Resolve #104 : Enhance Version Handling: Auto-Resolve kubectl Major.Minor to Latest Patch (#172)
* feat: Implement resolveKubectlVersion function with comprehensive test coverage

Introduce resolveKubectlVersion function that enables automatic selection of the latest patch version when provided with major.minor version input (e.g., '1.27' resolves to 'v1.27.15')

Test Coverage:
- Major.minor version expansion to latest available patch
- Full version passthrough behavior (returns unchanged)
- Single matching version selection logic
- Comprehensive unit tests for kubectl version resolution scenarios

* chore: fix Prettier formatting

* refactor(resolveKubectlVersion): switch to k8s CDN for security patch retrieval

Replaced GitHub API Octo client with k8s CDN to fetch the latest security patch for improved reliability. Separated the API call logic from resolveKubectlVersion to enhance testability and readability.

* feat: validate semantic version and refactor patch logic

- Added validation to `resolveKubectlVersion` to ensure input follows "major.minor" or "major.minor.patch" format.
- Moved `getLatestPatchVersion` from `run.ts` to `helpers.ts` to improve code organization and ensure a more robust testing process.

* Bump github/codeql-action in /.github/workflows in the actions group (#173)

Bumps the actions group in /.github/workflows with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.29.0 to 3.29.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ce28f5bb42...39edc492db)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: fix code style issues with Prettier

* revised parsing logic

* Improved readability and maintainability

* regenerated package-lock.json

* Regenerated Package-lock.json

* removed unnecessary files

* regenerated package-lock.json

* Regenerate package-lock.json to match package.json version ranges

* Restore package-lock.json to previous version

* uninstall ncc and regenerate package-lock.json using npm ci

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 15:31:20 -06:00
dependabot[bot]
41a1936057 Bump github/codeql-action in /.github/workflows in the actions group (#175)
Bumps the actions group in /.github/workflows with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.29.1 to 3.29.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](39edc492db...181d5eefc2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 15:07:39 -04:00
dependabot[bot]
f2e9242c07 Bump the actions group with 2 updates (#176)
Bumps the actions group with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest).


Updates `@types/node` from 24.0.7 to 24.0.10
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `jest` from 30.0.3 to 30.0.4
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.0.4/packages/jest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: jest
  dependency-version: 30.0.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 15:06:34 -04:00
Tatsinnit
00ca972929 Add husky precommit check in the repo. (#171)
Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
2025-07-03 10:55:16 +12:00
dependabot[bot]
ff4789395b Bump the actions group across 1 directory with 3 updates (#174)
Bumps the actions group with 3 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [prettier](https://github.com/prettier/prettier).


Updates `@types/node` from 24.0.3 to 24.0.7
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `jest` from 30.0.0 to 30.0.3
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.0.3/packages/jest)

Updates `prettier` from 3.5.3 to 3.6.2
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.3...3.6.2)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: jest
  dependency-version: 30.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: prettier
  dependency-version: 3.6.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 15:16:40 -04:00
dependabot[bot]
71c4c470b9 Bump github/codeql-action in /.github/workflows in the actions group (#173)
Bumps the actions group in /.github/workflows with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.29.0 to 3.29.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ce28f5bb42...39edc492db)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 15:16:16 -04:00
10 changed files with 1047 additions and 1116 deletions

2
.github/CODEOWNERS vendored
View File

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

View File

@@ -59,7 +59,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
uses: github/codeql-action/init@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -86,6 +86,6 @@ jobs:
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
uses: github/codeql-action/analyze@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3
with:
category: '/language:${{matrix.language}}'

View File

@@ -27,6 +27,8 @@ jobs:
if [[ $PR_BASE_REF != releases/* ]]; then
npm install
npm run build
# remove node_modules to match production environment where only index.js is present
rm -rf node_modules
fi
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

9
.husky/pre-commit Normal file
View File

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

2013
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,8 @@
"test": "jest",
"test-coverage": "jest --coverage",
"format": "prettier --write .",
"format-check": "prettier --check ."
"format-check": "prettier --check .",
"prepare": "husky"
},
"keywords": [
"actions",
@@ -24,10 +25,11 @@
},
"devDependencies": {
"@types/jest": "^30.0.0",
"@types/node": "^24.0.2",
"@types/node": "^24.0.13",
"@vercel/ncc": "^0.38.3",
"jest": "^30.0.0",
"prettier": "3.5.3",
"husky": "^9.1.7",
"jest": "^30.0.4",
"prettier": "3.6.2",
"ts-jest": "^29.4.0",
"typescript": "5.8.3"
}

View File

@@ -1,6 +1,8 @@
import * as os from 'os'
import * as util from 'util'
import * as fs from 'fs'
import * as core from '@actions/core'
import * as toolCache from '@actions/tool-cache'
export function getKubectlArch(): string {
const arch = os.arch()
if (arch === 'x64') {
@@ -23,6 +25,29 @@ export function getkubectlDownloadURL(version: string, arch: string): string {
}
}
export async function getLatestPatchVersion(
major: string,
minor: string
): Promise<string> {
const version = `${major}.${minor}`
const sourceURL = `https://cdn.dl.k8s.io/release/stable-${version}.txt`
try {
const downloadPath = await toolCache.downloadTool(sourceURL)
const latestPatch = fs
.readFileSync(downloadPath, 'utf8')
.toString()
.trim()
if (!latestPatch) {
throw new Error(`No patch version found for ${version}`)
}
return latestPatch
} catch (error) {
core.debug(error)
core.warning('GetLatestPatchVersionFailed')
throw new Error(`Failed to get latest patch version for ${version}`)
}
}
export function getExecutableExtension(): string {
if (os.type().match(/^Win/)) {
return '.exe'

View File

@@ -2,7 +2,8 @@ import * as run from './run'
import {
getkubectlDownloadURL,
getKubectlArch,
getExecutableExtension
getExecutableExtension,
getLatestPatchVersion
} from './helpers'
import * as os from 'os'
import * as toolCache from '@actions/tool-cache'
@@ -12,6 +13,9 @@ import * as core from '@actions/core'
import * as util from 'util'
describe('Testing all functions in run file.', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('getExecutableExtension() - return .exe when os is Windows', () => {
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
expect(getExecutableExtension()).toBe('.exe')
@@ -164,6 +168,59 @@ describe('Testing all functions in run file.', () => {
)
expect(toolCache.downloadTool).not.toHaveBeenCalled()
})
test('getLatestPatchVersion() - download and return latest patch version', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.27.15')
const result = await getLatestPatchVersion('1', '27')
expect(result).toBe('v1.27.15')
expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://cdn.dl.k8s.io/release/stable-1.27.txt'
)
})
test('getLatestPatchVersion() - throw error when patch version is empty', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('')
await expect(getLatestPatchVersion('1', '27')).rejects.toThrow(
'Failed to get latest patch version for 1.27'
)
})
test('getLatestPatchVersion() - throw error when download fails', async () => {
jest
.spyOn(toolCache, 'downloadTool')
.mockRejectedValue(new Error('Network error'))
await expect(getLatestPatchVersion('1', '27')).rejects.toThrow(
'Failed to get latest patch version for 1.27'
)
})
test('resolveKubectlVersion() - expands major.minor to latest patch', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.27.15')
const result = await run.resolveKubectlVersion('1.27')
expect(result).toBe('v1.27.15')
})
test('resolveKubectlVersion() - returns full version unchanged', async () => {
const result = await run.resolveKubectlVersion('v1.27.15')
expect(result).toBe('v1.27.15')
})
test('resolveKubectlVersion() - adds v prefix to full version', async () => {
const result = await run.resolveKubectlVersion('1.27.15')
expect(result).toBe('v1.27.15')
})
test('resolveKubectlVersion() - expands v-prefixed major.minor to latest patch', async () => {
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.27.15')
const result = await run.resolveKubectlVersion('v1.27')
expect(result).toBe('v1.27.15')
})
test('run() - download specified version and set output', async () => {
jest.spyOn(core, 'getInput').mockReturnValue('v1.15.5')
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')

View File

@@ -1,14 +1,13 @@
import * as path from 'path'
import * as util from 'util'
import * as fs from 'fs'
import * as toolCache from '@actions/tool-cache'
import * as core from '@actions/core'
import {
getkubectlDownloadURL,
getKubectlArch,
getExecutableExtension
getExecutableExtension,
getLatestPatchVersion
} from './helpers'
const kubectlToolName = 'kubectl'
@@ -20,6 +19,8 @@ export async function run() {
let version = core.getInput('version', {required: true})
if (version.toLocaleLowerCase() === 'latest') {
version = await getStableKubectlVersion()
} else {
version = await resolveKubectlVersion(version)
}
const cachedPath = await downloadKubectl(version)
@@ -89,3 +90,28 @@ export async function downloadKubectl(version: string): Promise<string> {
fs.chmodSync(kubectlPath, '775')
return kubectlPath
}
export async function resolveKubectlVersion(version: string): Promise<string> {
const cleanedVersion = version.trim()
const versionMatch = cleanedVersion.match(
/^v?(?<major>\d+)\.(?<minor>\d+)(?:\.(?<patch>\d+))?$/
)
if (!versionMatch?.groups) {
throw new Error(
`Invalid version format: "${version}". Version must be in "major.minor" or "major.minor.patch" format (e.g., "1.27" or "v1.27.15").`
)
}
const {major, minor, patch} = versionMatch.groups
if (patch) {
// Full version was provided, just ensure it has a 'v' prefix
return cleanedVersion.startsWith('v')
? cleanedVersion
: `v${cleanedVersion}`
}
// Patch version is missing, fetch the latest
return await getLatestPatchVersion(major, minor)
}

View File

@@ -1,7 +1,8 @@
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs"
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"]
},
"exclude": ["node_modules", "test"]
}