Compare commits

...

74 Commits

Author SHA1 Message Date
Suneha Bose d32f722e54 Update CODEOWNERS 2025-07-22 12:18:44 -07:00
dependabot[bot] 4ad647536e Bump @types/node from 24.0.13 to 24.0.15 in the actions group (#168)
---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.15
  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-22 12:05:30 -07:00
dependabot[bot] f95370c1a4 Bump form-data from 4.0.2 to 4.0.4 (#169)
---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 12:04:50 -07:00
Betsy George 0fc754ad67 #146 Adding optional kubeconfig encoding variable (#164)
* encoding input variable added

* encoding input variable added

* encoding input variable added

* corrected unit tests

* corrected unit tests

* prettier edits

* working on tests

* working on tests

* working on tests

* minor edits

* minor edits

* better logic structure

* added tests for edge cases

* edited to enum
2025-07-17 12:27:04 -06:00
dependabot[bot] 8440376895 Bump @types/node from 24.0.10 to 24.0.13 in the actions group (#165)
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 13:03:38 -06:00
dependabot[bot] 73c851170f Bump the actions group with 4 updates (#163)
Bumps the actions group with 4 updates: [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env), [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [babel-jest](https://github.com/jestjs/jest/tree/HEAD/packages/babel-jest) and [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest).


Updates `@babel/preset-env` from 7.27.2 to 7.28.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.0/packages/babel-preset-env)

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 `babel-jest` from 30.0.2 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/babel-jest)

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: "@babel/preset-env"
  dependency-version: 7.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@types/node"
  dependency-version: 24.0.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: babel-jest
  dependency-version: 30.0.4
  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 12:22:53 -07:00
dependabot[bot] 71a74a51a0 Bump github/codeql-action in /.github/workflows in the actions group (#162)
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](https://github.com/github/codeql-action/compare/39edc492dbe16b1465b0cafca41432d857bdb31a...181d5eefc20863364f96762470ba6f862bdef56b)

---
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 12:22:35 -07:00
Tatsinnit c8c2ee9d3e Feat/enable husky precommit check (#159)
* Add husky precommit hook.

Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>

* Add husky precommit hook.

Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>

* Add more informative messaging.

Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>

---------

Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
2025-07-02 14:06:04 -04:00
dependabot[bot] 692b57e472 Bump github/codeql-action in /.github/workflows in the actions group (#160)
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](https://github.com/github/codeql-action/compare/ce28f5bb42b7a9f2c824e633a3f6ee835bab6858...39edc492dbe16b1465b0cafca41432d857bdb31a)

---
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-02 14:05:24 -04:00
dependabot[bot] 3ac66a3029 Bump the actions group with 3 updates (#161)
Bumps the actions group with 3 updates: [@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.2 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-02 14:05:09 -04:00
dependabot[bot] 79824a32e9 Bump the actions group with 2 updates (#158)f
Bumps the actions group with 2 updates: [babel-jest](https://github.com/jestjs/jest/tree/HEAD/packages/babel-jest) and [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest).


Updates `babel-jest` from 30.0.0 to 30.0.2
- [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.2/packages/babel-jest)

Updates `jest` from 30.0.0 to 30.0.2
- [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.2/packages/jest)

---
updated-dependencies:
- dependency-name: babel-jest
  dependency-version: 30.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: jest
  dependency-version: 30.0.2
  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-06-24 15:08:05 -04:00
dependabot[bot] 910f9259f7 Bump @types/jest in the actions group across 1 directory (#157)
Bumps the actions group with 1 update in the / directory: [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest).


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

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-version: 30.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-17 15:14:36 -04:00
dependabot[bot] f7d748aa83 Bump github/codeql-action in /.github/workflows in the actions group (#155) 2025-06-17 15:08:47 -04:00
Tatsinnit 6381c85c74 Fix the major update packages including Jest. (#156)
Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
2025-06-17 12:07:25 -07:00
dependabot[bot] 454a244870 Bump github/codeql-action in /.github/workflows in the actions group (#152) 2025-06-10 15:17:45 -04:00
dependabot[bot] 6851e67f4a Bump @types/node from 22.15.29 to 22.15.30 in the actions group (#153) 2025-06-10 15:13:01 -04:00
dependabot[bot] c11aaa17fe Bump the actions group with 2 updates (#150) 2025-06-03 15:05:10 -04:00
dependabot[bot] 1aa4d89457 Bump tar-fs from 3.0.8 to 3.0.9 (#151) 2025-06-04 07:04:07 +12:00
dependabot[bot] 14ede2518b Bump @types/node from 22.15.18 to 22.15.21 in the actions group (#149) 2025-05-27 15:06:07 -04:00
dependabot[bot] 99bf174624 Bump the actions group with 2 updates (#147) 2025-05-20 10:57:30 -04:00
dependabot[bot] 6d041f335a Bump github/codeql-action in /.github/workflows in the actions group (#148) 2025-05-20 10:57:10 -04:00
dependabot[bot] 97a27df14f Bump the actions group with 3 updates (#145) 2025-05-13 15:17:34 -04:00
dependabot[bot] 0ea2a4278a Bump the actions group with 3 updates (#144) 2025-05-06 12:09:22 -07:00
dependabot[bot] 9538f1a33d Bump github/codeql-action in /.github/workflows in the actions group (#143) 2025-05-06 12:08:57 -07:00
dependabot[bot] 28ef1bdfc0 Bump github/codeql-action in /.github/workflows in the actions group (#141) 2025-04-29 12:08:23 -07:00
dependabot[bot] 1ab2e2c9aa Bump @types/node from 22.14.1 to 22.15.2 in the actions group (#142) 2025-04-29 12:04:25 -07:00
dependabot[bot] ef02e01573 Bump actions/setup-node in /.github/workflows in the actions group (#140) 2025-04-22 10:25:54 -04:00
dependabot[bot] b969c2d317 Bump github/codeql-action in /.github/workflows in the actions group (#139) 2025-04-15 12:11:55 -07:00
dependabot[bot] 37ab0bfac4 Bump the actions group with 3 updates (#138) 2025-04-15 12:10:56 -07:00
dependabot[bot] 71218192d2 Bump the actions group with 4 updates (#137) 2025-04-08 12:08:48 -07:00
dependabot[bot] 99d4c42f16 Bump github/codeql-action in /.github/workflows in the actions group (#135) 2025-04-01 12:07:42 -07:00
dependabot[bot] 06e58873bc Bump the actions group with 3 updates (#136) 2025-04-01 12:06:44 -07:00
dependabot[bot] 452870641e Bump @types/node from 22.10.2 to 22.13.11 in the actions group (#133)
Bumps the actions group with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `@types/node` from 22.10.2 to 22.13.11
- [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-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-03-25 12:13:22 -07:00
dependabot[bot] e4c918cc16 Bump the actions group in /.github/workflows with 2 updates (#134) 2025-03-26 08:12:21 +13:00
Tatsinnit 959bbfb69a Fix for client-node ESM v Commonjs issue. (#132)
Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
2025-03-19 11:12:40 -04:00
dependabot[bot] 5374e54fdc Bump jsonpath-plus from 10.2.0 to 10.3.0 (#126)
Bumps [jsonpath-plus](https://github.com/s3u/JSONPath) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/s3u/JSONPath/releases)
- [Changelog](https://github.com/JSONPath-Plus/JSONPath/blob/main/CHANGES.md)
- [Commits](https://github.com/s3u/JSONPath/compare/v10.2.0...v10.3.0)

---
updated-dependencies:
- dependency-name: jsonpath-plus
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 14:23:50 -04:00
dependabot[bot] a52253b63a Bump github/codeql-action (#131)
Bumps the actions group with 1 update in the /.github/workflows directory: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.28.9 to 3.28.11
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0...6bb031afdd8eb862ea3fc1848194185e076637e5)

---
updated-dependencies:
- dependency-name: github/codeql-action
  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-03-13 14:19:53 -04:00
dependabot[bot] 4654abedbc Bump github/codeql-action in /.github/workflows in the actions group (#121)
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.28.6 to 3.28.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/17a820bf2e43b47be2c72b39cc905417bc1ab6d0...9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0)

---
updated-dependencies:
- dependency-name: github/codeql-action
  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-02-12 15:07:27 -05:00
Tatsinnit f23a9ab176 Security: remove very outdated action (#119) 2025-02-05 21:06:06 -08:00
Vidya Reddy d0f3e049ae Pin SHA for security and stability (#118) 2025-02-05 13:14:42 -08:00
Vidya Reddy e3ab0d3c82 Add Code Quality analysis (#117) 2025-02-04 12:21:48 -08:00
dependabot[bot] 886043f755 Bump the actions group across 1 directory with 2 updates (#109)
Bumps the actions group with 2 updates in the / directory: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [prettier](https://github.com/prettier/prettier).


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

Updates `prettier` from 3.4.1 to 3.4.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.4.1...3.4.2)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: prettier
  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>
2024-12-18 15:12:42 -05:00
dependabot[bot] 6e733fcb67 Bump cross-spawn from 7.0.3 to 7.0.6 (#105)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-04 15:09:47 -05:00
dependabot[bot] 3c029a39d9 Bump the actions group across 1 directory with 6 updates (#107)
Bumps the actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@kubernetes/client-node](https://github.com/kubernetes-client/javascript) | `0.22.0` | `0.22.3` |
| [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) | `29.5.13` | `29.5.14` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.7.4` | `22.10.1` |
| [@vercel/ncc](https://github.com/vercel/ncc) | `0.38.2` | `0.38.3` |
| [prettier](https://github.com/prettier/prettier) | `3.3.3` | `3.4.1` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.6.2` | `5.7.2` |



Updates `@kubernetes/client-node` from 0.22.0 to 0.22.3
- [Release notes](https://github.com/kubernetes-client/javascript/releases)
- [Changelog](https://github.com/kubernetes-client/javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/javascript/commits)

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

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

Updates `@vercel/ncc` from 0.38.2 to 0.38.3
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.38.2...0.38.3)

Updates `prettier` from 3.3.3 to 3.4.1
- [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.3.3...3.4.1)

Updates `typescript` from 5.6.2 to 5.7.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.2...v5.7.2)

---
updated-dependencies:
- dependency-name: "@kubernetes/client-node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: typescript
  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>
2024-12-04 15:08:02 -05:00
dependabot[bot] 2beb148ddc Bump the actions group across 1 directory with 6 updates (#97)
Bumps the actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) | `1.10.1` | `1.11.1` |
| [@kubernetes/client-node](https://github.com/kubernetes-client/javascript) | `0.21.0` | `0.22.0` |
| [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) | `29.5.12` | `29.5.13` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.5.4` | `22.7.4` |
| [@vercel/ncc](https://github.com/vercel/ncc) | `0.38.1` | `0.38.2` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.5.4` | `5.6.2` |



Updates `@actions/core` from 1.10.1 to 1.11.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Updates `@kubernetes/client-node` from 0.21.0 to 0.22.0
- [Release notes](https://github.com/kubernetes-client/javascript/releases)
- [Changelog](https://github.com/kubernetes-client/javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/javascript/compare/0.21.0...0.22.0)

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

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

Updates `@vercel/ncc` from 0.38.1 to 0.38.2
- [Release notes](https://github.com/vercel/ncc/releases)
- [Commits](https://github.com/vercel/ncc/compare/0.38.1...0.38.2)

Updates `typescript` from 5.5.4 to 5.6.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.5.4...v5.6.2)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@kubernetes/client-node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@vercel/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: typescript
  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>
2024-10-09 15:08:33 -04:00
dependabot[bot] 2b56913365 Bump the actions group in /.github/workflows with 3 updates (#91)
Bumps the actions group in /.github/workflows with 3 updates: [actions/stale](https://github.com/actions/stale), [actions/checkout](https://github.com/actions/checkout) and [actionsx/prettier](https://github.com/actionsx/prettier).


Updates `actions/stale` from 3 to 9
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v3...v9)

Updates `actions/checkout` from 1 to 4
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v1...v4)

Updates `actionsx/prettier` from 2 to 3
- [Release notes](https://github.com/actionsx/prettier/releases)
- [Commits](https://github.com/actionsx/prettier/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actionsx/prettier
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 15:21:09 -04:00
dependabot[bot] a517c9dfcc Bump the actions group across 1 directory with 6 updates (#93)
Bumps the actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) | `1.10.0` | `1.10.1` |
| [@actions/exec](https://github.com/actions/toolkit/tree/HEAD/packages/exec) | `1.0.1` | `1.1.1` |
| [@actions/io](https://github.com/actions/toolkit/tree/HEAD/packages/io) | `1.1.2` | `1.1.3` |
| [@kubernetes/client-node](https://github.com/kubernetes-client/javascript) | `0.16.3` | `0.21.0` |
| [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) | `4.0.4` | `4.0.9` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.16.5` | `22.5.4` |



Updates `@actions/core` from 1.10.0 to 1.10.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Updates `@actions/exec` from 1.0.1 to 1.1.1
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/exec/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/@actions/artifact@1.1.1/packages/exec)

Updates `@actions/io` from 1.1.2 to 1.1.3
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/io/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/io)

Updates `@kubernetes/client-node` from 0.16.3 to 0.21.0
- [Release notes](https://github.com/kubernetes-client/javascript/releases)
- [Changelog](https://github.com/kubernetes-client/javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/javascript/compare/0.16.3...0.21.0)

Updates `@types/js-yaml` from 4.0.4 to 4.0.9
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-yaml)

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

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@actions/exec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@actions/io"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@kubernetes/client-node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: "@types/js-yaml"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 15:18:51 -04:00
Brandon Foley 61a0d19c30 4.0.1 Changelog (#94) 2024-09-06 14:27:01 -07:00
Brandon Foley 5e6a3a4114 Update devDependencies (#90) 2024-09-06 09:33:20 -04:00
Brandon Foley 2d160654d6 Adding dependabot (#89)
* Adding dependabot

* update spacing
2024-09-05 18:00:13 -04:00
David Gamero a57aa49538 update release workflow to major version tag (#86)
* Update release-pr.yml

* Update README.md
2024-03-08 18:07:19 -05:00
David Gamero a72463cdd7 v4 release (#84) 2024-02-13 15:44:18 -05:00
Sarah Miles f2d80c8192 Update to Node 20 (#83) 2024-02-13 15:07:04 -05:00
David Gamero 3624a1fc64 separate action and execution (#77) 2023-01-27 14:49:09 -05:00
dependabot[bot] ab43e1cba5 Bump minimatch from 3.0.4 to 3.1.2 (#74)
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 14:07:12 -05:00
dependabot[bot] f7b05df5e5 Bump json5 from 2.2.1 to 2.2.3 (#75)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 13:25:42 -05:00
Oliver King 6332864ca0 Update README with v3 version (#72) 2023-01-09 12:32:46 -06:00
dependabot[bot] d7e25ce077 Bump qs from 6.5.2 to 6.5.3 (#73)
Bumps [qs](https://github.com/ljharb/qs) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.5.2...v6.5.3)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 13:44:07 -05:00
Sumner Warren 0689e8a931 Update @actions/core (#68)
to address https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-11-02 10:25:00 -04:00
dependabot[bot] 03c6fe6b8a Bump jose from 2.0.5 to 2.0.6 (#65)
Bumps [jose](https://github.com/panva/jose) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/v2.0.6/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v2.0.5...v2.0.6)

---
updated-dependencies:
- dependency-name: jose
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 13:34:45 -04:00
Vidya Reddy b0cfd07ecc Systax error fixes (#64) 2022-09-19 09:47:11 -07:00
Vidya Reddy ccc0c881dc Added the bug report and feature request form (#63)
* Added the bug report and feature request form

* updated the url
2022-09-06 17:33:42 -04:00
dependabot[bot] e617f31159 Bump @actions/core from 1.2.6 to 1.9.1 (#62)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.9.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-22 13:40:02 -04:00
Vidya Reddy 778581b6aa Vidya reddy/vercel ncc (#58)
* updated action file with node16

* Code consistency using prettier and its workflow

* Enforce Prettier

* code fix

* code fix

* code fix

* add vercel/ncc to build script

* modified action file

Co-authored-by: Vidya Reddy <vidyareddy@microsoft.com>
2022-07-05 10:17:19 -07:00
David Gamero 6331e961d2 fix broken build - switch to ncc build (#56)
* switch to ncc build

* update

* bump ncc
2022-06-30 16:24:00 -04:00
dependabot[bot] 4a983766a0 Bump got from 11.8.2 to 11.8.5 (#52)
Bumps [got](https://github.com/sindresorhus/got) from 11.8.2 to 11.8.5.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.8.2...v11.8.5)

---
updated-dependencies:
- dependency-name: got
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-27 13:36:19 -04:00
Vidya Reddy b6c5bf067a Vidya reddy pretty code (#53)
* updated action file with node16

* Code consistency using prettier and its workflow

* Enforce Prettier

* code fix

* code fix

* code fix

Co-authored-by: Vidya Reddy <vidyareddy@microsoft.com>
2022-06-24 16:08:48 -07:00
Sigurd Fosseng e972a5b196 use @kubernetes/client-node to generate default config (#51) 2022-06-22 10:58:10 -04:00
Vidya b19619f34c updated action file with node16 (#49)
Co-authored-by: Vidya Reddy <vidyareddy@microsoft.com>
2022-06-16 14:43:53 -04:00
dependabot[bot] 6c102e2f8d Bump minimist from 1.2.5 to 1.2.6 (#47)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 15:10:01 -04:00
dependabot[bot] 9328550046 Bump shelljs from 0.8.4 to 0.8.5 (#43)
Bumps [shelljs](https://github.com/shelljs/shelljs) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/shelljs/shelljs/releases)
- [Changelog](https://github.com/shelljs/shelljs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/shelljs/shelljs/compare/v0.8.4...v0.8.5)

---
updated-dependencies:
- dependency-name: shelljs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-07 09:41:54 -05:00
Tommy Barnes 6961761392 Updated workflows and gitignore (#45)
* Updated workflows and gitignore

* Removing ts-build-check
2022-02-04 13:04:43 -05:00
David Gamero 5c5598ab58 master to main rename (#44) 2022-02-02 15:27:35 -05:00
Oliver King 9c64ee94e4 update action.yml to hit description character limit (#40) 2021-12-07 14:40:49 -05:00
58 changed files with 12699 additions and 16575 deletions
+1 -1
View File
@@ -1 +1 @@
* @Azure/aks-atlanta
* @Azure/cloud-native-github-action-owners
+36
View File
@@ -0,0 +1,36 @@
name: Bug Report
description: File a bug report specifying all inputs you provided for the action, we will respond to this thread with any questions.
title: 'Bug: '
labels: ['bug', 'triage']
assignees: '@Azure/aks-atlanta'
body:
- type: textarea
id: What-happened
attributes:
label: What happened?
description: Tell us what happened and how is it different from the expected?
placeholder: Tell us what you see!
validations:
required: true
- type: checkboxes
id: Version
attributes:
label: Version
options:
- label: I am using the latest version
required: true
- type: input
id: Runner
attributes:
label: Runner
description: What runner are you using?
placeholder: Mention the runner info (self-hosted, operating system)
validations:
required: true
- type: textarea
id: Logs
attributes:
label: Relevant log output
description: Run in debug mode for the most verbose logs. Please feel free to attach a screenshot of the logs
validations:
required: true
+6
View File
@@ -0,0 +1,6 @@
blank_issues_enabled: false
contact_links:
- name: GitHub Action "k8s-set-context" Support
url: https://github.com/Azure/k8s-set-context
security: https://github.com/Azure/k8s-set-context/blob/main/SECURITY.md
about: Please ask and answer questions here.
@@ -0,0 +1,13 @@
name: Feature Request
description: File a Feature Request form, we will respond to this thread with any questions.
title: 'Feature Request: '
labels: ['Feature']
assignees: '@Azure/aks-atlanta'
body:
- type: textarea
id: Feature_request
attributes:
label: Feature request
description: Provide example functionality and links to relevant docs
validations:
required: true
@@ -1,7 +1,7 @@
---
name: "Issue: Bug Report / Feature Request"
name: 'Issue: Bug Report / Feature Request'
about: Create a report to help us improve
title: ""
title: ''
labels: need-to-triage
assignees: "@Azure/aks-atlanta"
assignees: '@Azure/aks-atlanta'
---
+18
View File
@@ -0,0 +1,18 @@
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:
- '*'
+91
View File
@@ -0,0 +1,91 @@
# 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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
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@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
category: '/language:${{matrix.language}}'
+26 -26
View File
@@ -2,34 +2,34 @@ name: Setting Default Labels
# Controls when the action will run.
on:
schedule:
- cron: "0 0/3 * * *"
schedule:
- cron: '0 0/3 * * *'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/stale@v3
name: Setting Issue as Idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue is idle because it has been open for 14 days with no activity."
stale-issue-label: "idle"
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
exempt-issue-labels: "backlog"
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
name: Setting Issue as Idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
stale-issue-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
exempt-issue-labels: 'backlog'
- uses: actions/stale@v3
name: Setting PR as Idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: "This PR is idle because it has been open for 14 days with no activity."
stale-pr-label: "idle"
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
name: Setting PR as Idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
stale-pr-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
+140 -139
View File
@@ -1,143 +1,144 @@
name: Run Integration Tests
on:
pull_request:
branches:
- master
- "releases/*"
push:
branches:
- master
- "releases/*"
pull_request:
branches:
- main
- 'releases/*'
push:
branches:
- main
- 'releases/*'
jobs:
kubeconfig-method-integration-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
id: checkout-code
uses: actions/checkout@v2
- name: Npm Install and Build
id: npm-build
run: |
npm install
npm run build
- name: Set Context
uses: ./
with:
method: kubeconfig
context: exp-scratch
kubeconfig: |
apiVersion: v1
clusters:
- cluster:
certificate-authority: fake-ca-file
server: https://1.2.3.4
name: development
- cluster:
insecure-skip-tls-verify: true
server: https://5.6.7.8
name: scratch
contexts:
- context:
cluster: development
namespace: frontend
user: developer
name: dev-frontend
- context:
cluster: development
namespace: storage
user: developer
name: dev-storage
- context:
cluster: scratch
namespace: default
user: experimenter
name: exp-scratch
current-context: ""
kind: Config
preferences: {}
users:
- name: developer
user:
client-certificate: fake-cert-file
client-key: fake-key-file
- name: experimenter
user:
password: some-password
username: exp
- name: Vertify Results
run: |
echo "$EXPECTED_KC" > /tmp/expected_kc.json
DIFF=$(diff <(jq -S -c . $KUBECONFIG) <(jq -S -c . /tmp/expected_kc.json))
if [ "$DIFF" != "" ]; then exit 1; else echo -e "Kubeconfig matches expected"; fi
env:
EXPECTED_KC: |
{
"apiVersion": "v1",
"clusters": [
{
"cluster": {
"certificate-authority": "fake-ca-file",
"insecure-skip-tls-verify": false,
"server": "https://1.2.3.4"
},
"name": "development"
},
{
"cluster": {
"insecure-skip-tls-verify": true,
"server": "https://5.6.7.8"
},
"name": "scratch"
}
],
"contexts": [
{
"context": {
"cluster": "development",
"name": "dev-frontend",
"namespace": "frontend",
"user": "developer"
},
"name": "dev-frontend"
},
{
"context": {
"cluster": "development",
"name": "dev-storage",
"namespace": "storage",
"user": "developer"
},
"name": "dev-storage"
},
{
"context": {
"cluster": "scratch",
"name": "exp-scratch",
"namespace": "default",
"user": "experimenter"
},
"name": "exp-scratch"
}
],
"current-context": "exp-scratch",
"kind": "Config",
"preferences": {
},
"users": [
{
"name": "developer",
"user": {
"client-certificate": "fake-cert-file",
"client-key": "fake-key-file"
}
},
{
"name": "experimenter",
"user": {
"password": "some-password",
"username": "exp"
}
}
]
}
kubeconfig-method-integration-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
id: checkout-code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Npm Install and Build
id: npm-build
run: |
npm install
- name: Build
run: npm run build
- name: Set Context
uses: ./
with:
method: kubeconfig
context: exp-scratch
kubeconfig: |
apiVersion: v1
clusters:
- cluster:
certificate-authority: fake-ca-file
server: https://1.2.3.4
name: development
- cluster:
insecure-skip-tls-verify: true
server: https://5.6.7.8
name: scratch
contexts:
- context:
cluster: development
namespace: frontend
user: developer
name: dev-frontend
- context:
cluster: development
namespace: storage
user: developer
name: dev-storage
- context:
cluster: scratch
namespace: default
user: experimenter
name: exp-scratch
current-context: ""
kind: Config
preferences: {}
users:
- name: developer
user:
client-certificate: fake-cert-file
client-key: fake-key-file
- name: experimenter
user:
password: some-password
username: exp
- name: Vertify Results
run: |
echo "$EXPECTED_KC" > /tmp/expected_kc.json
DIFF=$(diff <(jq -S -c . $KUBECONFIG) <(jq -S -c . /tmp/expected_kc.json))
if [ "$DIFF" != "" ]; then exit 1; else echo -e "Kubeconfig matches expected"; fi
env:
EXPECTED_KC: |
{
"apiVersion": "v1",
"clusters": [
{
"cluster": {
"certificate-authority": "fake-ca-file",
"insecure-skip-tls-verify": false,
"server": "https://1.2.3.4"
},
"name": "development"
},
{
"cluster": {
"insecure-skip-tls-verify": true,
"server": "https://5.6.7.8"
},
"name": "scratch"
}
],
"contexts": [
{
"context": {
"cluster": "development",
"name": "dev-frontend",
"namespace": "frontend",
"user": "developer"
},
"name": "dev-frontend"
},
{
"context": {
"cluster": "development",
"name": "dev-storage",
"namespace": "storage",
"user": "developer"
},
"name": "dev-storage"
},
{
"context": {
"cluster": "scratch",
"name": "exp-scratch",
"namespace": "default",
"user": "experimenter"
},
"name": "exp-scratch"
}
],
"current-context": "exp-scratch",
"kind": "Config",
"preferences": {
},
"users": [
{
"name": "developer",
"user": {
"client-certificate": "fake-cert-file",
"client-key": "fake-key-file"
}
},
{
"name": "experimenter",
"user": {
"password": "some-password",
"username": "exp"
}
}
]
}
+25
View File
@@ -0,0 +1,25 @@
name: 'Run Prettify'
on:
pull_request:
push:
branches: [main]
jobs:
prettier:
name: Prettier Check
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 'lts/*'
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Run Prettier Check
run: npx prettier --check .
+18
View File
@@ -0,0 +1,18 @@
name: Release Project
on:
push:
branches:
- main
paths:
- CHANGELOG.md
workflow_dispatch:
jobs:
release:
permissions:
actions: read
contents: write
uses: Azure/action-release-workflows/.github/workflows/release_js_project.yaml@v1
with:
changelogPath: ./CHANGELOG.md
+10
View File
@@ -0,0 +1,10 @@
name: Tag and create release draft
on:
push:
branches:
- releases/*
jobs:
tag-and-release:
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main
-41
View File
@@ -1,41 +0,0 @@
name: TypeScript Build Check
on: pull_request
jobs:
ts-build-check:
runs-on: ubuntu-latest
steps:
- name: Checkout Pull Request
uses: actions/checkout@v2
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
path: original-pr
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: Clone and Build Pull Request
run: |
cp $GITHUB_WORKSPACE/original-pr/ $GITHUB_WORKSPACE/built-pr -r
cd $GITHUB_WORKSPACE/built-pr/
npm i
npm run build
- name: Compare Built Directories
id: diff
run: |
DIFF=$(diff $GITHUB_WORKSPACE/original-pr/lib $GITHUB_WORKSPACE/built-pr/lib -rqiEZbwBd)
if [ "$DIFF" != "" ]; then exit 1; else echo -e "PR contains up-to-date compiled JavaScript."; fi
- name: Comment Unbuilt TypeScript
if: failure() && steps.diff.outcome == 'failure'
uses: actions/github-script@v2
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: ${{ github.event.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Please compile the TypeScript code with `npm run build`. The compiled JavaScript is not up-to-date.'
})
+16 -16
View File
@@ -1,20 +1,20 @@
name: Run Unit Tests
on:
pull_request:
branches:
- master
- "releases/*"
push:
branches:
- master
- "releases/*"
pull_request:
branches:
- main
- 'releases/*'
push:
branches:
- main
- 'releases/*'
jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Run Unit Tests
run: |
npm install
npm test
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Run Unit Tests
run: |
npm install
npm test
+3
View File
@@ -329,3 +329,6 @@ ASALocalRun/
.mfractor/
node_modules
coverage
# Transpiled JS
lib/
+7
View File
@@ -0,0 +1,7 @@
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
}
+4
View File
@@ -0,0 +1,4 @@
# dependencies
/node_modules
coverage
/lib
+8
View File
@@ -0,0 +1,8 @@
{
"trailingComma": "none",
"bracketSpacing": false,
"semi": false,
"tabWidth": 3,
"singleQuote": true,
"printWidth": 80
}
+10
View File
@@ -0,0 +1,10 @@
# Change Log
## [4.0.1] - 2024-09-06
- #90 update dev dependencies with Typescript to 5
- #89 Adding dependabot
## [4.0.0] - 2024-02-13
- #83 update to node20 as node16 is deprecated
+9 -9
View File
@@ -1,9 +1,9 @@
# Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
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
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
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
+109 -109
View File
@@ -1,109 +1,109 @@
# Kubernetes set context
This action can be used to set cluster context before other actions like [`azure/k8s-deploy`](https://github.com/Azure/k8s-deploy/tree/master) and [`azure/k8s-create-secret`](https://github.com/Azure/k8s-create-secret/tree/master). It should also be used before `kubectl` commands (in script) are run subsequently in the workflow.
It is a requirement to use [`azure/login`](https://github.com/Azure/login/tree/master) in your workflow before using this action when using the `service-account` or `service-principal` methods.
There are three approaches for specifying the deployment target:
- Kubeconfig file provided as input to the action
- Service account approach where the secret associated with the service account is provided as input to the action
- Service principal approach (only applicable for arc cluster) where service principal provided with 'creds' is used as input to action
In all these approaches it is recommended to store these contents (kubeconfig file content or secret content) in a [secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets/).
Refer to the [action metadata file](./action.yml) for details about inputs. Note that different inputs are required for different method and cluster types. Use the below examples as a reference.
## Example usage
### Kubeconfig approach
```yaml
- uses: azure/k8s-set-context@v2
with:
method: kubeconfig
kubeconfig: <your kubeconfig>
context: <context name> # current-context from kubeconfig is used as default
```
**Please note** that the input requires the _contents_ of the kubeconfig file, and not its path.
Following are the ways to fetch kubeconfig file onto your local development machine so that the same can be used in the action input shown above.
#### Azure Kubernetes Service cluster
```bash
az aks get-credentials --name
--resource-group
[--admin]
[--file]
[--overwrite-existing]
[--subscription]
```
Further details can be found in [az aks get-credentials documentation](https://docs.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-get-credentials).
#### Generic Kubernetes cluster
Please refer to documentation on fetching [kubeconfig for any generic K8s cluster](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
### Service account approach
```yaml
- uses: azure/k8s-set-context@v2
with:
method: service-account
k8s-url: <URL of the cluster's API server>
k8s-secret: <secret associated with the service account>
```
For fetching Server URL, execute the following command on your shell:
```bash
kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}'
```
For fetching Secret object required to connect and authenticate with the cluster, the following sequence of commands need to be run:
```bash
kubectl get serviceAccounts <service-account-name> -n <namespace> -o 'jsonpath={.secrets[*].name}'
kubectl get secret <service-account-secret-name> -n <namespace> -o yaml
```
### Service account approach for arc cluster
```yaml
- uses: azure/k8s-set-context@v2
with:
method: service-account
cluster-type: arc
cluster-name: <cluster-name>
resource-group: <resource-group>
token: "${{ secrets.SA_TOKEN }}"
```
### Service principal approach for arc cluster
```yaml
- uses: azure/k8s-set-context@v2
with:
method: service-principal
cluster-type: arc
cluster-name: <cluster-name>
resource-group: <resource-group>
```
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
# Kubernetes set context
This action can be used to set cluster context before other actions like [`azure/k8s-deploy`](https://github.com/Azure/k8s-deploy/tree/master) and [`azure/k8s-create-secret`](https://github.com/Azure/k8s-create-secret/tree/master). It should also be used before `kubectl` commands (in script) are run subsequently in the workflow.
It is a requirement to use [`azure/login`](https://github.com/Azure/login/tree/master) in your workflow before using this action when using the `service-account` or `service-principal` methods.
There are three approaches for specifying the deployment target:
- Kubeconfig file provided as input to the action
- Service account approach where the secret associated with the service account is provided as input to the action
- Service principal approach (only applicable for arc cluster) where service principal provided with 'creds' is used as input to action
In all these approaches it is recommended to store these contents (kubeconfig file content or secret content) in a [secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets/).
Refer to the [action metadata file](./action.yml) for details about inputs. Note that different inputs are required for different method and cluster types. Use the below examples as a reference.
## Example usage
### Kubeconfig approach
```yaml
- uses: azure/k8s-set-context@v4
with:
method: kubeconfig
kubeconfig: <your kubeconfig>
context: <context name> # current-context from kubeconfig is used as default
```
**Please note** that the input requires the _contents_ of the kubeconfig file, and not its path.
Following are the ways to fetch kubeconfig file onto your local development machine so that the same can be used in the action input shown above.
#### Azure Kubernetes Service cluster
```bash
az aks get-credentials --name
--resource-group
[--admin]
[--file]
[--overwrite-existing]
[--subscription]
```
Further details can be found in [az aks get-credentials documentation](https://docs.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-get-credentials).
#### Generic Kubernetes cluster
Please refer to documentation on fetching [kubeconfig for any generic K8s cluster](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
### Service account approach
```yaml
- uses: azure/k8s-set-context@v4
with:
method: service-account
k8s-url: <URL of the cluster's API server>
k8s-secret: <secret associated with the service account>
```
For fetching Server URL, execute the following command on your shell:
```bash
kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}'
```
For fetching Secret object required to connect and authenticate with the cluster, the following sequence of commands need to be run:
```bash
kubectl get serviceAccounts <service-account-name> -n <namespace> -o 'jsonpath={.secrets[*].name}'
kubectl get secret <service-account-secret-name> -n <namespace> -o yaml
```
### Service account approach for arc cluster
```yaml
- uses: azure/k8s-set-context@v4
with:
method: service-account
cluster-type: arc
cluster-name: <cluster-name>
resource-group: <resource-group>
token: '${{ secrets.SA_TOKEN }}'
```
### Service principal approach for arc cluster
```yaml
- uses: azure/k8s-set-context@v4
with:
method: service-principal
cluster-type: arc
cluster-name: <cluster-name>
resource-group: <resource-group>
```
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
+35 -35
View File
@@ -1,35 +1,35 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.1 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.** Instead, please report them to the Microsoft Security Response Center at [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://technet.microsoft.com/en-us/security/dn606155).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
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
This information will help us triage your report more quickly.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.1 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)>) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.** Instead, please report them to the Microsoft Security Response Center at [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://technet.microsoft.com/en-us/security/dn606155).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
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
This information will help us triage your report more quickly.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->
+43 -39
View File
@@ -1,39 +1,43 @@
name: "Kubernetes Set Context"
description: "Set the context of a target Kubernetes cluster and export the kubeconfig which will be used by other actions like azure/k8s-deploy"
inputs:
# Please ensure you have used azure/login in the workflow before this action
cluster-type:
description: "Acceptable values: generic or arc"
required: true
default: "generic"
method:
description: "Acceptable values: kubeconfig or service-account or service-principal"
required: true
default: "kubeconfig"
kubeconfig:
description: "Contents of kubeconfig file"
required: false
context:
description: "If your kubeconfig has multiple contexts, use this field to use a specific context, otherwise the default one would be chosen"
required: false
k8s-url:
description: "Cluster Url"
required: false
k8s-secret:
description: "Service account secret (run kubectl get serviceaccounts <service-account-name> -o yaml and copy the service-account-secret-name)"
required: false
token:
description: "Token extracted from the secret of service account (should be base 64 decoded)"
required: false
resource-group:
description: "Azure resource group name"
required: false
cluster-name:
description: "Azure connected cluster name"
required: false
branding:
color: "blue"
runs:
using: "node12"
main: "lib/run.js"
name: 'Kubernetes Set Context'
description: 'Set the context of a target Kubernetes cluster and export the kubeconfig which is used by subsequent actions'
inputs:
# Please ensure you have used azure/login in the workflow before this action
cluster-type:
description: 'Acceptable values: generic or arc'
required: true
default: 'generic'
method:
description: 'Acceptable values: kubeconfig or service-account or service-principal'
required: true
default: 'kubeconfig'
kubeconfig:
description: 'Contents of kubeconfig file'
required: false
kubeconfig-encoding:
description: 'Encoding of the kubeconfig input. Accepts "plaintext" (default) or "base64".'
required: false
default: 'plaintext'
context:
description: 'If your kubeconfig has multiple contexts, use this field to use a specific context, otherwise the default one would be chosen'
required: false
k8s-url:
description: 'Cluster Url'
required: false
k8s-secret:
description: 'Service account secret (run kubectl get serviceaccounts <service-account-name> -o yaml and copy the service-account-secret-name)'
required: false
token:
description: 'Token extracted from the secret of service account (should be base 64 decoded)'
required: false
resource-group:
description: 'Azure resource group name'
required: false
cluster-name:
description: 'Azure connected cluster name'
required: false
branding:
color: 'blue'
runs:
using: 'node20'
main: 'lib/index.js'
+7
View File
@@ -0,0 +1,7 @@
// babel.config.js
export default {
presets: [
'@babel/preset-env', // For handling ES modules
'@babel/preset-typescript' // For handling TypeScript
]
}
+28 -20
View File
@@ -1,20 +1,28 @@
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,
},
},
};
export default {
restoreMocks: true,
clearMocks: true,
resetMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest', // Use ts-jest for TypeScript files
'^.+\\.js$': 'babel-jest' // Transform TypeScript files
},
transformIgnorePatterns: [
'/node_modules/(?!@kubernetes/client-node)/' // Make sure to transform the Kubernetes client module
],
moduleNameMapper: {
'^.+\\.css$': 'jest-transform-stub' // Handle CSS imports (if any)
},
extensionsToTreatAsEsm: ['.ts', '.tsx'], // Treat TypeScript files as ESM
verbose: true,
coverageThreshold: {
global: {
branches: 0,
functions: 40,
lines: 22,
statements: 22
}
}
}
-84
View File
@@ -1,84 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getArcKubeconfig = exports.KUBECONFIG_LOCATION = void 0;
const core = __importStar(require("@actions/core"));
const io = __importStar(require("@actions/io"));
const method_1 = require("../types/method");
const path = __importStar(require("path"));
const azCommands_1 = require("./azCommands");
const RUNNER_TEMP = process.env["RUNNER_TEMP"] || "";
exports.KUBECONFIG_LOCATION = path.join(RUNNER_TEMP, `arc_kubeconfig_${Date.now()}`);
/**
* Gets the kubeconfig based on provided method for an Arc Kubernetes cluster
* @returns The kubeconfig wrapped in a Promise
*/
function getArcKubeconfig() {
return __awaiter(this, void 0, void 0, function* () {
const resourceGroupName = core.getInput("resource-group", { required: true });
const clusterName = core.getInput("cluster-name", { required: true });
const azPath = yield io.which("az", true);
const method = method_1.parseMethod(core.getInput("method", { required: true }));
yield azCommands_1.runAzCliCommand(azPath, ["extension", "add", "-n", "connectedk8s"]);
switch (method) {
case method_1.Method.SERVICE_ACCOUNT:
const saToken = core.getInput("token", { required: true });
return yield azCommands_1.runAzKubeconfigCommandBlocking(azPath, [
"connectedk8s",
"proxy",
"-n",
clusterName,
"-g",
resourceGroupName,
"--token",
saToken,
"-f",
exports.KUBECONFIG_LOCATION,
], exports.KUBECONFIG_LOCATION);
case method_1.Method.SERVICE_PRINCIPAL:
return yield azCommands_1.runAzKubeconfigCommandBlocking(azPath, [
"connectedk8s",
"proxy",
"-n",
clusterName,
"-g",
resourceGroupName,
"-f",
exports.KUBECONFIG_LOCATION,
], exports.KUBECONFIG_LOCATION);
case undefined:
core.warning("Defaulting to kubeconfig method");
case method_1.Method.KUBECONFIG:
default:
throw Error("Kubeconfig method not supported for Arc cluster");
}
});
}
exports.getArcKubeconfig = getArcKubeconfig;
-67
View File
@@ -1,67 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAzKubeconfigCommandBlocking = exports.runAzCliCommand = void 0;
const fs = __importStar(require("fs"));
const exec_1 = require("@actions/exec");
const child_process_1 = require("child_process");
const AZ_TIMEOUT_SECONDS = 120;
/**
* Executes an az cli command
* @param azPath The path to the az tool
* @param args The arguments to be invoked
* @param options Optional options for the command execution
*/
function runAzCliCommand(azPath, args, options = {}) {
return __awaiter(this, void 0, void 0, function* () {
yield exec_1.exec(azPath, args, options);
});
}
exports.runAzCliCommand = runAzCliCommand;
/**
* Executes an az cli command that will set the kubeconfig
* @param azPath The path to the az tool
* @param args The arguments to be be invoked
* @param kubeconfigPath The path to the kubeconfig that is updated by the command
* @returns The contents of the kubeconfig
*/
function runAzKubeconfigCommandBlocking(azPath, args, kubeconfigPath) {
return __awaiter(this, void 0, void 0, function* () {
const proc = child_process_1.spawn(azPath, args, {
detached: true,
stdio: "ignore",
});
proc.unref();
yield sleep(AZ_TIMEOUT_SECONDS);
return fs.readFileSync(kubeconfigPath).toString();
});
}
exports.runAzKubeconfigCommandBlocking = runAzKubeconfigCommandBlocking;
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
-87
View File
@@ -1,87 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createKubeconfig = exports.getDefaultKubeconfig = void 0;
const core = __importStar(require("@actions/core"));
const jsyaml = __importStar(require("js-yaml"));
const k8sSecret_1 = require("../types/k8sSecret");
const method_1 = require("../types/method");
/**
* Gets the kubeconfig based on provided method for a default Kubernetes cluster
* @returns The kubeconfig
*/
function getDefaultKubeconfig() {
const method = method_1.parseMethod(core.getInput("method", { required: true }));
switch (method) {
case method_1.Method.SERVICE_ACCOUNT: {
const clusterUrl = core.getInput("k8s-url", { required: true });
core.debug("Found clusterUrl. Creating kubeconfig using certificate and token");
const k8sSecret = core.getInput("k8s-secret", {
required: true,
});
const parsedK8sSecret = k8sSecret_1.parseK8sSecret(jsyaml.load(k8sSecret));
const certAuth = parsedK8sSecret.data["ca.crt"];
const token = Buffer.from(parsedK8sSecret.data.token, "base64").toString();
return createKubeconfig(certAuth, token, clusterUrl);
}
case method_1.Method.SERVICE_PRINCIPAL: {
core.warning("Service Principal method not supported for default cluster type");
}
case undefined: {
core.warning("Defaulting to kubeconfig method");
}
default: {
core.debug("Setting context using kubeconfig");
return core.getInput("kubeconfig", { required: true });
}
}
}
exports.getDefaultKubeconfig = getDefaultKubeconfig;
/**
* Creates a kubeconfig and returns the string representation
* @param certAuth The certificate authentication of the cluster
* @param token The user token
* @param clusterUrl The server url of the cluster
* @returns The kubeconfig as a string
*/
function createKubeconfig(certAuth, token, clusterUrl) {
const kubeconfig = {
apiVersion: "v1",
kind: "Config",
clusters: [
{
cluster: {
"certificate-authority-data": certAuth,
server: clusterUrl,
},
},
],
users: [
{
user: {
token: token,
},
},
],
};
return JSON.stringify(kubeconfig);
}
exports.createKubeconfig = createKubeconfig;
-61
View File
@@ -1,61 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const core = __importStar(require("@actions/core"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const cluster_1 = require("./types/cluster");
const utils_1 = require("./utils");
/**
* Sets the Kubernetes context based on supplied action inputs
*/
function run() {
return __awaiter(this, void 0, void 0, function* () {
// get inputs
const clusterType = cluster_1.parseCluster(core.getInput("cluster-type", {
required: true,
}));
const runnerTempDirectory = process.env["RUNNER_TEMP"];
const kubeconfigPath = path.join(runnerTempDirectory, `kubeconfig_${Date.now()}`);
// get kubeconfig and update context
const kubeconfig = yield utils_1.getKubeconfig(clusterType);
const kubeconfigWithContext = utils_1.setContext(kubeconfig);
// output kubeconfig
core.debug(`Writing kubeconfig contents to ${kubeconfigPath}`);
fs.writeFileSync(kubeconfigPath, kubeconfigWithContext);
fs.chmodSync(kubeconfigPath, "600");
core.debug("Setting KUBECONFIG environment variable");
core.exportVariable("KUBECONFIG", kubeconfigPath);
});
}
exports.run = run;
// Run the application
run().catch(core.setFailed);
-14
View File
@@ -1,14 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCluster = exports.Cluster = void 0;
var Cluster;
(function (Cluster) {
Cluster["ARC"] = "arc";
Cluster["GENERIC"] = "generic";
})(Cluster = exports.Cluster || (exports.Cluster = {}));
/**
* Converts a string to the Cluster enum
* @param str The cluster type (case insensitive)
* @returns The Cluster enum or undefined if it can't be parsed
*/
exports.parseCluster = (str) => Cluster[Object.keys(Cluster).filter((k) => Cluster[k].toString().toLowerCase() === str.toLowerCase())[0]];
-41
View File
@@ -1,41 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseK8sSecret = void 0;
const util = __importStar(require("util"));
/**
* Throws an error if an object does not have all required fields to be a K8sSecret
* @param secret
* @returns A type guarded K8sSecret
*/
function parseK8sSecret(secret) {
if (!secret)
throw Error("K8s secret yaml is invalid");
if (!secret.data)
throw k8sSecretMissingFieldError("data");
if (!secret.data.token)
throw k8sSecretMissingFieldError("token");
if (!secret.data["ca.crt"])
throw k8sSecretMissingFieldError("ca.crt");
return secret;
}
exports.parseK8sSecret = parseK8sSecret;
const k8sSecretMissingFieldError = (field) => Error(util.format("K8s secret yaml does not contain %s field", field));
-15
View File
@@ -1,15 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseMethod = exports.Method = void 0;
var Method;
(function (Method) {
Method["KUBECONFIG"] = "kubeconfig";
Method["SERVICE_ACCOUNT"] = "service-account";
Method["SERVICE_PRINCIPAL"] = "service-principal";
})(Method = exports.Method || (exports.Method = {}));
/**
* Converts a string to the Method enum
* @param str The method (case insensitive)
* @returns The Method enum or undefined if it can't be parsed
*/
exports.parseMethod = (str) => Method[Object.keys(Method).filter((k) => Method[k].toString().toLowerCase() === str.toLowerCase())[0]];
-76
View File
@@ -1,76 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setContext = exports.getKubeconfig = void 0;
const core = __importStar(require("@actions/core"));
const client_node_1 = require("@kubernetes/client-node");
const default_1 = require("./kubeconfigs/default");
const arc_1 = require("./kubeconfigs/arc");
const cluster_1 = require("./types/cluster");
/**
* Gets the kubeconfig based on Kubernetes cluster type
* @param type The cluster type for the kubeconfig (defaults to generic)
* @returns A promise of the kubeconfig
*/
function getKubeconfig(type) {
return __awaiter(this, void 0, void 0, function* () {
switch (type) {
case cluster_1.Cluster.ARC: {
return yield arc_1.getArcKubeconfig();
}
case undefined: {
core.warning("Cluster type not recognized. Defaulting to generic.");
}
default: {
return default_1.getDefaultKubeconfig();
}
}
});
}
exports.getKubeconfig = getKubeconfig;
/**
* Sets the context by updating the kubeconfig
* @param kubeconfig The kubeconfig
* @returns Updated kubeconfig with the context
*/
function setContext(kubeconfig) {
const context = core.getInput("context");
if (!context) {
core.debug("Can't set context because context is unspecified.");
return kubeconfig;
}
// load current kubeconfig
const kc = new client_node_1.KubeConfig();
kc.loadFromString(kubeconfig);
// update kubeconfig
kc.setCurrentContext(context);
return kc.exportConfig();
}
exports.setContext = setContext;
+11254 -15012
View File
File diff suppressed because it is too large Load Diff
+44 -33
View File
@@ -1,33 +1,44 @@
{
"name": "k8s-set-context-action",
"version": "1.0.0",
"private": true,
"main": "lib/run.js",
"scripts": {
"build": "tsc --outDir ./lib --rootDir ./src",
"test": "jest",
"test-coverage": "jest --coverage"
},
"keywords": [
"actions",
"node",
"setup"
],
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/tool-cache": "^1.0.0",
"@kubernetes/client-node": "^0.16.0",
"js-yaml": "^3.13.1"
},
"devDependencies": {
"@types/jest": "^25.2.2",
"@types/js-yaml": "^4.0.4",
"@types/node": "^12.0.4",
"jest": "^26.6.3",
"ts-jest": "^25.5.1",
"typescript": "3.9.2"
}
}
{
"name": "k8s-set-context-action",
"version": "4.0.0",
"private": true,
"main": "lib/index.js",
"type": "module",
"scripts": {
"prebuild": "npm i @vercel/ncc",
"build": "ncc build src/run.ts -o lib",
"test": "jest",
"test-coverage": "jest --coverage",
"format": "prettier --write .",
"format-check": "prettier --check .",
"prepare": "husky"
},
"keywords": [
"actions",
"node",
"setup"
],
"author": "GitHub",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.3",
"@kubernetes/client-node": "^1.3.0",
"husky": "^9.1.7",
"js-yaml": "^4.1.0"
},
"devDependencies": {
"@babel/preset-env": "^7.28.0",
"@babel/preset-typescript": "^7.27.1",
"@types/jest": "^30.0.0",
"@types/js-yaml": "^4.0.9",
"@types/node": "^24.0.15",
"@vercel/ncc": "^0.38.3",
"babel-jest": "^30.0.4",
"jest": "^30.0.4",
"prettier": "^3.6.2",
"ts-jest": "^29.4.0",
"typescript": "^5.8.3"
}
}
+30
View File
@@ -0,0 +1,30 @@
import {getRequiredInputError} from '../tests/util'
import {run} from './action'
import fs from 'fs'
import * as utils from './utils'
describe('Run', () => {
it('throws error without cluster type', async () => {
await expect(run()).rejects.toThrow(getRequiredInputError('cluster-type'))
})
it('writes kubeconfig and sets context', async () => {
const kubeconfig = 'kubeconfig'
process.env['INPUT_CLUSTER-TYPE'] = 'default'
process.env['RUNNER_TEMP'] = '/sample/path'
jest
.spyOn(utils, 'getKubeconfig')
.mockImplementation(async () => kubeconfig)
jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {})
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
jest.spyOn(utils, 'setContext').mockImplementation(() => kubeconfig)
expect(await run())
expect(utils.getKubeconfig).toHaveBeenCalled()
expect(fs.writeFileSync).toHaveBeenCalled()
expect(fs.chmodSync).toHaveBeenCalled()
expect(utils.setContext).toHaveBeenCalled()
})
})
+33
View File
@@ -0,0 +1,33 @@
import * as core from '@actions/core'
import * as path from 'path'
import * as fs from 'fs'
import {Cluster, parseCluster} from './types/cluster'
import {setContext, getKubeconfig} from './utils'
/**
* Sets the Kubernetes context based on supplied action inputs
*/
export async function run() {
// get inputs
const clusterType: Cluster | undefined = parseCluster(
core.getInput('cluster-type', {
required: true
})
)
const runnerTempDirectory: string = process.env['RUNNER_TEMP']
const kubeconfigPath: string = path.join(
runnerTempDirectory,
`kubeconfig_${Date.now()}`
)
// get kubeconfig and update context
const kubeconfig: string = await getKubeconfig(clusterType)
const kubeconfigWithContext: string = setContext(kubeconfig)
// output kubeconfig
core.debug(`Writing kubeconfig contents to ${kubeconfigPath}`)
fs.writeFileSync(kubeconfigPath, kubeconfigWithContext)
fs.chmodSync(kubeconfigPath, '600')
core.debug('Setting KUBECONFIG environment variable')
core.exportVariable('KUBECONFIG', kubeconfigPath)
}
+94 -94
View File
@@ -1,103 +1,103 @@
import * as actions from "@actions/exec";
import * as io from "@actions/io";
import { getRequiredInputError } from "../../tests/util";
import { getArcKubeconfig, KUBECONFIG_LOCATION } from "./arc";
import * as az from "./azCommands";
import * as actions from '@actions/exec'
import * as io from '@actions/io'
import {getRequiredInputError} from '../../tests/util'
import {getArcKubeconfig, KUBECONFIG_LOCATION} from './arc'
import * as az from './azCommands'
describe("Arc kubeconfig", () => {
test("it throws error without resource group", async () => {
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError("resource-group")
);
});
test("it throws error without cluster name", async () => {
process.env["INPUT_RESOURCE-GROUP"] = "group";
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError("cluster-name")
);
});
describe("runs az cli commands", () => {
const group = "group";
const name = "name";
const path = "path";
const kubeconfig = "kubeconfig";
beforeEach(() => {
process.env["INPUT_RESOURCE-GROUP"] = group;
process.env["INPUT_CLUSTER-NAME"] = name;
jest.spyOn(io, "which").mockImplementation(async () => path);
jest.spyOn(az, "runAzCliCommand").mockImplementation(async () => {});
jest
.spyOn(az, "runAzKubeconfigCommandBlocking")
.mockImplementation(async () => kubeconfig);
});
it("throws an error without method", async () => {
describe('Arc kubeconfig', () => {
test('it throws error without resource group', async () => {
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError("method")
);
});
getRequiredInputError('resource-group')
)
})
test('it throws error without cluster name', async () => {
process.env['INPUT_RESOURCE-GROUP'] = 'group'
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError('cluster-name')
)
})
describe('runs az cli commands', () => {
const group = 'group'
const name = 'name'
const path = 'path'
const kubeconfig = 'kubeconfig'
describe("service account method", () => {
beforeEach(() => {
process.env["INPUT_METHOD"] = "service-account";
});
process.env['INPUT_RESOURCE-GROUP'] = group
process.env['INPUT_CLUSTER-NAME'] = name
it("throws an error without token", async () => {
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError("token")
);
});
jest.spyOn(io, 'which').mockImplementation(async () => path)
jest.spyOn(az, 'runAzCliCommand').mockImplementation(async () => {})
jest
.spyOn(az, 'runAzKubeconfigCommandBlocking')
.mockImplementation(async () => kubeconfig)
})
it("gets the kubeconfig", async () => {
const token = "token";
process.env["INPUT_TOKEN"] = token;
it('throws an error without method', async () => {
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError('method')
)
})
expect(await getArcKubeconfig()).toBe(kubeconfig);
expect(az.runAzKubeconfigCommandBlocking).toHaveBeenCalledWith(
path,
[
"connectedk8s",
"proxy",
"-n",
name,
"-g",
group,
"--token",
token,
"-f",
KUBECONFIG_LOCATION,
],
KUBECONFIG_LOCATION
);
});
});
describe('service account method', () => {
beforeEach(() => {
process.env['INPUT_METHOD'] = 'service-account'
})
describe("service principal method", () => {
beforeEach(() => {
process.env["INPUT_METHOD"] = "service-principal";
});
it('throws an error without token', async () => {
await expect(getArcKubeconfig()).rejects.toThrow(
getRequiredInputError('token')
)
})
it("gets the kubeconfig", async () => {
expect(await getArcKubeconfig()).toBe(kubeconfig);
expect(az.runAzKubeconfigCommandBlocking).toHaveBeenCalledWith(
path,
[
"connectedk8s",
"proxy",
"-n",
name,
"-g",
group,
"-f",
KUBECONFIG_LOCATION,
],
KUBECONFIG_LOCATION
);
});
});
});
});
it('gets the kubeconfig', async () => {
const token = 'token'
process.env['INPUT_TOKEN'] = token
expect(await getArcKubeconfig()).toBe(kubeconfig)
expect(az.runAzKubeconfigCommandBlocking).toHaveBeenCalledWith(
path,
[
'connectedk8s',
'proxy',
'-n',
name,
'-g',
group,
'--token',
token,
'-f',
KUBECONFIG_LOCATION
],
KUBECONFIG_LOCATION
)
})
})
describe('service principal method', () => {
beforeEach(() => {
process.env['INPUT_METHOD'] = 'service-principal'
})
it('gets the kubeconfig', async () => {
expect(await getArcKubeconfig()).toBe(kubeconfig)
expect(az.runAzKubeconfigCommandBlocking).toHaveBeenCalledWith(
path,
[
'connectedk8s',
'proxy',
'-n',
name,
'-g',
group,
'-f',
KUBECONFIG_LOCATION
],
KUBECONFIG_LOCATION
)
})
})
})
})
+56 -56
View File
@@ -1,68 +1,68 @@
import * as core from "@actions/core";
import * as io from "@actions/io";
import { Method, parseMethod } from "../types/method";
import * as path from "path";
import { runAzCliCommand, runAzKubeconfigCommandBlocking } from "./azCommands";
import * as core from '@actions/core'
import * as io from '@actions/io'
import {Method, parseMethod} from '../types/method'
import * as path from 'path'
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(
RUNNER_TEMP,
`arc_kubeconfig_${Date.now()}`
);
RUNNER_TEMP,
`arc_kubeconfig_${Date.now()}`
)
/**
* Gets the kubeconfig based on provided method for an Arc Kubernetes cluster
* @returns The kubeconfig wrapped in a Promise
*/
export async function getArcKubeconfig(): Promise<string> {
const resourceGroupName = core.getInput("resource-group", { required: true });
const clusterName = core.getInput("cluster-name", { required: true });
const azPath = await io.which("az", true);
const resourceGroupName = core.getInput('resource-group', {required: true})
const clusterName = core.getInput('cluster-name', {required: true})
const azPath = await io.which('az', true)
const method: Method | undefined = parseMethod(
core.getInput("method", { required: true })
);
const method: Method | undefined = parseMethod(
core.getInput('method', {required: true})
)
await runAzCliCommand(azPath, ["extension", "add", "-n", "connectedk8s"]);
await runAzCliCommand(azPath, ['extension', 'add', '-n', 'connectedk8s'])
switch (method) {
case Method.SERVICE_ACCOUNT:
const saToken = core.getInput("token", { required: true });
return await runAzKubeconfigCommandBlocking(
azPath,
[
"connectedk8s",
"proxy",
"-n",
clusterName,
"-g",
resourceGroupName,
"--token",
saToken,
"-f",
KUBECONFIG_LOCATION,
],
KUBECONFIG_LOCATION
);
case Method.SERVICE_PRINCIPAL:
return await runAzKubeconfigCommandBlocking(
azPath,
[
"connectedk8s",
"proxy",
"-n",
clusterName,
"-g",
resourceGroupName,
"-f",
KUBECONFIG_LOCATION,
],
KUBECONFIG_LOCATION
);
case undefined:
core.warning("Defaulting to kubeconfig method");
case Method.KUBECONFIG:
default:
throw Error("Kubeconfig method not supported for Arc cluster");
}
switch (method) {
case Method.SERVICE_ACCOUNT:
const saToken = core.getInput('token', {required: true})
return await runAzKubeconfigCommandBlocking(
azPath,
[
'connectedk8s',
'proxy',
'-n',
clusterName,
'-g',
resourceGroupName,
'--token',
saToken,
'-f',
KUBECONFIG_LOCATION
],
KUBECONFIG_LOCATION
)
case Method.SERVICE_PRINCIPAL:
return await runAzKubeconfigCommandBlocking(
azPath,
[
'connectedk8s',
'proxy',
'-n',
clusterName,
'-g',
resourceGroupName,
'-f',
KUBECONFIG_LOCATION
],
KUBECONFIG_LOCATION
)
case undefined:
core.warning('Defaulting to kubeconfig method')
case Method.KUBECONFIG:
default:
throw Error('Kubeconfig method not supported for Arc cluster')
}
}
+11 -11
View File
@@ -1,14 +1,14 @@
import * as actions from "@actions/exec";
import { runAzCliCommand } from "./azCommands";
import * as actions from '@actions/exec'
import {runAzCliCommand} from './azCommands'
describe("Az commands", () => {
test("it runs an az cli command", async () => {
const path = "path";
const args = ["args"];
describe('Az commands', () => {
test('it runs an az cli command', async () => {
const path = 'path'
const args = ['args']
jest.spyOn(actions, "exec").mockImplementation(async () => 0);
jest.spyOn(actions, 'exec').mockImplementation(async () => 0)
expect(await runAzCliCommand(path, args));
expect(actions.exec).toBeCalledWith(path, args, {});
});
});
expect(await runAzCliCommand(path, args))
expect(actions.exec).toHaveBeenCalledWith(path, args, {})
})
})
+20 -20
View File
@@ -1,9 +1,9 @@
import * as fs from "fs";
import { ExecOptions } from "@actions/exec/lib/interfaces";
import { exec } from "@actions/exec";
import { spawn } from "child_process";
import * as fs from 'fs'
import {ExecOptions} from '@actions/exec/lib/interfaces'
import {exec} from '@actions/exec'
import {spawn} from 'child_process'
const AZ_TIMEOUT_SECONDS: number = 120;
const AZ_TIMEOUT_SECONDS: number = 120
/**
* Executes an az cli command
@@ -12,11 +12,11 @@ const AZ_TIMEOUT_SECONDS: number = 120;
* @param options Optional options for the command execution
*/
export async function runAzCliCommand(
azPath: string,
args: string[],
options: ExecOptions = {}
azPath: string,
args: string[],
options: ExecOptions = {}
) {
await exec(azPath, args, options);
await exec(azPath, args, options)
}
/**
* Executes an az cli command that will set the kubeconfig
@@ -26,19 +26,19 @@ export async function runAzCliCommand(
* @returns The contents of the kubeconfig
*/
export async function runAzKubeconfigCommandBlocking(
azPath: string,
args: string[],
kubeconfigPath: string
azPath: string,
args: string[],
kubeconfigPath: string
): Promise<string> {
const proc = spawn(azPath, args, {
detached: true,
stdio: "ignore",
});
proc.unref();
const proc = spawn(azPath, args, {
detached: true,
stdio: 'ignore'
})
proc.unref()
await sleep(AZ_TIMEOUT_SECONDS);
return fs.readFileSync(kubeconfigPath).toString();
await sleep(AZ_TIMEOUT_SECONDS)
return fs.readFileSync(kubeconfigPath).toString()
}
const sleep = (seconds: number) =>
new Promise((resolve) => setTimeout(resolve, seconds * 1000));
new Promise((resolve) => setTimeout(resolve, seconds * 1000))
+172 -109
View File
@@ -1,128 +1,191 @@
import * as fs from "fs";
import { getRequiredInputError } from "../../tests/util";
import { createKubeconfig, getDefaultKubeconfig } from "./default";
import * as fs from 'fs'
import * as core from '@actions/core'
import {getRequiredInputError} from '../../tests/util'
import {createKubeconfig, getDefaultKubeconfig} from './default'
describe("Default kubeconfig", () => {
test("it creates a kubeconfig with proper format", () => {
const certAuth = "certAuth";
const token = "token";
const clusterUrl = "clusterUrl";
describe('Default kubeconfig', () => {
test('it creates a kubeconfig with proper format', () => {
const certAuth = 'certAuth'
const token = 'token'
const clusterUrl = 'clusterUrl'
const kc = createKubeconfig(certAuth, token, clusterUrl);
const expected = JSON.stringify({
apiVersion: "v1",
kind: "Config",
clusters: [
{
cluster: {
"certificate-authority-data": certAuth,
server: clusterUrl,
},
},
],
users: [
{
user: {
token: token,
},
},
],
});
const kc = createKubeconfig(certAuth, token, clusterUrl)
const expected = JSON.stringify({
apiVersion: 'v1',
kind: 'Config',
clusters: [
{
name: 'default',
cluster: {
server: clusterUrl,
'certificate-authority-data': certAuth,
'insecure-skip-tls-verify': false
}
}
],
users: [{name: 'default-user', user: {token}}],
contexts: [
{
name: 'loaded-context',
context: {
cluster: 'default',
user: 'default-user',
name: 'loaded-context'
}
}
],
preferences: {},
'current-context': 'loaded-context'
})
expect(kc).toBe(expected)
})
expect(kc).toBe(expected);
});
test("it throws error without method", () => {
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError("method")
);
});
describe("default method", () => {
beforeEach(() => {
process.env["INPUT_METHOD"] = "default";
});
test("it throws error without kubeconfig", () => {
test('it throws error without method', () => {
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError("kubeconfig")
);
});
getRequiredInputError('method')
)
})
test("it gets default config through kubeconfig input", () => {
const kc = "example kc";
process.env["INPUT_KUBECONFIG"] = kc;
describe('default method', () => {
beforeEach(() => {
process.env['INPUT_METHOD'] = 'default'
})
expect(getDefaultKubeconfig()).toBe(kc);
});
});
test('it throws error without kubeconfig', () => {
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError('kubeconfig')
)
})
test("it defaults to default method", () => {
process.env["INPUT_METHOD"] = "unknown";
test('it gets default config through kubeconfig input', () => {
const kc = 'example kc'
process.env['INPUT_KUBECONFIG'] = kc
const kc = "example kc";
process.env["INPUT_KUBECONFIG"] = kc;
expect(getDefaultKubeconfig()).toBe(kc)
})
expect(getDefaultKubeconfig()).toBe(kc);
});
test('returns kubeconfig as plaintext when encoding is plaintext', () => {
const kc = 'example kc'
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
if (name === 'method') return 'default'
if (name === 'kubeconfig-encoding') return 'plaintext'
if (name === 'kubeconfig') return kc
return ''
})
expect(getDefaultKubeconfig()).toBe(kc)
})
test("it defaults to default method from service-principal", () => {
process.env["INPUT_METHOD"] = "service-principal";
test('it gets default config through base64 kubeconfig input', () => {
const kc = 'example kc'
const base64Kc = Buffer.from(kc, 'utf-8').toString('base64')
const kc = "example kc";
process.env["INPUT_KUBECONFIG"] = kc;
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
if (name === 'method') return 'default'
if (name === 'kubeconfig-encoding') return 'base64'
if (name === 'kubeconfig') return base64Kc
return ''
})
expect(getDefaultKubeconfig()).toBe(kc);
});
expect(getDefaultKubeconfig()).toBe(kc)
})
describe("service-account method", () => {
beforeEach(() => {
process.env["INPUT_METHOD"] = "service-account";
});
test('it throws error for unknown kubeconfig-encoding', () => {
const kc = 'example kc'
const unknownEncoding = 'foobar'
test("it throws error without cluster url", () => {
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError("k8s-url")
);
});
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
if (name === 'method') return 'default'
if (name === 'kubeconfig-encoding') return unknownEncoding
if (name === 'kubeconfig') return kc
return ''
})
test("it throws error without k8s secret", () => {
process.env["INPUT_K8S-URL"] = "url";
expect(() => getDefaultKubeconfig()).toThrow(
"Invalid kubeconfig-encoding: 'foobar'. Must be 'plaintext' or 'base64'."
)
})
})
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError("k8s-secret")
);
});
test('it defaults to default method', () => {
process.env['INPUT_METHOD'] = 'unknown'
test("it gets kubeconfig through service-account", () => {
const k8sUrl = "https://testing-dns-4za.hfp.earth.azmk8s.io:443";
const token = "ZXlKaGJHY2lPcUpTVXpJMU5pSX=";
const cert = "LS0tLS1CRUdJTiBDRWyUSUZJQ";
const k8sSecret = fs.readFileSync("tests/sample-secret.yml").toString();
const kc = 'example kc'
process.env['INPUT_KUBECONFIG'] = kc
process.env["INPUT_K8S-URL"] = k8sUrl;
process.env["INPUT_K8S-SECRET"] = k8sSecret;
expect(getDefaultKubeconfig()).toBe(kc)
})
const expectedConfig = JSON.stringify({
apiVersion: "v1",
kind: "Config",
clusters: [
{
cluster: {
"certificate-authority-data": cert,
server: k8sUrl,
},
},
],
users: [
{
user: {
token: Buffer.from(token, "base64").toString(),
},
},
],
});
expect(getDefaultKubeconfig()).toBe(expectedConfig);
});
});
});
test('it defaults to default method from service-principal', () => {
process.env['INPUT_METHOD'] = 'service-principal'
const kc = 'example kc'
process.env['INPUT_KUBECONFIG'] = kc
expect(getDefaultKubeconfig()).toBe(kc)
})
describe('service-account method', () => {
beforeEach(() => {
process.env['INPUT_METHOD'] = 'service-account'
})
test('it throws error without cluster url', () => {
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError('k8s-url')
)
})
test('it throws error without k8s secret', () => {
process.env['INPUT_K8S-URL'] = 'url'
expect(() => getDefaultKubeconfig()).toThrow(
getRequiredInputError('k8s-secret')
)
})
test('it gets kubeconfig through service-account', () => {
const k8sUrl = 'https://testing-dns-4za.hfp.earth.azmk8s.io:443'
const token = 'ZXlKaGJHY2lPcUpTVXpJMU5pSX='
const cert = 'LS0tLS1CRUdJTiBDRWyUSUZJQ'
const k8sSecret = fs.readFileSync('tests/sample-secret.yml').toString()
process.env['INPUT_K8S-URL'] = k8sUrl
process.env['INPUT_K8S-SECRET'] = k8sSecret
const expectedConfig = JSON.stringify({
apiVersion: 'v1',
kind: 'Config',
clusters: [
{
name: 'default',
cluster: {
server: k8sUrl,
'certificate-authority-data': cert,
'insecure-skip-tls-verify': false
}
}
],
users: [
{
name: 'default-user',
user: {token: Buffer.from(token, 'base64').toString()}
}
],
contexts: [
{
name: 'loaded-context',
context: {
cluster: 'default',
user: 'default-user',
name: 'loaded-context'
}
}
],
preferences: {},
'current-context': 'loaded-context'
})
expect(getDefaultKubeconfig()).toBe(expectedConfig)
})
})
})
+74 -58
View File
@@ -1,49 +1,72 @@
import * as core from "@actions/core";
import * as jsyaml from "js-yaml";
import { K8sSecret, parseK8sSecret } from "../types/k8sSecret";
import { Method, parseMethod } from "../types/method";
import * as core from '@actions/core'
import * as jsyaml from 'js-yaml'
import {KubeConfig} from '@kubernetes/client-node'
import {K8sSecret, parseK8sSecret} from '../types/k8sSecret'
import {Method, parseMethod} from '../types/method'
/**
* Gets the kubeconfig based on provided method for a default Kubernetes cluster
* @returns The kubeconfig
*/
export function getDefaultKubeconfig(): string {
const method: Method | undefined = parseMethod(
core.getInput("method", { required: true })
);
const method: Method | undefined = parseMethod(
core.getInput('method', {required: true})
)
switch (method) {
case Method.SERVICE_ACCOUNT: {
const clusterUrl = core.getInput("k8s-url", { required: true });
core.debug(
"Found clusterUrl. Creating kubeconfig using certificate and token"
);
switch (method) {
case Method.SERVICE_ACCOUNT: {
const clusterUrl = core.getInput('k8s-url', {required: true})
core.debug(
'Found clusterUrl. Creating kubeconfig using certificate and token'
)
const k8sSecret: string = core.getInput("k8s-secret", {
required: true,
});
const parsedK8sSecret: K8sSecret = parseK8sSecret(jsyaml.load(k8sSecret));
const certAuth: string = parsedK8sSecret.data["ca.crt"];
const token: string = Buffer.from(
parsedK8sSecret.data.token,
"base64"
).toString();
const k8sSecret: string = core.getInput('k8s-secret', {
required: true
})
const parsedK8sSecret: K8sSecret = parseK8sSecret(
jsyaml.load(k8sSecret)
)
const certAuth: string = parsedK8sSecret.data['ca.crt']
const token: string = Buffer.from(
parsedK8sSecret.data.token,
'base64'
).toString()
return createKubeconfig(certAuth, token, clusterUrl);
}
case Method.SERVICE_PRINCIPAL: {
core.warning(
"Service Principal method not supported for default cluster type"
);
}
case undefined: {
core.warning("Defaulting to kubeconfig method");
}
default: {
core.debug("Setting context using kubeconfig");
return core.getInput("kubeconfig", { required: true });
}
}
return createKubeconfig(certAuth, token, clusterUrl)
}
case Method.SERVICE_PRINCIPAL: {
core.warning(
'Service Principal method not supported for default cluster type'
)
}
case undefined: {
core.warning('Defaulting to kubeconfig method')
}
default: {
core.debug('Setting context using kubeconfig')
enum Encoding {
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
}
}
}
/**
@@ -54,29 +77,22 @@ export function getDefaultKubeconfig(): string {
* @returns The kubeconfig as a string
*/
export function createKubeconfig(
certAuth: string,
token: string,
clusterUrl: string
certAuth: string,
token: string,
clusterUrl: string
): string {
const kubeconfig = {
apiVersion: "v1",
kind: "Config",
clusters: [
const kc = new KubeConfig()
kc.loadFromClusterAndUser(
{
cluster: {
"certificate-authority-data": certAuth,
server: clusterUrl,
},
name: 'default',
server: clusterUrl,
caData: certAuth,
skipTLSVerify: false
},
],
users: [
{
user: {
token: token,
},
},
],
};
return JSON.stringify(kubeconfig);
name: 'default-user',
token
}
)
return kc.exportConfig()
}
-30
View File
@@ -1,30 +0,0 @@
import { getRequiredInputError } from "../tests/util";
import { run } from "./run";
import fs from "fs";
import * as utils from "./utils";
describe("Run", () => {
it("throws error without cluster type", async () => {
await expect(run()).rejects.toThrow(getRequiredInputError("cluster-type"));
});
it("writes kubeconfig and sets context", async () => {
const kubeconfig = "kubeconfig";
process.env["INPUT_CLUSTER-TYPE"] = "default";
process.env["RUNNER_TEMP"] = "/sample/path";
jest
.spyOn(utils, "getKubeconfig")
.mockImplementation(async () => kubeconfig);
jest.spyOn(fs, "writeFileSync").mockImplementation(() => {});
jest.spyOn(fs, "chmodSync").mockImplementation(() => {});
jest.spyOn(utils, "setContext").mockImplementation(() => kubeconfig);
expect(await run());
expect(utils.getKubeconfig).toHaveBeenCalled();
expect(fs.writeFileSync).toHaveBeenCalled();
expect(fs.chmodSync).toHaveBeenCalled();
expect(utils.setContext).toHaveBeenCalled();
});
});
+3 -34
View File
@@ -1,36 +1,5 @@
import * as core from "@actions/core";
import * as path from "path";
import * as fs from "fs";
import { Cluster, parseCluster } from "./types/cluster";
import { setContext, getKubeconfig } from "./utils";
/**
* Sets the Kubernetes context based on supplied action inputs
*/
export async function run() {
// get inputs
const clusterType: Cluster | undefined = parseCluster(
core.getInput("cluster-type", {
required: true,
})
);
const runnerTempDirectory: string = process.env["RUNNER_TEMP"];
const kubeconfigPath: string = path.join(
runnerTempDirectory,
`kubeconfig_${Date.now()}`
);
// get kubeconfig and update context
const kubeconfig: string = await getKubeconfig(clusterType);
const kubeconfigWithContext: string = setContext(kubeconfig);
// output kubeconfig
core.debug(`Writing kubeconfig contents to ${kubeconfigPath}`);
fs.writeFileSync(kubeconfigPath, kubeconfigWithContext);
fs.chmodSync(kubeconfigPath, "600");
core.debug("Setting KUBECONFIG environment variable");
core.exportVariable("KUBECONFIG", kubeconfigPath);
}
import {run} from './action'
import * as core from '@actions/core'
// Run the application
run().catch(core.setFailed);
run().catch(core.setFailed)
+20 -20
View File
@@ -1,24 +1,24 @@
import { Cluster, parseCluster } from "./cluster";
import {Cluster, parseCluster} from './cluster'
describe("Cluster type", () => {
test("it has required values", () => {
const vals = <any>Object.values(Cluster);
expect(vals.includes("arc")).toBe(true);
expect(vals.includes("generic")).toBe(true);
});
describe('Cluster type', () => {
test('it has required values', () => {
const vals = <any>Object.values(Cluster)
expect(vals.includes('arc')).toBe(true)
expect(vals.includes('generic')).toBe(true)
})
test("it can parse valid values from a string", () => {
expect(parseCluster("arc")).toBe(Cluster.ARC);
expect(parseCluster("Arc")).toBe(Cluster.ARC);
expect(parseCluster("ARC")).toBe(Cluster.ARC);
test('it can parse valid values from a string', () => {
expect(parseCluster('arc')).toBe(Cluster.ARC)
expect(parseCluster('Arc')).toBe(Cluster.ARC)
expect(parseCluster('ARC')).toBe(Cluster.ARC)
expect(parseCluster("generic")).toBe(Cluster.GENERIC);
expect(parseCluster("Generic")).toBe(Cluster.GENERIC);
expect(parseCluster("GENERIC")).toBe(Cluster.GENERIC);
});
expect(parseCluster('generic')).toBe(Cluster.GENERIC)
expect(parseCluster('Generic')).toBe(Cluster.GENERIC)
expect(parseCluster('GENERIC')).toBe(Cluster.GENERIC)
})
test("it will return undefined if it can't parse values from a string", () => {
expect(parseCluster("invalid")).toBe(undefined);
expect(parseCluster("unsupportedType")).toBe(undefined);
});
});
test("it will return undefined if it can't parse values from a string", () => {
expect(parseCluster('invalid')).toBe(undefined)
expect(parseCluster('unsupportedType')).toBe(undefined)
})
})
+7 -7
View File
@@ -1,6 +1,6 @@
export enum Cluster {
ARC = "arc",
GENERIC = "generic",
ARC = 'arc',
GENERIC = 'generic'
}
/**
@@ -9,8 +9,8 @@ export enum Cluster {
* @returns The Cluster enum or undefined if it can't be parsed
*/
export const parseCluster = (str: string): Cluster | undefined =>
Cluster[
Object.keys(Cluster).filter(
(k) => Cluster[k].toString().toLowerCase() === str.toLowerCase()
)[0] as keyof typeof Cluster
];
Cluster[
Object.keys(Cluster).filter(
(k) => Cluster[k].toString().toLowerCase() === str.toLowerCase()
)[0] as keyof typeof Cluster
]
+28 -28
View File
@@ -1,33 +1,33 @@
import { parseK8sSecret, K8sSecret } from "./k8sSecret";
import {parseK8sSecret, K8sSecret} from './k8sSecret'
describe("K8sSecret type", () => {
describe("Parsing from any", () => {
test("it returns a type guarded secret", () => {
const secret = { data: { token: "token", "ca.crt": "cert" } };
expect(() => parseK8sSecret(secret)).not.toThrow();
});
describe('K8sSecret type', () => {
describe('Parsing from any', () => {
test('it returns a type guarded secret', () => {
const secret = {data: {token: 'token', 'ca.crt': 'cert'}}
expect(() => parseK8sSecret(secret)).not.toThrow()
})
test("it throws an error when secret not provided", () => {
expect(() => parseK8sSecret(undefined)).toThrow();
});
test('it throws an error when secret not provided', () => {
expect(() => parseK8sSecret(undefined)).toThrow()
})
test("it throws an error when there is no data field", () => {
const secret = {};
expect(() => parseK8sSecret(secret)).toThrow();
});
test('it throws an error when there is no data field', () => {
const secret = {}
expect(() => parseK8sSecret(secret)).toThrow()
})
test("it throws an error when there is no token", () => {
const secret = {
data: {
"ca.crt": "cert",
},
};
expect(() => parseK8sSecret(secret)).toThrow();
});
test('it throws an error when there is no token', () => {
const secret = {
data: {
'ca.crt': 'cert'
}
}
expect(() => parseK8sSecret(secret)).toThrow()
})
test("it throws an error when there is no ca.crt field", () => {
const secret = { data: { token: "token" } };
expect(() => parseK8sSecret(secret)).toThrow();
});
});
});
test('it throws an error when there is no ca.crt field', () => {
const secret = {data: {token: 'token'}}
expect(() => parseK8sSecret(secret)).toThrow()
})
})
})
+11 -11
View File
@@ -1,10 +1,10 @@
import * as util from "util";
import * as util from 'util'
export interface K8sSecret {
data: {
token: string;
"ca.crt": string;
};
data: {
token: string
'ca.crt': string
}
}
/**
@@ -13,13 +13,13 @@ export interface K8sSecret {
* @returns A type guarded K8sSecret
*/
export function parseK8sSecret(secret: any): K8sSecret {
if (!secret) throw Error("K8s secret yaml is invalid");
if (!secret.data) throw k8sSecretMissingFieldError("data");
if (!secret.data.token) throw k8sSecretMissingFieldError("token");
if (!secret.data["ca.crt"]) throw k8sSecretMissingFieldError("ca.crt");
if (!secret) throw Error('K8s secret yaml is invalid')
if (!secret.data) throw k8sSecretMissingFieldError('data')
if (!secret.data.token) throw k8sSecretMissingFieldError('token')
if (!secret.data['ca.crt']) throw k8sSecretMissingFieldError('ca.crt')
return secret as K8sSecret;
return secret as K8sSecret
}
const k8sSecretMissingFieldError = (field: string): Error =>
Error(util.format("K8s secret yaml does not contain %s field", field));
Error(util.format('K8s secret yaml does not contain %s field', field))
+24 -24
View File
@@ -1,29 +1,29 @@
import { Method, parseMethod } from "./method";
import {Method, parseMethod} from './method'
describe("Method type", () => {
test("it has required values", () => {
const vals = <any>Object.values(Method);
expect(vals.includes("kubeconfig")).toBe(true);
expect(vals.includes("service-account")).toBe(true);
expect(vals.includes("service-principal")).toBe(true);
});
describe('Method type', () => {
test('it has required values', () => {
const vals = <any>Object.values(Method)
expect(vals.includes('kubeconfig')).toBe(true)
expect(vals.includes('service-account')).toBe(true)
expect(vals.includes('service-principal')).toBe(true)
})
test("it can parse valid values from a string", () => {
expect(parseMethod("kubeconfig")).toBe(Method.KUBECONFIG);
expect(parseMethod("Kubeconfig")).toBe(Method.KUBECONFIG);
expect(parseMethod("KUBECONFIG")).toBe(Method.KUBECONFIG);
test('it can parse valid values from a string', () => {
expect(parseMethod('kubeconfig')).toBe(Method.KUBECONFIG)
expect(parseMethod('Kubeconfig')).toBe(Method.KUBECONFIG)
expect(parseMethod('KUBECONFIG')).toBe(Method.KUBECONFIG)
expect(parseMethod("service-account")).toBe(Method.SERVICE_ACCOUNT);
expect(parseMethod("Service-Account")).toBe(Method.SERVICE_ACCOUNT);
expect(parseMethod("SERVICE-ACCOUNT")).toBe(Method.SERVICE_ACCOUNT);
expect(parseMethod('service-account')).toBe(Method.SERVICE_ACCOUNT)
expect(parseMethod('Service-Account')).toBe(Method.SERVICE_ACCOUNT)
expect(parseMethod('SERVICE-ACCOUNT')).toBe(Method.SERVICE_ACCOUNT)
expect(parseMethod("service-principal")).toBe(Method.SERVICE_PRINCIPAL);
expect(parseMethod("Service-Principal")).toBe(Method.SERVICE_PRINCIPAL);
expect(parseMethod("SERVICE-PRINCIPAL")).toBe(Method.SERVICE_PRINCIPAL);
});
expect(parseMethod('service-principal')).toBe(Method.SERVICE_PRINCIPAL)
expect(parseMethod('Service-Principal')).toBe(Method.SERVICE_PRINCIPAL)
expect(parseMethod('SERVICE-PRINCIPAL')).toBe(Method.SERVICE_PRINCIPAL)
})
test("it will return undefined if it can't parse values from a string", () => {
expect(parseMethod("invalid")).toBe(undefined);
expect(parseMethod("unsupportedType")).toBe(undefined);
});
});
test("it will return undefined if it can't parse values from a string", () => {
expect(parseMethod('invalid')).toBe(undefined)
expect(parseMethod('unsupportedType')).toBe(undefined)
})
})
+8 -8
View File
@@ -1,7 +1,7 @@
export enum Method {
KUBECONFIG = "kubeconfig",
SERVICE_ACCOUNT = "service-account",
SERVICE_PRINCIPAL = "service-principal",
KUBECONFIG = 'kubeconfig',
SERVICE_ACCOUNT = 'service-account',
SERVICE_PRINCIPAL = 'service-principal'
}
/**
@@ -10,8 +10,8 @@ export enum Method {
* @returns The Method enum or undefined if it can't be parsed
*/
export const parseMethod = (str: string): Method | undefined =>
Method[
Object.keys(Method).filter(
(k) => Method[k].toString().toLowerCase() === str.toLowerCase()
)[0] as keyof typeof Method
];
Method[
Object.keys(Method).filter(
(k) => Method[k].toString().toLowerCase() === str.toLowerCase()
)[0] as keyof typeof Method
]
+38 -38
View File
@@ -1,47 +1,47 @@
import fs from "fs";
import * as arc from "./kubeconfigs/arc";
import * as def from "./kubeconfigs/default";
import { Cluster } from "./types/cluster";
import { getKubeconfig, setContext } from "./utils";
import fs from 'fs'
import * as arc from './kubeconfigs/arc'
import * as def from './kubeconfigs/default'
import {Cluster} from './types/cluster'
import {getKubeconfig, setContext} from './utils'
describe("Utils", () => {
describe("get kubeconfig", () => {
test("it gets arc kubeconfig when type is arc", async () => {
const arcKubeconfig = "arckubeconfig";
jest
.spyOn(arc, "getArcKubeconfig")
.mockImplementation(async () => arcKubeconfig);
describe('Utils', () => {
describe('get kubeconfig', () => {
test('it gets arc kubeconfig when type is arc', async () => {
const arcKubeconfig = 'arckubeconfig'
jest
.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 () => {
const defaultKubeconfig = "arckubeconfig";
jest
.spyOn(def, "getDefaultKubeconfig")
.mockImplementation(() => defaultKubeconfig);
test('it defaults to default kubeconfig', async () => {
const defaultKubeconfig = 'arckubeconfig'
jest
.spyOn(def, 'getDefaultKubeconfig')
.mockImplementation(() => defaultKubeconfig)
expect(await getKubeconfig(undefined)).toBe(defaultKubeconfig);
expect(await getKubeconfig(Cluster.GENERIC)).toBe(defaultKubeconfig);
});
});
expect(await getKubeconfig(undefined)).toBe(defaultKubeconfig)
expect(await getKubeconfig(Cluster.GENERIC)).toBe(defaultKubeconfig)
})
})
describe("set context", () => {
const kc = fs.readFileSync("tests/sample-kubeconfig.yml").toString();
describe('set context', () => {
const kc = fs.readFileSync('tests/sample-kubeconfig.yml').toString()
test("it doesn't change kubeconfig without context", () => {
expect(setContext(kc)).toBe(kc);
});
test("it doesn't change kubeconfig without context", () => {
expect(setContext(kc)).toBe(kc)
})
test("it writes the context to the kubeconfig", () => {
process.env["INPUT_CONTEXT"] = "example";
test('it writes the context to the kubeconfig', () => {
process.env['INPUT_CONTEXT'] = 'example'
const received = JSON.parse(setContext(kc));
const expectedKc = JSON.parse(
fs.readFileSync("tests/expected-kubeconfig.json").toString()
);
const received = JSON.parse(setContext(kc))
const expectedKc = JSON.parse(
fs.readFileSync('tests/expected-kubeconfig.json').toString()
)
expect(received).toMatchObject(expectedKc);
});
});
});
expect(received).toMatchObject(expectedKc)
})
})
})
+29 -29
View File
@@ -1,9 +1,9 @@
import * as core from "@actions/core";
import * as fs from "fs";
import { KubeConfig } from "@kubernetes/client-node";
import { getDefaultKubeconfig } from "./kubeconfigs/default";
import { getArcKubeconfig } from "./kubeconfigs/arc";
import { Cluster } from "./types/cluster";
import * as core from '@actions/core'
import * as fs from 'fs'
import {KubeConfig} from '@kubernetes/client-node'
import {getDefaultKubeconfig} from './kubeconfigs/default'
import {getArcKubeconfig} from './kubeconfigs/arc'
import {Cluster} from './types/cluster'
/**
* Gets the kubeconfig based on Kubernetes cluster type
@@ -11,19 +11,19 @@ import { Cluster } from "./types/cluster";
* @returns A promise of the kubeconfig
*/
export async function getKubeconfig(
type: Cluster | undefined
type: Cluster | undefined
): Promise<string> {
switch (type) {
case Cluster.ARC: {
return await getArcKubeconfig();
}
case undefined: {
core.warning("Cluster type not recognized. Defaulting to generic.");
}
default: {
return getDefaultKubeconfig();
}
}
switch (type) {
case Cluster.ARC: {
return await getArcKubeconfig()
}
case undefined: {
core.warning('Cluster type not recognized. Defaulting to generic.')
}
default: {
return getDefaultKubeconfig()
}
}
}
/**
@@ -32,17 +32,17 @@ export async function getKubeconfig(
* @returns Updated kubeconfig with the context
*/
export function setContext(kubeconfig: string): string {
const context: string = core.getInput("context");
if (!context) {
core.debug("Can't set context because context is unspecified.");
return kubeconfig;
}
const context: string = core.getInput('context')
if (!context) {
core.debug("Can't set context because context is unspecified.")
return kubeconfig
}
// load current kubeconfig
const kc = new KubeConfig();
kc.loadFromString(kubeconfig);
// load current kubeconfig
const kc = new KubeConfig()
kc.loadFromString(kubeconfig)
// update kubeconfig
kc.setCurrentContext(context);
return kc.exportConfig();
// update kubeconfig
kc.setCurrentContext(context)
return kc.exportConfig()
}
+23 -23
View File
@@ -1,27 +1,27 @@
{
"apiVersion": "v1",
"kind": "Config",
"clusters": [
{
"name": "example",
"cluster": {
"server": "http://example.com:8080",
"insecure-skip-tls-verify": false
"apiVersion": "v1",
"kind": "Config",
"clusters": [
{
"name": "example",
"cluster": {
"server": "http://example.com:8080",
"insecure-skip-tls-verify": false
}
}
}
],
"users": [],
"contexts": [
{
"name": "example",
"context": {
"cluster": "example",
"name": "example",
"user": "example",
"namespace": "example"
],
"users": [],
"contexts": [
{
"name": "example",
"context": {
"cluster": "example",
"name": "example",
"user": "example",
"namespace": "example"
}
}
}
],
"preferences": {},
"current-context": "example"
],
"preferences": {},
"current-context": "example"
}
+8 -8
View File
@@ -1,12 +1,12 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: http://example.com:8080
name: example
- cluster:
server: http://example.com:8080
name: example
contexts:
- context:
cluster: example
namespace: example
user: example
name: example
- context:
cluster: example
namespace: example
user: example
name: example
+30 -30
View File
@@ -1,35 +1,35 @@
apiVersion: v1
data:
ca.crt: LS0tLS1CRUdJTiBDRWyUSUZJQ
namespace: ZGVmBXUsLdA==
token: ZXlKaGJHY2lPcUpTVXpJMU5pSX=
ca.crt: LS0tLS1CRUdJTiBDRWyUSUZJQ
namespace: ZGVmBXUsLdA==
token: ZXlKaGJHY2lPcUpTVXpJMU5pSX=
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: e1414a3z-22fe-48d1-ab9e-18e4a5b91c
creationTimestamp: "2020-03-02T06:40:31Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:ca.crt: {}
f:namespace: {}
f:token: {}
f:metadata:
f:annotations:
.: {}
f:kubernetes.io/service-account.name: {}
f:kubernetes.io/service-account.uid: {}
f:type: {}
manager: kube-controller-manager
operation: Update
time: "2020-03-02T06:40:31Z"
name: default-token-bl8ra
namespace: default
resourceVersion: "278"
selfLink: /api/v1/namespaces/default/secrets/default-token-bl8ra
uid: e6d8b21b-2e3a-4606-98za-54fb44fdc
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: e1414a3z-22fe-48d1-ab9e-18e4a5b91c
creationTimestamp: '2020-03-02T06:40:31Z'
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:ca.crt: {}
f:namespace: {}
f:token: {}
f:metadata:
f:annotations:
.: {}
f:kubernetes.io/service-account.name: {}
f:kubernetes.io/service-account.uid: {}
f:type: {}
manager: kube-controller-manager
operation: Update
time: '2020-03-02T06:40:31Z'
name: default-token-bl8ra
namespace: default
resourceVersion: '278'
selfLink: /api/v1/namespaces/default/secrets/default-token-bl8ra
uid: e6d8b21b-2e3a-4606-98za-54fb44fdc
type: kubernetes.io/service-account-token
+1 -1
View File
@@ -4,4 +4,4 @@
* @returns Error with explanation message
*/
export const getRequiredInputError = (inputName) =>
Error(`Input required and not supplied: ${inputName}`);
Error(`Input required and not supplied: ${inputName}`)
+15 -8
View File
@@ -1,8 +1,15 @@
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"esModuleInterop": true
},
"exclude": ["node_modules", "tests", "src/**/*.test.ts"]
}
{
"compilerOptions": {
"baseUrl": ".",
"module": "ESNext", // or "NodeNext" depending on your setup
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"paths": {
"@actions/core": ["node_modules/@actions/core"],
"@kubernetes/client-node": ["node_modules/@kubernetes/client-node"]
}
},
"exclude": ["node_modules", "tests", "src/**/*.test.ts"]
}