Compare commits

..

1 Commits
main ... v4.0.0

Author SHA1 Message Date
GitHub Action
27bfb38730 build 2024-02-13 20:45:12 +00:00
38 changed files with 200322 additions and 2756 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

@ -1,91 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: 'CodeQL Advanced'
on:
push:
branches: ['main']
pull_request:
branches: ['main']
schedule:
- cron: '15 9 * * 0'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: javascript-typescript
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v3.29.5
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v3.29.5
with:
category: '/language:${{matrix.language}}'

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@v3
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@v3
name: Setting PR as Idle name: Setting PR as Idle
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -15,7 +15,7 @@ jobs:
steps: steps:
- name: Checkout Source Code - name: Checkout Source Code
id: checkout-code id: checkout-code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v2
- name: Npm Install and Build - name: Npm Install and Build
id: npm-build id: npm-build
run: | run: |

View File

@ -1,4 +1,4 @@
name: 'Run Prettify' name: 'Run prettify'
on: on:
pull_request: pull_request:
push: push:
@ -10,16 +10,9 @@ 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@v2
- name: Setup Node.js - name: Enforce Prettier
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 uses: actionsx/prettier@v2
with: with:
node-version: 'lts/*' args: --check .
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Run Prettier Check
run: npx prettier --check .

View File

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

View File

@ -13,7 +13,7 @@ jobs:
unit-test: unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v1
- name: Run Unit Tests - name: Run Unit Tests
run: | run: |
npm install npm install

1
.gitignore vendored
View File

@ -331,4 +331,3 @@ node_modules
coverage coverage
# Transpiled JS # Transpiled JS
lib/

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,54 +1,5 @@
# Change Log # Change Log
## [5.0.0] - 2026-04-07
### Features
- #227 Migrate to ESM with esbuild, vitest
### Runtime and platform
- #222 Update Node version from 20 to 24
### Dependabot updates
- #231 Bump github/codeql-action in /.github/workflows in the actions group
- #230 Bump typescript in the actions group across 1 directory
- #228 Bump picomatch
- #226 Bump github/codeql-action in /.github/workflows in the actions group
- #223 Bump undici from 6.23.0 to 6.24.0
- #221 Bump the actions group in /.github/workflows with 2 updates
- #218 Bump the actions group in /.github/workflows with 2 updates
- #219 Bump minimatch
- #217 Bump undici and @actions/http-client
- #216 Bump github/codeql-action in /.github/workflows in the actions group
- #214 Bump the actions group in /.github/workflows with 2 updates
- #212 Bump the actions group in /.github/workflows with 2 updates
- #211 Bump the actions group with 3 updates
- #210 Bump the actions group with 2 updates
- #208 Bump @types/node from 25.0.2 to 25.0.3 in the actions group
- #209 Bump github/codeql-action in /.github/workflows in the actions group
- #206 Bump the actions group with 3 updates
- #207 Bump github/codeql-action in /.github/workflows in the actions group
- #205 Bump the actions group in /.github/workflows with 4 updates
- #204 Bump the actions group with 2 updates
- #202 Bump the actions group in /.github/workflows with 2 updates
- #203 Bump prettier from 3.6.2 to 3.7.3 in the actions group
- #201 Bump glob from 10.4.5 to 10.5.0
- #200 Bump js-yaml from 3.14.1 to 3.14.2
- #198 Bump js-yaml from 4.1.0 to 4.1.1
- #199 Bump the actions group with 2 updates
## [4.0.2] - 2025-11-13
- #[164](https://github.com/Azure/k8s-set-context/pull/164) Adding optional kubeconfig encoding variable
- Dependabot updates
## [4.0.1] - 2024-09-06
- #90 update dev dependencies with Typescript to 5
- #89 Adding dependabot
## [4.0.0] - 2024-02-13 ## [4.0.0] - 2024-02-13
- #83 update to node20 as node16 is deprecated - #83 update to node20 as node16 is deprecated

View File

