├── .eslintignore
├── .eslintrc.json
├── .github
├── dependabot.yml
└── workflows
│ └── test.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── LICENSE
├── README.md
├── action.yml
├── dist
└── index.js
├── package-lock.json
├── package.json
├── src
└── main.ts
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 | lib/
3 | node_modules/
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["jest", "@typescript-eslint"],
3 | "extends": ["plugin:github/es6"],
4 | "parser": "@typescript-eslint/parser",
5 | "parserOptions": {
6 | "ecmaVersion": 9,
7 | "sourceType": "module",
8 | "project": "./tsconfig.json"
9 | },
10 | "rules": {
11 | "eslint-comments/no-use": "off",
12 | "import/no-namespace": "off",
13 | "no-unused-vars": "off",
14 | "@typescript-eslint/no-unused-vars": "error",
15 | "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
16 | "@typescript-eslint/no-require-imports": "error",
17 | "@typescript-eslint/array-type": "error",
18 | "@typescript-eslint/await-thenable": "error",
19 | "@typescript-eslint/ban-ts-ignore": "error",
20 | "camelcase": "off",
21 | "@typescript-eslint/camelcase": "error",
22 | "@typescript-eslint/class-name-casing": "error",
23 | "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
24 | "@typescript-eslint/func-call-spacing": ["error", "never"],
25 | "@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
26 | "@typescript-eslint/no-array-constructor": "error",
27 | "@typescript-eslint/no-empty-interface": "error",
28 | "@typescript-eslint/no-explicit-any": "error",
29 | "@typescript-eslint/no-extraneous-class": "error",
30 | "@typescript-eslint/no-for-in-array": "error",
31 | "@typescript-eslint/no-inferrable-types": "error",
32 | "@typescript-eslint/no-misused-new": "error",
33 | "@typescript-eslint/no-namespace": "error",
34 | "@typescript-eslint/no-non-null-assertion": "warn",
35 | "@typescript-eslint/no-object-literal-type-assertion": "error",
36 | "@typescript-eslint/no-unnecessary-qualifier": "error",
37 | "@typescript-eslint/no-unnecessary-type-assertion": "error",
38 | "@typescript-eslint/no-useless-constructor": "error",
39 | "@typescript-eslint/no-var-requires": "error",
40 | "@typescript-eslint/prefer-for-of": "warn",
41 | "@typescript-eslint/prefer-function-type": "warn",
42 | "@typescript-eslint/prefer-includes": "error",
43 | "@typescript-eslint/prefer-interface": "error",
44 | "@typescript-eslint/prefer-string-starts-ends-with": "error",
45 | "@typescript-eslint/promise-function-async": "error",
46 | "@typescript-eslint/require-array-sort-compare": "error",
47 | "@typescript-eslint/restrict-plus-operands": "error",
48 | "semi": "off",
49 | "@typescript-eslint/semi": ["error", "never"],
50 | "@typescript-eslint/type-annotation-spacing": "error",
51 | "@typescript-eslint/unbound-method": "error"
52 | },
53 | "env": {
54 | "node": true,
55 | "es6": true,
56 | "jest/globals": true
57 | }
58 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: "action-setup-kube-tools Test"
2 | on:
3 | # Schedule run: Runs at 00:00, only on Mondays (Japan Time)
4 | schedule:
5 | - cron: '0 15 * * 1'
6 | pull_request:
7 | push:
8 | branches:
9 | - master
10 | - 'releases/*'
11 | - 'v*'
12 |
13 | jobs:
14 | build: # make sure build/ci work properly
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v4
18 | - uses: actions/setup-node@v4
19 | with:
20 | node-version: '20.x'
21 | - run: |
22 | npm install
23 | npm run all
24 | test1:
25 | runs-on: ubuntu-latest
26 | steps:
27 | - uses: actions/checkout@v4
28 | - uses: ./
29 | id: setup
30 | - run: |
31 | kubectl version --client
32 | kustomize version
33 | helm version
34 | kubeval --version
35 | kubeconform -v
36 | conftest --version
37 | yq --version
38 | rancher --version
39 | tilt version
40 | skaffold version
41 | kube-score version
42 | - run: |
43 | kubectl=${{steps.setup.outputs.kubectl-path}}
44 | kustomize=${{steps.setup.outputs.kustomize-path}}
45 | helm=${{steps.setup.outputs.helm-path}}
46 | kubeval=${{steps.setup.outputs.kubeval-path}}
47 | kubeconform=${{steps.setup.outputs.kubeconform-path}}
48 | conftest=${{steps.setup.outputs.conftest-path}}
49 | yq=${{steps.setup.outputs.yq-path}}
50 | rancher=${{steps.setup.outputs.rancher-path}}
51 | tilt=${{steps.setup.outputs.tilt-path}}
52 | skaffold=${{steps.setup.outputs.skaffold-path}}
53 | kubescore=${{steps.setup.outputs.kube-score-path}}
54 |
55 | ${kubectl} version --client
56 | ${kustomize} version
57 | ${helm} version
58 | ${kubeval} --version
59 | ${kubeconform} -v
60 | ${conftest} --version
61 | ${yq} --version
62 | ${rancher} --version
63 | ${tilt} version
64 | ${skaffold} version
65 | ${kubescore} version
66 |
67 | test2:
68 | runs-on: ubuntu-latest
69 | steps:
70 | - uses: actions/checkout@v4
71 | - uses: ./
72 | with:
73 | kubectl: '1.17.1'
74 | kustomize: '3.7.0'
75 | helm: '3.2.4'
76 | kubeval: '0.16.1'
77 | kubeconform: '0.5.0'
78 | conftest: '0.18.2'
79 | yq: '4.7.1'
80 | rancher: '2.4.10'
81 | tilt: '0.18.11'
82 | skaffold: '1.20.0'
83 | kube-score: '1.10.1'
84 | id: setup
85 | - run: |
86 | kubectl version --client
87 | kustomize version
88 | helm version
89 | kubeval --version
90 | kubeconform -v
91 | conftest --version
92 | yq --version
93 | rancher --version
94 | tilt version
95 | skaffold version
96 | kube-score version
97 | - run: |
98 | kubectl=${{steps.setup.outputs.kubectl-path}}
99 | kustomize=${{steps.setup.outputs.kustomize-path}}
100 | helm=${{steps.setup.outputs.helm-path}}
101 | kubeval=${{steps.setup.outputs.kubeval-path}}
102 | kubeconform=${{steps.setup.outputs.kubeconform-path}}
103 | conftest=${{steps.setup.outputs.conftest-path}}
104 | yq=${{steps.setup.outputs.yq-path}}
105 | rancher=${{steps.setup.outputs.rancher-path}}
106 | tilt=${{steps.setup.outputs.tilt-path}}
107 | skaffold=${{steps.setup.outputs.skaffold-path}}
108 | kubescore=${{steps.setup.outputs.kube-score-path}}
109 |
110 | ${kubectl} version --client
111 | ${kustomize} version
112 | ${helm} version
113 | ${kubeval} --version
114 | ${kubeconform} -v
115 | ${conftest} --version
116 | ${yq} --version
117 | ${rancher} --version
118 | ${tilt} version
119 | ${skaffold} version
120 | ${kubescore} version
121 |
122 | test3:
123 | runs-on: ubuntu-latest
124 | steps:
125 | - uses: actions/checkout@v4
126 | - uses: ./
127 | with:
128 | arch-type: 'amd64'
129 | setup-tools: |
130 | kubectl
131 | helm
132 | kustomize
133 | skaffold
134 | kubectl: '1.17.1'
135 | helm: '3.2.4'
136 | kustomize: '3.7.0'
137 | skaffold: '1.20.0'
138 | id: setup
139 | - run: |
140 | kubectl version --client
141 | kustomize version
142 | helm version
143 | skaffold version
144 | - run: |
145 | kubectl=${{steps.setup.outputs.kubectl-path}}
146 | kustomize=${{steps.setup.outputs.kustomize-path}}
147 | helm=${{steps.setup.outputs.helm-path}}
148 | kubeval=${{steps.setup.outputs.kubeval-path}}
149 | kubeconform=${{steps.setup.outputs.kubeconform-path}}
150 | conftest=${{steps.setup.outputs.conftest-path}}
151 | yq=${{steps.setup.outputs.yq-path}}
152 | rancher=${{steps.setup.outputs.rancher-path}}
153 | tilt=${{steps.setup.outputs.tilt-path}}
154 | skaffold=${{steps.setup.outputs.skaffold-path}}
155 | kubescore=${{steps.setup.outputs.kube-score-path}}
156 |
157 | if [ ! -z ${kubectl} ]; then
158 | ${kubectl} version --client
159 | fi
160 | if [ ! -z ${kustomize} ]; then
161 | ${kustomize} version
162 | fi
163 | if [ ! -z ${helm} ]; then
164 | ${helm} version
165 | fi
166 | if [ ! -z ${kubeval} ]; then
167 | ${kubeval} --version
168 | fi
169 | if [ ! -z ${kubeconform} ]; then
170 | ${kubeconform} -v
171 | fi
172 | if [ ! -z ${conftest} ]; then
173 | ${conftest} --version
174 | fi
175 | if [ ! -z ${yq} ]; then
176 | ${yq} --version
177 | fi
178 | if [ ! -z ${rancher} ]; then
179 | ${rancher} --version
180 | fi
181 | if [ ! -z ${tilt} ]; then
182 | ${tilt} version
183 | fi
184 | if [ ! -z ${skaffold} ]; then
185 | ${skaffold} version
186 | fi
187 | if [ ! -z ${kubescore} ]; then
188 | ${kubescore} version
189 | fi
190 |
191 | # ARM test
192 | test4:
193 | runs-on: ubuntu-latest
194 | steps:
195 | - uses: actions/checkout@v4
196 | - uses: ./
197 | with:
198 | arch-type: 'arm64'
199 | id: setup
200 | - run: |
201 | kubectl=${{steps.setup.outputs.kubectl-path}}
202 | kustomize=${{steps.setup.outputs.kustomize-path}}
203 | helm=${{steps.setup.outputs.helm-path}}
204 | kubeval=${{steps.setup.outputs.kubeval-path}}
205 | kubeconform=${{steps.setup.outputs.kubeconform-path}}
206 | conftest=${{steps.setup.outputs.conftest-path}}
207 | yq=${{steps.setup.outputs.yq-path}}
208 | rancher=${{steps.setup.outputs.rancher-path}}
209 | tilt=${{steps.setup.outputs.tilt-path}}
210 | skaffold=${{steps.setup.outputs.skaffold-path}}
211 | kubescore=${{steps.setup.outputs.kube-score-path}}
212 |
213 | if [ ! -z ${kubectl} ]; then
214 | file ${kubectl}
215 | fi
216 | if [ ! -z ${kustomize} ]; then
217 | file ${kustomize}
218 | fi
219 | if [ ! -z ${helm} ]; then
220 | file ${helm}
221 | fi
222 | if [ ! -z ${kubeval} ]; then
223 | file ${kubeval}
224 | fi
225 | if [ ! -z ${kubeconform} ]; then
226 | file ${kubeconform}
227 | fi
228 | if [ ! -z ${conftest} ]; then
229 | file ${conftest}
230 | fi
231 | if [ ! -z ${yq} ]; then
232 | file ${yq}
233 | fi
234 | if [ ! -z ${rancher} ]; then
235 | file ${rancher}
236 | fi
237 | if [ ! -z ${tilt} ]; then
238 | file ${tilt}
239 | fi
240 | if [ ! -z ${skaffold} ]; then
241 | file ${skaffold}
242 | fi
243 | if [ ! -z ${kubescore} ]; then
244 | file ${kubescore}
245 | fi
246 |
247 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependency directory
2 | node_modules
3 |
4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # Diagnostic reports (https://nodejs.org/api/report.html)
14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
15 |
16 | # Runtime data
17 | pids
18 | *.pid
19 | *.seed
20 | *.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 | lib-cov
24 |
25 | # Coverage directory used by tools like istanbul
26 | coverage
27 | *.lcov
28 |
29 | # nyc test coverage
30 | .nyc_output
31 |
32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
33 | .grunt
34 |
35 | # Bower dependency directory (https://bower.io/)
36 | bower_components
37 |
38 | # node-waf configuration
39 | .lock-wscript
40 |
41 | # Compiled binary addons (https://nodejs.org/api/addons.html)
42 | build/Release
43 |
44 | # Dependency directories
45 | jspm_packages/
46 |
47 | # TypeScript v1 declaration files
48 | typings/
49 |
50 | # TypeScript cache
51 | *.tsbuildinfo
52 |
53 | # Optional npm cache directory
54 | .npm
55 |
56 | # Optional eslint cache
57 | .eslintcache
58 |
59 | # Optional REPL history
60 | .node_repl_history
61 |
62 | # Output of 'npm pack'
63 | *.tgz
64 |
65 | # Yarn Integrity file
66 | .yarn-integrity
67 |
68 | # dotenv environment variables file
69 | .env
70 | .env.test
71 |
72 | # parcel-bundler cache (https://parceljs.org/)
73 | .cache
74 |
75 | # next.js build output
76 | .next
77 |
78 | # nuxt.js build output
79 | .nuxt
80 |
81 | # vuepress build output
82 | .vuepress/dist
83 |
84 | # Serverless directories
85 | .serverless/
86 |
87 | # FuseBox cache
88 | .fusebox/
89 |
90 | # DynamoDB Local files
91 | .dynamodb/
92 |
93 | # OS metadata
94 | .DS_Store
95 | Thumbs.db
96 |
97 | # Ignore built ts files
98 | __tests__/runner/*
99 | lib/**/*
100 |
101 | /t/*
102 | /*/t/*
103 |
104 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist/
2 | lib/
3 | node_modules/
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": false,
6 | "singleQuote": true,
7 | "trailingComma": "none",
8 | "bracketSpacing": false,
9 | "arrowParens": "avoid",
10 | "parser": "typescript"
11 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2024 Yoichi Kawasaki and contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/yokawasa/action-setup-kube-tools/actions/workflows/test.yml)
2 |
3 | # action-setup-kube-tools
4 | A GitHub Action that setup Kubernetes tools (kubectl, kustomize, helm, kubeconform, conftest, yq, rancher, tilt, skaffold, kube-score) and cache them on the runner. It is like a typescript version of [stefanprodan/kube-tools](https://github.com/stefanprodan/kube-tools) with no command input param, but as compared with [it](https://github.com/stefanprodan/kube-tools), it's **very fast** as it installs the tools asynchronously.
5 |
6 | ## Usage
7 |
8 | ### Inputs
9 |
10 | |Parameter|Required|Default Value|Description|
11 | |:--:|:--:|:--:|:--|
12 | |`fail-fast`|`false`|`true`| the action immediately fails when it fails to download (ie. due to a bad version) |
13 | |`arch-type`|`false`|`amd64`| The processor architecture type of the tool binary to setup. Supported types are only `amd64` and `arm64`. If a type other than the supported Types is specified, it will be treated as `amd64`.|
14 | |`setup-tools`|`false`|`""`|List of tool name to setup. By default, the action download and setup all supported Kubernetes tools. By specifying `setup-tools` you can choose which tools the action setup. Supported separator is `return` in multi-line string. Supported tools are `kubectl`, `kustomize`, `helm`, `helmv3`, `kubeval`, `conftest`, `yq`, `rancher`, `tilt`, `skaffold`, `kube-score`|
15 | |`kubectl`|`false`|`1.24.10`| kubectl version. kubectl vesion can be found [here](https://github.com/kubernetes/kubernetes/releases)|
16 | |`kustomize`|`false`|`5.0.0`| kustomize version. kustomize vesion can be found [here](https://github.com/kubernetes-sigs/kustomize/releases)|
17 | |`helm`|`false`|`3.11.1`| helm version. helm vesion can be found [here](https://github.com/helm/helm/releases)|
18 | |`kubeval`|`false`|`0.16.1`| kubeval version (must be **0.16.1+**). kubeval vesion can be found [here](https://github.com/instrumenta/kubeval/releases).
NOTE: this parameter is deprecating as `kubeval` is no longer maintained. A good replacement is [kubeconform](https://github.com/yannh/kubeconform). See also [this](https://github.com/instrumenta/kubeval) for more details.|
19 | |`kubeconform`|`false`|`0.5.0`| kubeconform version. kubeconform vesion can be found [here](https://github.com/yannh/kubeconform/releases)|
20 | |`conftest`|`false`|`0.39.0`| conftest version. conftest vesion can be found [here](https://github.com/open-policy-agent/conftest/releases)|
21 | |`yq`|`false`|`4.30.7`| yq version. yq vesion can be found [here](https://github.com/mikefarah/yq/releases/)|
22 | |`rancher`|`false`|`2.7.0`| Rancher CLI version. Rancher CLI vesion can be found [here](https://github.com/rancher/cli/releases)|
23 | |`tilt`|`false`|`0.31.2`| Tilt version. Tilt vesion can be found [here](https://github.com/tilt-dev/tilt/releases)|
24 | |`skaffold`|`false`|`2.1.0`| Skaffold version. Skaffold vesion can be found [here](https://github.com/GoogleContainerTools/skaffold/releases)|
25 | |`kube-score`|`false`|`1.16.1`| kube-score version. kube-score vesion can be found [here](https://github.com/zegl/kube-score/releases)|
26 |
27 | > - Supported Environments: Linux
28 | > - From v0.7.0, the action supports tool version 'v' prefix. Prior to v0.7.0, the action only accept the tool version without 'v' prefix but from v0.7.0 the action automatically add/remove the prefix as necessary
29 | >
30 | ### Outputs
31 | |Parameter|Description|
32 | |:--:|:--|
33 | |`kubectl-path`| kubectl command path if the action setup the tool, otherwise empty string |
34 | |`kustomize-path`| kustomize command path if the action setup the tool, otherwise empty string |
35 | |`helm-path`| helm command path if the action setup the tool, otherwise empty string |
36 | |`kubeval-path`| kubeval command path if the action setup the tool, otherwise empty string |
37 | |`kubeconform-path`| kubeconform command path if the action setup the tool, otherwise empty string |
38 | |`conftest-path`| conftest command path if the action setup the tool, otherwise empty string |
39 | |`yq-path`| yq command path if the action setup the tool, otherwise empty string |
40 | |`rancher-path`| rancher command path if the action setup the tool, otherwise empty string |
41 | |`tilt-path`| rancher command path if the action setup the tool, otherwise empty string |
42 | |`skaffold-path`| rancher command path if the action setup the tool, otherwise empty string |
43 | |`kube-score-path:`| rancher command path if the action setup the tool, otherwise empty string |
44 |
45 | ### Sample Workflow
46 |
47 | Specific versions for the commands can be setup by adding inputs parameters like this:
48 |
49 | ```yaml
50 | test:
51 | runs-on: ubuntu-latest
52 | steps:
53 | - uses: actions/checkout@v2
54 | - uses: yokawasa/action-setup-kube-tools@v0.11.2
55 | with:
56 | kubectl: '1.25'
57 | kustomize: '5.0.0'
58 | helm: '3.11.1'
59 | kubeconform: '0.5.0'
60 | conftest: '0.39.0'
61 | rancher: '2.7.0'
62 | tilt: '0.31.2'
63 | skaffold: '2.1.0'
64 | kube-score: '1.16.1'
65 | - run: |
66 | kubectl version --client
67 | kustomize version
68 | helm version
69 | kubeconform -v
70 | conftest --version
71 | yq --version
72 | rancher --version
73 | tilt version
74 | skaffold version
75 | kube-score version
76 | ```
77 |
78 | Default versions for the commands will be setup if you don't give any inputs like this:
79 |
80 | ```yaml
81 | test:
82 | runs-on: ubuntu-latest
83 | steps:
84 | - uses: actions/checkout@v2
85 | - uses: yokawasa/action-setup-kube-tools@v0.11.2
86 | - run: |
87 | kubectl version --client
88 | kustomize version
89 | helm version
90 | kubeconform -v
91 | conftest --version
92 | yq --version
93 | rancher --version
94 | tilt version
95 | skaffold version
96 | kube-score version
97 | ```
98 |
99 | By specifying setup-tools you can choose which tools the action setup. Supported separator is return in multi-line string like this
100 |
101 | ```yaml
102 | test:
103 | runs-on: ubuntu-latest
104 | steps:
105 | - uses: actions/checkout@v2
106 | - uses: yokawasa/action-setup-kube-tools@v0.11.2
107 | with:
108 | setup-tools: |
109 | kubectl
110 | helm
111 | kustomize
112 | skaffold
113 | kubectl: '1.25'
114 | helm: '3.11.1'
115 | kustomize: '5.0.0'
116 | skaffold: '2.1.0'
117 | - run: |
118 | kubectl version --client
119 | kustomize version
120 | helm version
121 | skaffold version
122 | ```
123 |
124 | By specifying arch-type you can choose the processor architecture type of the tool binary to setup. Supported types are only `amd64`(default) and `arm64`.
125 |
126 | ```yaml
127 | test:
128 | steps:
129 | - uses: actions/checkout@v4
130 | - uses: yokawasa/action-setup-kube-tools@v0.11.2
131 | with:
132 | arch-type: 'arm64'
133 | setup-tools: |
134 | kubectl
135 | helm
136 | kustomize
137 | skaffold
138 | kubectl: '1.25'
139 | helm: '3.11.1'
140 | kustomize: '5.0.0'
141 | skaffold: '2.1.0'
142 | - run: |
143 | kubectl version --client
144 | kustomize version
145 | helm version
146 | skaffold version
147 | ```
148 |
149 |
150 | ## Developing the action
151 |
152 | Install the dependencies
153 | ```bash
154 | npm install
155 | ```
156 |
157 | Build the typescript and package it for distribution by running [ncc](https://github.com/zeit/ncc)
158 | ```bash
159 | npm run build && npm run format && npm run lint && npm run pack
160 | ```
161 |
162 | Finally push the results
163 | ```
164 | git add dist
165 | git commit -a -m "prod dependencies"
166 | git push origin releases/v0.11.2
167 | ```
168 |
169 | ## References
170 |
171 | - https://kubernetes.io/releases/
172 | - https://github.com/kubernetes-sigs/kustomize/releases
173 | - https://github.com/helm/helm/releases
174 | - https://helm.sh/docs/topics/version_skew/
175 | - https://github.com/instrumenta/kubeval/releases
176 | - https://github.com/open-policy-agent/conftest/releases
177 | - https://github.com/mikefarah/yq/releases
178 | - https://github.com/rancher/cli/releases
179 | - https://github.com/tilt-dev/tilt/releases
180 | - https://github.com/GoogleContainerTools/skaffold/releases
181 | - https://github.com/zegl/kube-score/releases
182 |
183 | ## Contributing
184 | Bug reports and pull requests are welcome on GitHub at https://github.com/yokawasa/action-setup-kube-tools
185 |
186 | ## Changelog
187 |
188 | Please see the [list of releases](https://github.com/yokawasa/action-setup-kube-tools/releases) for information on changes between releases.
189 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: 'Setup Kubernetes Tools'
2 | description: 'Setup Kubernetes tools: kubectl, kustomize, helm, kubeconform, conftest, yq, rancher, tilt, skaffold, kube-score'
3 | author: 'Yoichi Kawasaki @yokawasa'
4 | inputs:
5 | fail-fast:
6 | required: false
7 | default: 'true'
8 | description: 'the action immediately fails when it fails to download (ie. due to a bad version)'
9 | arch-type:
10 | required: false
11 | default: 'amd64'
12 | description: 'The processor architecture type of the tool binary to setup. Supported types are only "amd64" and "arm64". If a type other than the supported Types is specified, it will be treated as "amd64"'
13 | setup-tools:
14 | required: false
15 | default: ''
16 | description: 'List of tool name to setup. By default, the action download and setup all supported Kubernetes tools. By specifying "setup-tools" you can choose which tools the action setup. Supported separator is return in multi-line string. Supported tools are "kubectl", "kustomize", "helm", "helmv3", "kubeval", "conftest", "yq", "rancher", "tilt", "skaffold", "kube-score"'
17 | kubectl:
18 | required: false
19 | default: '1.24.10'
20 | description: 'kubectl version'
21 | kustomize:
22 | required: false
23 | default: '5.0.0'
24 | description: 'kustomize version'
25 | helm:
26 | required: false
27 | default: '3.11.1'
28 | description: 'helm version'
29 | kubeval:
30 | required: false
31 | default: '0.16.1'
32 | description: 'kubeval version'
33 | kubeconform:
34 | required: false
35 | default: '0.5.0'
36 | description: 'kubeconform version'
37 | conftest:
38 | required: false
39 | default: '0.39.0'
40 | description: 'conftest version'
41 | yq:
42 | required: false
43 | default: '4.30.7'
44 | description: 'yq version'
45 | rancher:
46 | required: false
47 | default: '2.7.0'
48 | description: 'rancher cli version'
49 | tilt:
50 | required: false
51 | default: '0.31.2'
52 | description: 'tilt version'
53 | skaffold:
54 | required: false
55 | default: '2.1.0'
56 | description: 'skaffold version'
57 | kube-score:
58 | required: false
59 | default: '1.16.1'
60 | description: 'kube-score version'
61 | outputs:
62 | kubectl-path:
63 | description: 'kubectl command path if the action setup the tool, otherwise empty string'
64 | kustomize-path:
65 | description: 'kustomize command path if the action setup the tool, otherwise empty string'
66 | helm-path:
67 | description: 'helm command path if the action setup the tool, otherwise empty string'
68 | kubeval-path:
69 | description: 'kubeval command path if the action setup the tool, otherwise empty string'
70 | conftest-path:
71 | description: 'conftest command path if the action setup the tool, otherwise empty string'
72 | yq-path:
73 | description: 'yq command path if the action setup the tool, otherwise empty string'
74 | rancher-path:
75 | description: 'rancher cli command path if the action setup the tool, otherwise empty string'
76 | tilt-path:
77 | description: 'tilt command path if the action setup the tool, otherwise empty string'
78 | skaffold-path:
79 | description: 'skaffold command path if the action setup the tool, otherwise empty string'
80 | kube-score-path:
81 | description: 'kube-score command path if the action setup the tool, otherwise empty string'
82 | branding:
83 | icon: 'terminal'
84 | color: 'blue'
85 | runs:
86 | using: 'node20'
87 | main: 'dist/index.js'
88 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "action-setup-kube-tools",
3 | "version": "0.11.2",
4 | "private": true,
5 | "description": "Github Action that install Kubernetes tools (kubectl, kustomize, helm, kubeconform, conftest, yq, etc.) and cache them on the runner",
6 | "main": "lib/main.js",
7 | "scripts": {
8 | "build": "tsc",
9 | "format": "prettier --write **/*.ts",
10 | "format-check": "prettier --check **/*.ts",
11 | "lint": "eslint src/*.ts",
12 | "pack": "ncc build",
13 | "all": "npm run build && npm run format && npm run lint && npm run pack"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/yokawasa/action-setup-kube-tools.git"
18 | },
19 | "keywords": [
20 | "actions",
21 | "node",
22 | "setup",
23 | "kubernetes",
24 | "kubectl",
25 | "kustomize",
26 | "helm",
27 | "kubeval",
28 | "kubeconform",
29 | "conftest",
30 | "yq",
31 | "rancher",
32 | "tilt",
33 | "skaffold",
34 | "kube-score"
35 | ],
36 | "author": "Yoichi Kawasaki",
37 | "license": "MIT",
38 | "dependencies": {
39 | "@actions/core": "^1.10.0",
40 | "@actions/exec": "^1.1.1",
41 | "@actions/tool-cache": "^2.0.1"
42 | },
43 | "devDependencies": {
44 | "@types/node": "^12.7.12",
45 | "@typescript-eslint/parser": "^2.8.0",
46 | "@vercel/ncc": "^0.34.0",
47 | "eslint": "^5.16.0",
48 | "eslint-plugin-github": "^2.0.0",
49 | "eslint-plugin-jest": "^22.21.0",
50 | "js-yaml": "^3.13.1",
51 | "prettier": "^1.19.1",
52 | "ts-jest": "^26.1.0",
53 | "typescript": "^3.9.10"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import * as os from 'os'
2 | import * as path from 'path'
3 | import * as util from 'util'
4 | import * as fs from 'fs'
5 |
6 | import * as toolCache from '@actions/tool-cache'
7 | import * as core from '@actions/core'
8 |
9 | const defaultProcessorArchType = 'amd64'
10 |
11 | const defaultKubectlVersion = '1.24.10'
12 | const defaultKustomizeVersion = '5.0.0'
13 | const defaultHelmVersion = '3.11.1'
14 | const defaultKubevalVersion = '0.16.1'
15 | const defaultKubeconformVersion = '0.5.0'
16 | const defaultConftestVersion = '0.39.0'
17 | const defaultYqVersion = '4.30.7'
18 | const defaultRancherVersion = '2.7.0'
19 | const defaultTiltVersion = '0.31.2'
20 | const defaultSkaffoldVersion = '2.1.0'
21 | const defaultKubeScoreVersion = '1.16.1'
22 |
23 | interface Tool {
24 | name: string
25 | defaultVersion: string
26 | isArchived: boolean
27 | supportArm: boolean
28 | commandPathInPackage: string
29 | }
30 |
31 | const Tools: Tool[] = [
32 | {
33 | name: 'kubectl',
34 | defaultVersion: defaultKubectlVersion,
35 | isArchived: false,
36 | supportArm: true,
37 | commandPathInPackage: 'kubectl'
38 | },
39 | {
40 | name: 'kustomize',
41 | defaultVersion: defaultKustomizeVersion,
42 | isArchived: true,
43 | supportArm: true,
44 | commandPathInPackage: 'kustomize'
45 | },
46 | {
47 | name: 'helm',
48 | defaultVersion: defaultHelmVersion,
49 | isArchived: true,
50 | supportArm: true,
51 | commandPathInPackage: 'linux-{arch}/helm'
52 | },
53 | {
54 | name: 'kubeval',
55 | defaultVersion: defaultKubevalVersion,
56 | isArchived: true,
57 | supportArm: false,
58 | commandPathInPackage: 'kubeval'
59 | },
60 | {
61 | name: 'kubeconform',
62 | defaultVersion: defaultKubeconformVersion,
63 | isArchived: true,
64 | supportArm: true,
65 | commandPathInPackage: 'kubeconform'
66 | },
67 | {
68 | name: 'conftest',
69 | defaultVersion: defaultConftestVersion,
70 | isArchived: true,
71 | supportArm: true,
72 | commandPathInPackage: 'conftest'
73 | },
74 | {
75 | name: 'yq',
76 | defaultVersion: defaultYqVersion,
77 | isArchived: false,
78 | supportArm: true,
79 | commandPathInPackage: 'yq_linux_{arch}'
80 | },
81 | {
82 | name: 'rancher',
83 | defaultVersion: defaultRancherVersion,
84 | isArchived: true,
85 | supportArm: true,
86 | commandPathInPackage: 'rancher-v{ver}/rancher'
87 | },
88 | {
89 | name: 'tilt',
90 | defaultVersion: defaultTiltVersion,
91 | isArchived: true,
92 | supportArm: true,
93 | commandPathInPackage: 'tilt'
94 | },
95 | {
96 | name: 'skaffold',
97 | defaultVersion: defaultSkaffoldVersion,
98 | isArchived: false,
99 | supportArm: true,
100 | commandPathInPackage: 'skaffold-linux-{arch}'
101 | },
102 | {
103 | name: 'kube-score',
104 | defaultVersion: defaultKubeScoreVersion,
105 | isArchived: false,
106 | supportArm: true,
107 | commandPathInPackage: 'kube-score'
108 | }
109 | ]
110 |
111 | // Replace all {ver} and {arch} placeholders in the source format string with the actual values
112 | function replacePlaceholders(
113 | format: string,
114 | version: string,
115 | archType: string
116 | ): string {
117 | return format.replace(/{ver}|{arch}/g, match => {
118 | return match === '{ver}' ? version : archType
119 | })
120 | }
121 |
122 | function getDownloadURL(
123 | commandName: string,
124 | version: string,
125 | archType: string
126 | ): string {
127 | let actualArchType = archType
128 | let urlFormat = ''
129 | switch (commandName) {
130 | case 'kubectl':
131 | urlFormat = 'https://dl.k8s.io/release/v{ver}/bin/linux/{arch}/kubectl'
132 | break
133 | case 'kustomize':
134 | urlFormat =
135 | 'https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv{ver}/kustomize_v{ver}_linux_{arch}.tar.gz'
136 | break
137 | case 'helm':
138 | urlFormat = 'https://get.helm.sh/helm-v{ver}-linux-{arch}.tar.gz'
139 | break
140 | case 'kubeval':
141 | actualArchType = 'amd64' // kubeval only supports amd64
142 | urlFormat =
143 | 'https://github.com/instrumenta/kubeval/releases/download/v{ver}/kubeval-linux-{arch}.tar.gz'
144 | break
145 | case 'kubeconform':
146 | urlFormat =
147 | 'https://github.com/yannh/kubeconform/releases/download/v{ver}/kubeconform-linux-{arch}.tar.gz'
148 | break
149 | case 'conftest':
150 | actualArchType = archType === 'arm64' ? archType : 'x86_64'
151 | urlFormat =
152 | 'https://github.com/open-policy-agent/conftest/releases/download/v{ver}/conftest_{ver}_Linux_{arch}.tar.gz'
153 | break
154 | case 'yq':
155 | urlFormat =
156 | 'https://github.com/mikefarah/yq/releases/download/v{ver}/yq_linux_{arch}'
157 | break
158 | case 'rancher':
159 | actualArchType = archType === 'arm64' ? 'arm' : archType
160 | urlFormat =
161 | 'https://github.com/rancher/cli/releases/download/v{ver}/rancher-linux-{arch}-v{ver}.tar.gz'
162 | break
163 | case 'tilt':
164 | actualArchType = archType === 'arm64' ? archType : 'x86_64'
165 | urlFormat =
166 | 'https://github.com/tilt-dev/tilt/releases/download/v{ver}/tilt.{ver}.linux.{arch}.tar.gz'
167 | break
168 | case 'skaffold':
169 | urlFormat =
170 | 'https://github.com/GoogleContainerTools/skaffold/releases/download/v{ver}/skaffold-linux-{arch}'
171 | break
172 | case 'kube-score':
173 | urlFormat =
174 | 'https://github.com/zegl/kube-score/releases/download/v{ver}/kube-score_{ver}_linux_{arch}'
175 | break
176 | default:
177 | return ''
178 | }
179 | return replacePlaceholders(urlFormat, version, actualArchType)
180 | }
181 |
182 | async function downloadTool(
183 | version: string,
184 | archType: string,
185 | tool: Tool
186 | ): Promise {
187 | let cachedToolPath = toolCache.find(tool.name, version)
188 | let commandPathInPackage = tool.commandPathInPackage
189 | let commandPath = ''
190 |
191 | if (!cachedToolPath) {
192 | const downloadURL = getDownloadURL(tool.name, version, archType)
193 |
194 | try {
195 | const packagePath = await toolCache.downloadTool(downloadURL)
196 |
197 | if (tool.isArchived) {
198 | const extractTarBaseDirPath = util.format(
199 | '%s_%s',
200 | packagePath,
201 | tool.name
202 | )
203 |
204 | fs.mkdirSync(extractTarBaseDirPath)
205 |
206 | const extractedDirPath = await toolCache.extractTar(
207 | packagePath,
208 | extractTarBaseDirPath
209 | )
210 |
211 | commandPathInPackage = replacePlaceholders(
212 | commandPathInPackage,
213 | version,
214 | archType
215 | )
216 | commandPath = util.format(
217 | '%s/%s',
218 | extractedDirPath,
219 | commandPathInPackage
220 | )
221 | } else {
222 | commandPath = packagePath
223 | }
224 | } catch (exception) {
225 | throw new Error(`Download ${tool.name} Failed! (url: ${downloadURL})`)
226 | }
227 | cachedToolPath = await toolCache.cacheFile(
228 | commandPath,
229 | tool.name,
230 | tool.name,
231 | version
232 | )
233 | // eslint-disable-next-line no-console
234 | console.log(`${tool.name} version '${version}' has been cached`)
235 | } else {
236 | // eslint-disable-next-line no-console
237 | console.log(`Found in cache: ${tool.name} version '${version}'`)
238 | }
239 |
240 | const cachedCommand = path.join(cachedToolPath, tool.name)
241 | fs.chmodSync(cachedCommand, '777')
242 | return cachedCommand
243 | }
244 |
245 | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
246 | async function run() {
247 | if (!os.type().match(/^Linux/)) {
248 | throw new Error('The action only support Linux OS!')
249 | }
250 |
251 | let failFast = true
252 | if (core.getInput('fail-fast', {required: false}).toLowerCase() === 'false') {
253 | failFast = false
254 | }
255 |
256 | let archType = defaultProcessorArchType
257 | if (core.getInput('arch-type', {required: false}).toLowerCase() === 'arm64') {
258 | archType = 'arm64'
259 | }
260 |
261 | let setupToolList: string[] = []
262 | const setupTools = core.getInput('setup-tools', {required: false}).trim()
263 | if (setupTools) {
264 | setupToolList = setupTools
265 | .split('\n')
266 | .map(function(x) {
267 | return x.trim()
268 | })
269 | .filter(x => x !== '')
270 | }
271 |
272 | // eslint-disable-next-line github/array-foreach
273 | Tools.forEach(async function(tool) {
274 | let toolPath = ''
275 | // By default, the action setup all supported Kubernetes tools, which mean
276 | // all tools can be setup when setuptools does not have any elements.
277 | if (setupToolList.length === 0 || setupToolList.includes(tool.name)) {
278 | let toolVersion = core
279 | .getInput(tool.name, {required: false})
280 | .toLowerCase()
281 | if (toolVersion && toolVersion.startsWith('v')) {
282 | toolVersion = toolVersion.substr(1)
283 | }
284 | if (!toolVersion) {
285 | toolVersion = tool.defaultVersion
286 | }
287 | if (archType === 'arm64' && !tool.supportArm) {
288 | // eslint-disable-next-line no-console
289 | console.log(
290 | `The ${tool.name} does not support arm64 architecture, skip it`
291 | )
292 | return
293 | }
294 |
295 | try {
296 | const cachedPath = await downloadTool(toolVersion, archType, tool)
297 | core.addPath(path.dirname(cachedPath))
298 | toolPath = cachedPath
299 | } catch (exception) {
300 | if (failFast) {
301 | // eslint-disable-next-line no-console
302 | console.log(`Exiting immediately (fail fast) - [Reason] ${exception}`)
303 | process.exit(1)
304 | }
305 | }
306 | }
307 | core.setOutput(`${tool.name}-path`, toolPath)
308 | })
309 | }
310 |
311 | run().catch(core.setFailed)
312 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "outDir": "./lib",
6 | "rootDir": "./src",
7 | "strict": true,
8 | "noImplicitAny": true,
9 | "esModuleInterop": true
10 | },
11 | "exclude": ["node_modules", "**/*.test.ts"]
12 | }
13 |
--------------------------------------------------------------------------------