Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ description: 'Install a specific version of kubectl binary. Acceptable values ar
inputs:
version:
description: 'Version of kubectl'
required: true
required: false
default: 'latest'
version-file:
description: 'Path to a .tool-versions (asdf/mise) file to read the kubectl version from. Takes precedence over the version input.'
required: false
outputs:
kubectl-path:
description: 'Path to the cached kubectl binary'
Expand Down
15 changes: 15 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,18 @@ export function getExecutableExtension(): string {
}
return ''
}

export function parseToolVersionsFile(filePath: string): string {
const content = fs.readFileSync(filePath, 'utf8').toString()
for (const line of content.split('\n')) {
const trimmed = line.trim()
if (trimmed.startsWith('#') || trimmed === '') continue
const [tool, version] = trimmed.split(/\s+/)
if (tool === 'kubectl' && version) {
return version
}
}
throw new Error(
`Could not find a kubectl entry in tool-versions file: ${filePath}`
)
}
54 changes: 51 additions & 3 deletions src/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const {
getkubectlDownloadURL,
getKubectlArch,
getExecutableExtension,
getLatestPatchVersion
getLatestPatchVersion,
parseToolVersionsFile
} = await import('./helpers.js')

describe('Testing all functions in run file.', () => {
Expand Down Expand Up @@ -226,14 +227,18 @@ describe('Testing all functions in run file.', () => {
expect(result).toBe('v1.27.15')
})
test('run() - download specified version and set output', async () => {
vi.mocked(core.getInput).mockReturnValue('v1.15.5')
vi.mocked(core.getInput).mockImplementation((name) => {
if (name === 'version-file') return ''
return 'v1.15.5'
})
vi.mocked(toolCache.find).mockReturnValue('pathToCachedTool')
vi.mocked(os.type).mockReturnValue('Windows_NT')
vi.mocked(fs.chmodSync).mockImplementation()
vi.mocked(core.addPath).mockImplementation()
vi.spyOn(console, 'log').mockImplementation()
vi.mocked(core.setOutput).mockImplementation()
expect(await run.run()).toBeUndefined()
expect(core.getInput).toHaveBeenCalledWith('version-file')
expect(core.getInput).toHaveBeenCalledWith('version', {required: true})
expect(core.addPath).toHaveBeenCalledWith('pathToCachedTool')
expect(core.setOutput).toHaveBeenCalledWith(
Expand All @@ -242,7 +247,10 @@ describe('Testing all functions in run file.', () => {
)
})
test('run() - get latest version, download it and set output', async () => {
vi.mocked(core.getInput).mockReturnValue('latest')
vi.mocked(core.getInput).mockImplementation((name) => {
if (name === 'version-file') return ''
return 'latest'
})
vi.mocked(toolCache.downloadTool).mockResolvedValue('pathToTool')
vi.mocked(fs.readFileSync).mockReturnValue('v1.20.4')
vi.mocked(toolCache.find).mockReturnValue('pathToCachedTool')
Expand All @@ -255,11 +263,51 @@ describe('Testing all functions in run file.', () => {
expect(toolCache.downloadTool).toHaveBeenCalledWith(
'https://dl.k8s.io/release/stable.txt'
)
expect(core.getInput).toHaveBeenCalledWith('version-file')
expect(core.getInput).toHaveBeenCalledWith('version', {required: true})
expect(core.addPath).toHaveBeenCalledWith('pathToCachedTool')
expect(core.setOutput).toHaveBeenCalledWith(
'kubectl-path',
path.join('pathToCachedTool', 'kubectl.exe')
)
})
test('parseToolVersionsFile() - return kubectl version from .tool-versions file', () => {
vi.mocked(fs.readFileSync).mockReturnValue(
'kubectl 1.27.15\nnode 20.0.0\n'
)
expect(parseToolVersionsFile('.tool-versions')).toBe('1.27.15')
expect(fs.readFileSync).toHaveBeenCalledWith('.tool-versions', 'utf8')
})
test('parseToolVersionsFile() - ignore comments and blank lines', () => {
vi.mocked(fs.readFileSync).mockReturnValue(
'# comment\n\nkubectl 1.27.15\n'
)
expect(parseToolVersionsFile('.tool-versions')).toBe('1.27.15')
})
test('parseToolVersionsFile() - throw error when kubectl entry is not found', () => {
vi.mocked(fs.readFileSync).mockReturnValue('node 20.0.0\npython 3.11.0\n')
expect(() => parseToolVersionsFile('.tool-versions')).toThrow(
'Could not find a kubectl entry in tool-versions file: .tool-versions'
)
})
test('run() - use version-file to determine kubectl version', async () => {
vi.mocked(core.getInput).mockImplementation((name) => {
if (name === 'version-file') return '.tool-versions'
return ''
})
vi.mocked(fs.readFileSync).mockReturnValue('kubectl 1.27.15\n')
vi.mocked(toolCache.find).mockReturnValue('pathToCachedTool')
vi.mocked(os.type).mockReturnValue('Linux')
vi.mocked(fs.chmodSync).mockImplementation()
vi.mocked(core.addPath).mockImplementation()
vi.mocked(core.setOutput).mockImplementation()
expect(await run.run()).toBeUndefined()
expect(core.getInput).toHaveBeenCalledWith('version-file')
expect(fs.readFileSync).toHaveBeenCalledWith('.tool-versions', 'utf8')
expect(core.addPath).toHaveBeenCalledWith('pathToCachedTool')
expect(core.setOutput).toHaveBeenCalledWith(
'kubectl-path',
path.join('pathToCachedTool', 'kubectl')
)
})
})
19 changes: 14 additions & 5 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,28 @@ import {
getkubectlDownloadURL,
getKubectlArch,
getExecutableExtension,
getLatestPatchVersion
getLatestPatchVersion,
parseToolVersionsFile
} from './helpers.js'

const kubectlToolName = 'kubectl'
const stableKubectlVersion = 'v1.15.0'
const stableVersionUrl = 'https://dl.k8s.io/release/stable.txt'

export async function run() {
let version = core.getInput('version', {required: true})
if (version.toLocaleLowerCase() === 'latest') {
version = await getStableKubectlVersion()
const versionFile = core.getInput('version-file')
let version: string

if (versionFile) {
const rawVersion = parseToolVersionsFile(versionFile)
version = await resolveKubectlVersion(rawVersion)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tatsinnit do you want me to address this issue ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for the contributions @acouvreur here are some thoughts, please: #261 (review)

} else {
version = await resolveKubectlVersion(version)
version = core.getInput('version', {required: true})
if (version.toLocaleLowerCase() === 'latest') {
version = await getStableKubectlVersion()
} else {
version = await resolveKubectlVersion(version)
}
}
const cachedPath = await downloadKubectl(version)

Expand Down