@ -19,7 +19,7 @@ Refer to the [action metadata file](./action.yml) for details about inputs. Note
### Kubeconfig approach ### Kubeconfig approach
```yaml ```yaml
- uses: azure/k8s-set-context@v5 - uses: azure/k8s-set-context@v3
with: with:
method: kubeconfig method: kubeconfig
kubeconfig: <your kubeconfig> kubeconfig: <your kubeconfig>
@ -50,7 +50,7 @@ Please refer to documentation on fetching [kubeconfig for any generic K8s cluste
### Service account approach ### Service account approach
```yaml ```yaml
- uses: azure/k8s-set-context@v5 - uses: azure/k8s-set-context@v3
with: with:
method: service-account method: service-account
k8s-url: <URL of the cluster's API server> k8s-url: <URL of the cluster's API server>
@ -74,7 +74,7 @@ kubectl get secret <service-account-secret-name> -n <namespace> -o yaml
### Service account approach for arc cluster ### Service account approach for arc cluster
```yaml ```yaml
- uses: azure/k8s-set-context@v5 - uses: azure/k8s-set-context@v3
with: with:
method: service-account method: service-account
cluster-type: arc cluster-type: arc
@ -86,7 +86,7 @@ kubectl get secret <service-account-secret-name> -n <namespace> -o yaml
### Service principal approach for arc cluster ### Service principal approach for arc cluster
```yaml ```yaml
- uses: azure/k8s-set-context@v5 - uses: azure/k8s-set-context@v3
with: with:
method: service-principal method: service-principal
cluster-type: arc cluster-type: arc

View File

@ -13,10 +13,6 @@ inputs:
kubeconfig: kubeconfig:
description: 'Contents of kubeconfig file' description: 'Contents of kubeconfig file'
required: false required: false
kubeconfig-encoding:
description: 'Encoding of the kubeconfig input. Accepts "plaintext" (default) or "base64".'
required: false
default: 'plaintext'
context: context:
description: 'If your kubeconfig has multiple contexts, use this field to use a specific context, otherwise the default one would be chosen' description: 'If your kubeconfig has multiple contexts, use this field to use a specific context, otherwise the default one would be chosen'
required: false required: false
@ -39,5 +35,5 @@ inputs:
branding: branding:
color: 'blue' color: 'blue'
runs: runs:
using: 'node24' using: 'node20'
main: 'lib/index.js' main: 'lib/index.js'

20
jest.config.js Normal file
View File

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

39
lib/exec-child.js Normal file
View File

@ -0,0 +1,39 @@
if (require.main !== module) {
throw new Error('This file should not be required');
}
var childProcess = require('child_process');
var fs = require('fs');
var paramFilePath = process.argv[2];
var serializedParams = fs.readFileSync(paramFilePath, 'utf8');
var params = JSON.parse(serializedParams);
var cmd = params.command;
var execOptions = params.execOptions;
var pipe = params.pipe;
var stdoutFile = params.stdoutFile;
var stderrFile = params.stderrFile;
var c = childProcess.exec(cmd, execOptions, function (err) {
if (!err) {
process.exitCode = 0;
} else if (err.code === undefined) {
process.exitCode = 1;
} else {
process.exitCode = err.code;
}
});
var stdoutStream = fs.createWriteStream(stdoutFile);
var stderrStream = fs.createWriteStream(stderrFile);
c.stdout.pipe(stdoutStream);
c.stderr.pipe(stderrStream);
c.stdout.pipe(process.stdout);
c.stderr.pipe(process.stderr);
if (pipe) {
c.stdin.end(pipe);
}

192191
lib/index.js Normal file

File diff suppressed because one or more lines are too long

10065
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,15 @@
{ {
"name": "k8s-set-context-action", "name": "k8s-set-context-action",
"version": "5.0.0", "version": "4.0.0",
"private": true, "private": true,
"main": "lib/index.js", "main": "lib/index.js",
"type": "module",
"scripts": { "scripts": {
"build": "tsc --noEmit && esbuild src/run.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 @vercel/ncc",
"typecheck": "tsc --noEmit", "build": "ncc build src/run.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"
}, },
"keywords": [ "keywords": [
"actions", "actions",
@ -21,19 +19,20 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^3.0.0", "@actions/core": "^1.10.0",
"@actions/exec": "^3.0.0", "@actions/exec": "^1.0.0",
"@actions/io": "^3.0.2", "@actions/io": "^1.1.2",
"@kubernetes/client-node": "^1.4.0", "@kubernetes/client-node": "^0.16.0",
"husky": "^9.1.7", "js-yaml": "^4.1.0"
"js-yaml": "^4.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^4.0.9", "@types/jest": "^28.1.2",
"@types/node": "^25.5.2", "@types/js-yaml": "^4.0.4",
"esbuild": "^0.28.0", "@types/node": "^16.0.0",
"prettier": "^3.8.0", "@vercel/ncc": "^0.34.0",
"typescript": "^6.0.2", "jest": "^28.1.1",
"vitest": "^4.1.1" "prettier": "2.7.1",
"ts-jest": "^28.0.5",
"typescript": "4.7.4"
} }
} }

View File

@ -1,9 +1,7 @@
import {vi, describe, it, expect} from 'vitest' import {getRequiredInputError} from '../tests/util'
import {getRequiredInputError} from '../tests/util.js' import {run} from './action'
import {run} from './action.js' import fs from 'fs'
import * as utils from './utils'
vi.mock('fs')
vi.mock('./utils.js')
describe('Run', () => { describe('Run', () => {
it('throws error without cluster type', async () => { it('throws error without cluster type', async () => {
@ -11,23 +9,22 @@ describe('Run', () => {
}) })
it('writes kubeconfig and sets context', async () => { it('writes kubeconfig and sets context', async () => {
const {getKubeconfig, setContext} = await import('./utils.js')
const fs = await import('fs')
const kubeconfig = 'kubeconfig' const kubeconfig = 'kubeconfig'
process.env['INPUT_CLUSTER-TYPE'] = 'default' process.env['INPUT_CLUSTER-TYPE'] = 'default'
process.env['RUNNER_TEMP'] = '/sample/path' process.env['RUNNER_TEMP'] = '/sample/path'
vi.mocked(getKubeconfig).mockResolvedValue(kubeconfig) jest
vi.mocked(setContext).mockReturnValue(kubeconfig) .spyOn(utils, 'getKubeconfig')
vi.mocked(fs.writeFileSync).mockImplementation(() => {}) .mockImplementation(async () => kubeconfig)
vi.mocked(fs.chmodSync).mockImplementation(() => {}) jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {})
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(utils, 'setContext').mockImplementation(() => kubeconfig)
await run() expect(await run())
expect(utils.getKubeconfig).toHaveBeenCalled()
expect(getKubeconfig).toHaveBeenCalled()
expect(fs.writeFileSync).toHaveBeenCalled() expect(fs.writeFileSync).toHaveBeenCalled()
expect(fs.chmodSync).toHaveBeenCalled() expect(fs.chmodSync).toHaveBeenCalled()
expect(setContext).toHaveBeenCalled() expect(utils.setContext).toHaveBeenCalled()
}) })
}) })

View File

@ -1,8 +1,8 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as path from 'path' import * as path from 'path'
import * as fs from 'fs' import * as fs from 'fs'
import {Cluster, parseCluster} from './types/cluster.js' import {Cluster, parseCluster} from './types/cluster'
import {setContext, getKubeconfig} from './utils.js' import {setContext, getKubeconfig} from './utils'
/** /**
* Sets the Kubernetes context based on supplied action inputs * Sets the Kubernetes context based on supplied action inputs
@ -14,7 +14,7 @@ export async function run() {
required: true required: true
}) })
) )
const runnerTempDirectory: string = process.env['RUNNER_TEMP'] ?? '' const runnerTempDirectory: string = process.env['RUNNER_TEMP']
const kubeconfigPath: string = path.join( const kubeconfigPath: string = path.join(
runnerTempDirectory, runnerTempDirectory,
`kubeconfig_${Date.now()}` `kubeconfig_${Date.now()}`

View File

@ -1,11 +1,8 @@
import {vi, describe, test, it, expect, beforeEach} from 'vitest' import * as actions from '@actions/exec'
import * as io from '@actions/io' import * as io from '@actions/io'
import {getRequiredInputError} from '../../tests/util.js' import {getRequiredInputError} from '../../tests/util'
import {getArcKubeconfig, KUBECONFIG_LOCATION} from './arc.js' import {getArcKubeconfig, KUBECONFIG_LOCATION} from './arc'
import * as az from './azCommands.js' import * as az from './azCommands'
vi.mock('@actions/io')
vi.mock('./azCommands.js')
describe('Arc kubeconfig', () => { describe('Arc kubeconfig', () => {
test('it throws error without resource group', async () => { test('it throws error without resource group', async () => {
@ -31,11 +28,11 @@ describe('Arc kubeconfig', () => {
process.env['INPUT_RESOURCE-GROUP'] = group process.env['INPUT_RESOURCE-GROUP'] = group
process.env['INPUT_CLUSTER-NAME'] = name process.env['INPUT_CLUSTER-NAME'] = name
vi.mocked(io.which).mockResolvedValue(path) jest.spyOn(io, 'which').mockImplementation(async () => path)
vi.mocked(az.runAzCliCommand).mockResolvedValue(undefined) jest.spyOn(az, 'runAzCliCommand').mockImplementation(async () => {})
vi.mocked(az.runAzKubeconfigCommandBlocking).mockResolvedValue( jest
kubeconfig .spyOn(az, 'runAzKubeconfigCommandBlocking')
) .mockImplementation(async () => kubeconfig)
}) })
it('throws an error without method', async () => { it('throws an error without method', async () => {

View File

@ -1,8 +1,8 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as io from '@actions/io' import * as io from '@actions/io'
import {Method, parseMethod} from '../types/method.js' import {Method, parseMethod} from '../types/method'
import * as path from 'path' import * as path from 'path'
import {runAzCliCommand, runAzKubeconfigCommandBlocking} from './azCommands.js' import {runAzCliCommand, runAzKubeconfigCommandBlocking} from './azCommands'
const RUNNER_TEMP: string = process.env['RUNNER_TEMP'] || '' const RUNNER_TEMP: string = process.env['RUNNER_TEMP'] || ''
export const KUBECONFIG_LOCATION: string = path.join( export const KUBECONFIG_LOCATION: string = path.join(

View File

@ -1,17 +1,14 @@
import {vi, describe, test, expect, beforeEach} from 'vitest'
import * as actions from '@actions/exec' import * as actions from '@actions/exec'
import {runAzCliCommand} from './azCommands.js' import {runAzCliCommand} from './azCommands'
vi.mock('@actions/exec')
describe('Az commands', () => { describe('Az commands', () => {
test('it runs an az cli command', async () => { test('it runs an az cli command', async () => {
const path = 'path' const path = 'path'
const args = ['args'] const args = ['args']
vi.mocked(actions.exec).mockResolvedValue(0) jest.spyOn(actions, 'exec').mockImplementation(async () => 0)
await runAzCliCommand(path, args) expect(await runAzCliCommand(path, args))
expect(actions.exec).toHaveBeenCalledWith(path, args, {}) expect(actions.exec).toBeCalledWith(path, args, {})
}) })
}) })

View File

@ -1,5 +1,6 @@
import * as fs from 'fs' import * as fs from 'fs'
import {ExecOptions, exec} from '@actions/exec' import {ExecOptions} from '@actions/exec/lib/interfaces'
import {exec} from '@actions/exec'
import {spawn} from 'child_process' import {spawn} from 'child_process'
const AZ_TIMEOUT_SECONDS: number = 120 const AZ_TIMEOUT_SECONDS: number = 120

View File

@ -1,7 +1,6 @@
import {vi, describe, test, expect, beforeEach, afterEach} from 'vitest'
import * as fs from 'fs' import * as fs from 'fs'
import {getRequiredInputError} from '../../tests/util.js' import {getRequiredInputError} from '../../tests/util'
import {createKubeconfig, getDefaultKubeconfig} from './default.js' import {createKubeconfig, getDefaultKubeconfig} from './default'
describe('Default kubeconfig', () => { describe('Default kubeconfig', () => {
test('it creates a kubeconfig with proper format', () => { test('it creates a kubeconfig with proper format', () => {
@ -51,11 +50,6 @@ describe('Default kubeconfig', () => {
process.env['INPUT_METHOD'] = 'default' process.env['INPUT_METHOD'] = 'default'
}) })
afterEach(() => {
delete process.env['INPUT_KUBECONFIG']
delete process.env['INPUT_KUBECONFIG-ENCODING']
})
test('it throws error without kubeconfig', () => { test('it throws error without kubeconfig', () => {
expect(() => getDefaultKubeconfig()).toThrow( expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError('kubeconfig') getRequiredInputError('kubeconfig')
@ -68,33 +62,6 @@ describe('Default kubeconfig', () => {
expect(getDefaultKubeconfig()).toBe(kc) expect(getDefaultKubeconfig()).toBe(kc)
}) })
test('returns kubeconfig as plaintext when encoding is plaintext', () => {
const kc = 'example kc'
process.env['INPUT_KUBECONFIG'] = kc
process.env['INPUT_KUBECONFIG-ENCODING'] = 'plaintext'
expect(getDefaultKubeconfig()).toBe(kc)
})
test('it gets default config through base64 kubeconfig input', () => {
const kc = 'example kc'
const base64Kc = Buffer.from(kc, 'utf-8').toString('base64')
process.env['INPUT_KUBECONFIG'] = base64Kc
process.env['INPUT_KUBECONFIG-ENCODING'] = 'base64'
expect(getDefaultKubeconfig()).toBe(kc)
})
test('it throws error for unknown kubeconfig-encoding', () => {
const kc = 'example kc'
process.env['INPUT_KUBECONFIG'] = kc
process.env['INPUT_KUBECONFIG-ENCODING'] = 'foobar'
expect(() => getDefaultKubeconfig()).toThrow(
"Invalid kubeconfig-encoding: 'foobar'. Must be 'plaintext' or 'base64'."
)
})
}) })
test('it defaults to default method', () => { test('it defaults to default method', () => {

View File

@ -1,8 +1,8 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as jsyaml from 'js-yaml' import * as jsyaml from 'js-yaml'
import {KubeConfig} from '@kubernetes/client-node' import {KubeConfig} from '@kubernetes/client-node'
import {K8sSecret, parseK8sSecret} from '../types/k8sSecret.js' import {K8sSecret, parseK8sSecret} from '../types/k8sSecret'
import {Method, parseMethod} from '../types/method.js' import {Method, parseMethod} from '../types/method'
/** /**
* Gets the kubeconfig based on provided method for a default Kubernetes cluster * Gets the kubeconfig based on provided method for a default Kubernetes cluster
@ -44,27 +44,7 @@ export function getDefaultKubeconfig(): string {
} }
default: { default: {
core.debug('Setting context using kubeconfig') core.debug('Setting context using kubeconfig')
enum Encoding { return core.getInput('kubeconfig', {required: true})
Base64 = 'base64',
Plaintext = 'plaintext'
}
const rawKubeconfig = core.getInput('kubeconfig', {required: true})
const encoding =
core.getInput('kubeconfig-encoding')?.toLowerCase() ||
Encoding.Plaintext
if (encoding !== Encoding.Base64 && encoding !== Encoding.Plaintext) {
throw new Error(
`Invalid kubeconfig-encoding: '${encoding}'. Must be 'plaintext' or 'base64'.`
)
}
const kubeconfig =
encoding === Encoding.Base64
? Buffer.from(rawKubeconfig, 'base64').toString('utf-8')
: rawKubeconfig
return kubeconfig
} }
} }
} }

View File

@ -1,4 +1,4 @@
import {run} from './action.js' import {run} from './action'
import * as core from '@actions/core' import * as core from '@actions/core'
// Run the application // Run the application

View File

@ -1,9 +1,8 @@
import {describe, test, expect} from 'vitest' import {Cluster, parseCluster} from './cluster'
import {Cluster, parseCluster} from './cluster.js'
describe('Cluster type', () => { describe('Cluster type', () => {
test('it has required values', () => { test('it has required values', () => {
const vals = Object.values(Cluster) as string[] const vals = <any>Object.values(Cluster)
expect(vals.includes('arc')).toBe(true) expect(vals.includes('arc')).toBe(true)
expect(vals.includes('generic')).toBe(true) expect(vals.includes('generic')).toBe(true)
}) })

View File

@ -8,10 +8,9 @@ export enum Cluster {
* @param str The cluster type (case insensitive) * @param str The cluster type (case insensitive)
* @returns The Cluster enum or undefined if it can't be parsed * @returns The Cluster enum or undefined if it can't be parsed
*/ */
export const parseCluster = (str: string): Cluster | undefined => { export const parseCluster = (str: string): Cluster | undefined =>
const key = Object.keys(Cluster).find( Cluster[
(k) => Object.keys(Cluster).filter(
Cluster[k as keyof typeof Cluster].toLowerCase() === str.toLowerCase() (k) => Cluster[k].toString().toLowerCase() === str.toLowerCase()
) as keyof typeof Cluster | undefined )[0] as keyof typeof Cluster
return key !== undefined ? Cluster[key] : undefined ]
}

View File

@ -1,5 +1,4 @@
import {describe, test, expect} from 'vitest' import {parseK8sSecret, K8sSecret} from './k8sSecret'
import {parseK8sSecret} from './k8sSecret.js'
describe('K8sSecret type', () => { describe('K8sSecret type', () => {
describe('Parsing from any', () => { describe('Parsing from any', () => {

View File

@ -1,9 +1,8 @@
import {describe, test, expect} from 'vitest' import {Method, parseMethod} from './method'
import {Method, parseMethod} from './method.js'
describe('Method type', () => { describe('Method type', () => {
test('it has required values', () => { test('it has required values', () => {
const vals = Object.values(Method) as string[] const vals = <any>Object.values(Method)
expect(vals.includes('kubeconfig')).toBe(true) expect(vals.includes('kubeconfig')).toBe(true)
expect(vals.includes('service-account')).toBe(true) expect(vals.includes('service-account')).toBe(true)
expect(vals.includes('service-principal')).toBe(true) expect(vals.includes('service-principal')).toBe(true)

View File

@ -9,10 +9,9 @@ export enum Method {
* @param str The method (case insensitive) * @param str The method (case insensitive)
* @returns The Method enum or undefined if it can't be parsed * @returns The Method enum or undefined if it can't be parsed
*/ */
export const parseMethod = (str: string): Method | undefined => { export const parseMethod = (str: string): Method | undefined =>
const key = Object.keys(Method).find( Method[
(k) => Object.keys(Method).filter(
Method[k as keyof typeof Method].toLowerCase() === str.toLowerCase() (k) => Method[k].toString().toLowerCase() === str.toLowerCase()
) as keyof typeof Method | undefined )[0] as keyof typeof Method
return key !== undefined ? Method[key] : undefined ]
}

View File

@ -1,26 +1,25 @@
import {vi, describe, test, expect} from 'vitest'
import fs from 'fs' import fs from 'fs'
import * as arc from './kubeconfigs/arc.js' import * as arc from './kubeconfigs/arc'
import * as def from './kubeconfigs/default.js' import * as def from './kubeconfigs/default'
import {Cluster} from './types/cluster.js' import {Cluster} from './types/cluster'
import {getKubeconfig, setContext} from './utils.js' import {getKubeconfig, setContext} from './utils'
describe('Utils', () => { describe('Utils', () => {
describe('get kubeconfig', () => { describe('get kubeconfig', () => {
test('it gets arc kubeconfig when type is arc', async () => { test('it gets arc kubeconfig when type is arc', async () => {
const arcKubeconfig = 'arckubeconfig' const arcKubeconfig = 'arckubeconfig'
vi.spyOn(arc, 'getArcKubeconfig').mockImplementation( jest
async () => arcKubeconfig .spyOn(arc, 'getArcKubeconfig')
) .mockImplementation(async () => arcKubeconfig)
expect(await getKubeconfig(Cluster.ARC)).toBe(arcKubeconfig) expect(await getKubeconfig(Cluster.ARC)).toBe(arcKubeconfig)
}) })
test('it defaults to default kubeconfig', async () => { test('it defaults to default kubeconfig', async () => {
const defaultKubeconfig = 'arckubeconfig' const defaultKubeconfig = 'arckubeconfig'
vi.spyOn(def, 'getDefaultKubeconfig').mockImplementation( jest
() => defaultKubeconfig .spyOn(def, 'getDefaultKubeconfig')
) .mockImplementation(() => defaultKubeconfig)
expect(await getKubeconfig(undefined)).toBe(defaultKubeconfig) expect(await getKubeconfig(undefined)).toBe(defaultKubeconfig)
expect(await getKubeconfig(Cluster.GENERIC)).toBe(defaultKubeconfig) expect(await getKubeconfig(Cluster.GENERIC)).toBe(defaultKubeconfig)

View File

@ -1,9 +1,9 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as fs from 'fs' import * as fs from 'fs'
import {KubeConfig} from '@kubernetes/client-node' import {KubeConfig} from '@kubernetes/client-node'
import {getDefaultKubeconfig} from './kubeconfigs/default.js' import {getDefaultKubeconfig} from './kubeconfigs/default'
import {getArcKubeconfig} from './kubeconfigs/arc.js' import {getArcKubeconfig} from './kubeconfigs/arc'
import {Cluster} from './types/cluster.js' import {Cluster} from './types/cluster'
/** /**
* Gets the kubeconfig based on Kubernetes cluster type * Gets the kubeconfig based on Kubernetes cluster type

View File

@ -1,14 +1,8 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES6",
"module": "NodeNext", "module": "commonjs",
"moduleResolution": "NodeNext", "esModuleInterop": true
"rootDir": "./src",
"outDir": "./lib",
"noImplicitAny": false,
"skipLibCheck": true,
"noEmit": true,
"types": ["node", "vitest/globals"]
}, },
"exclude": ["node_modules", "**/*.test.ts", "vitest.config.ts", "tests/"] "exclude": ["node_modules", "tests", "src/**/*.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
}
})