1
- # 🚀 Reusable GitHub Workflow: Kubernetes App Deployment with ArgoCD
1
+ # 🚀 Reusable GitHub Workflow: Kubernetes App Deployment with ArgoCD (v2 BETA)
2
2
3
- This GitHub Actions reusable workflow automates Kubernetes application deployment using [ Kustomize] ( https://kubectl.docs.kubernetes.io/references/kustomize/ ) and [ ArgoCD] ( https://argo-cd.readthedocs.io/en/stable/ ) . It renders and templates your manifest files, commits the results to your continuous deployment repo, and uses the ArgoCD REST API to create and sync applications.
3
+ This GitHub Actions ** reusable workflow** automates Kubernetes application deployment using [ Kustomize] ( https://kubectl.docs.kubernetes.io/references/kustomize/ ) and [ ArgoCD] ( https://argo-cd.readthedocs.io/en/stable/ ) .
4
+ It renders and templates your manifest files, commits the results to your ** continuous deployment (CD) repo** , and uses the ** ArgoCD REST API** to create and sync applications.
4
5
5
- > ✅ This workflow ** always creates the ArgoCD Application** if it does not already exist — ensuring first-time deployments are fully automated.
6
+ > ✅ ** ArgoCD Applications are auto-created if missing** , so first-time deployments work out-of-the-box.
7
+ > ⚠️ ** v2 is currently in BETA** — APIs and inputs may evolve slightly.
6
8
7
9
---
8
10
9
11
## ⚙️ Inputs
10
12
11
- | Name | Required | Type | Description |
12
- | -----------------------| ----------| ---------| -----------------------------------------------------------------------------|
13
- | ` runner ` | ❌ | string | GitHub runner label (default: ` ubuntu-latest ` ) |
14
- | ` cd_repo ` | ✅ | string | Continuous deployment repo that stores templated manifests |
15
- | ` environment ` | ✅ | string | Logical environment name (e.g. ` dev ` , ` prod ` ) |
16
- | ` application ` | ✅ | string | Application name (used as part of ArgoCD app name) |
17
- | ` namespace ` | ✅ | string | Kubernetes namespace to deploy into |
18
- | ` repo ` | ✅ | string | GitHub repo with source manifests (e.g. ` my-org/my-app ` ) |
19
- | ` repo_path ` | ✅ | string | Path to manifest files (e.g. ` manifests/ ` ) |
20
- | ` repo_commit_id ` | ❌ | string | Optional commit SHA to deploy (overrides ` branch_name ` ) |
21
- | ` branch_name ` | ❌ | string | Git branch to checkout (default: ` main ` ) |
22
- | ` overlay_dir ` | ✅ | string | Subdirectory under ` overlays/ ` to use with Kustomize |
23
- | ` image_tag ` | ❌ | string | Image tag to apply to container image(s) |
24
- | ` image_base_name ` | ❌ | string | Single image base name to patch (e.g. ` ghcr.io/org/app ` ) |
25
- | ` image_base_names ` | ❌ | string | Comma-separated list of image base names |
26
- | ` kustomize_version ` | ❌ | string | Kustomize version to install (default: ` 5.0.1 ` ) |
27
- | ` skip_status_check ` | ❌ | string | If ` 'true' ` , skips waiting for ArgoCD sync to finish |
28
- | ` insecure_argo ` | ❌ | boolean | If ` true ` , disables TLS verification for ArgoCD endpoints |
29
- | ` debug ` | ❌ | boolean | If ` true ` , prints debug output of generated files and paths |
30
-
31
- ---
32
-
33
- ## 🔐 Required Secrets
34
-
35
- | Name | Description |
36
- | --------------------------------------| -----------------------------------------------------|
37
- | ` ARGO_CD_ADMIN_USER ` | ArgoCD admin username |
38
- | ` ARGO_CD_ADMIN_PASSWORD ` | ArgoCD admin password |
39
- | ` CONTINUOUS_DEPLOYMENT_GH_APP_ID ` | GitHub App ID used to access the CD repo |
40
- | ` CONTINUOUS_DEPLOYMENT_GH_APP_PRIVATE_KEY ` | GitHub App private key |
41
-
42
- ### 🧩 Optional Secrets
43
-
44
- | Name | Description |
45
- | --------------------| -----------------------------------------------------------------------------|
46
- | ` ARGOCD_CA_CERT ` | PEM-formatted CA certificate to verify ArgoCD's TLS endpoint (if not using ` insecure_argo ` ) |
47
-
48
- > ⚠️ ** TLS Verification** :
49
- > You must either set ` insecure_argo: true ` to skip TLS validation ** OR** provide a valid ` ARGOCD_CA_CERT ` secret. If neither is set and ArgoCD is secured with a custom/self-signed certificate, the workflow will fail to connect.
50
-
51
- ---
52
-
53
- ## 📁 Repository Layout Expectations
54
-
55
- ### Source Repository (` repo ` )
56
-
57
- This should contain a standard [ Kustomize base/overlay structure] ( https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/ ) like:
58
-
59
- ```
60
- manifests/
61
- base/
62
- overlays/
63
- dev/
64
- prod/
65
- ```
66
-
67
- ### Continuous Deployment Repository (` cd_repo ` )
68
-
69
- The templated output from the deployment will be committed to:
70
- ```
71
- ${{ cd_repo }}/${cluster}/${namespace}/${application}/
13
+ ### Core
14
+ | Name | Required | Type | Description |
15
+ | ---------------| ----------| --------| -------------|
16
+ | ` runner ` | ❌ | string | GitHub runner label (default: ` ubuntu-latest ` ) |
17
+ | ` cd_repo ` | ✅ | string | Continuous deployment repo where templated manifests are stored |
18
+ | ` environment ` | ✅ | string | Logical environment name (e.g. ` dev ` , ` prod ` ) |
19
+ | ` cluster ` | ❌ | string | Required only when ` env_map[environment] ` has multiple clusters |
20
+ | ` namespace ` | ✅ | string | Kubernetes namespace for deployment |
21
+
22
+ ### Source Repo
23
+ | Name | Required | Type | Description |
24
+ | -----------------| ----------| --------| -------------|
25
+ | ` repo ` | ✅ | string | GitHub repo containing source manifests (e.g. ` my-org/my-app ` ) |
26
+ | ` deployFilesPath ` | ❌ | string | Path to manifest files inside ` repo ` |
27
+ | ` repo_commit_id ` | ❌ | string | Commit SHA to deploy (overrides ` branch_name ` ) |
28
+ | ` branch_name ` | ❌ | string | Branch to checkout (default: ` main ` ) |
29
+
30
+ ### Deployment Modes
31
+ - ** Mode A (single app):**
32
+ - ` application ` (string, required)
33
+ - ` deployFilesPath ` (string, required if not using ` applicationDetails ` )
34
+ - ` image_tag ` (string, optional)
35
+ - ` image_base_name ` (string, optional)
36
+ - ` image_base_names ` (string, optional, comma-separated list)
37
+
38
+ - ** Mode B (multi app):**
39
+ - ` applicationDetails ` (JSON array, optional)
40
+ ``` json
41
+ [
42
+ {"name" :" app1" ,"images" :[" repo/app1" ," repo/sidecar" ],"path" :" services/app1/overlays/prod" },
43
+ {"name" :" app2" ,"images" :[" repo/app2" ],"path" :" apps/app2/overlays/prod" }
44
+ ]
45
+ ```
46
+
47
+ ### Environment Map
48
+ | Name | Required | Type | Description |
49
+ |-----------|----------|--------|-------------|
50
+ | `env_map` | ❌ | string | JSON describing environments, clusters, registries, and UAMI mappings |
51
+
52
+ Example shape:
53
+ ```json
54
+ {
55
+ "dev" : {
56
+ "cluster_count" : 1 ,
57
+ "clusters" : [
58
+ {
59
+ "cluster" : " aks-west-europe" ,
60
+ "dns_zone" : " internal.demo.affinity7software.com" ,
61
+ "container_registry" : " ghcr.io/my-org" ,
62
+ "uami_map" : [
63
+ {"uami_name" :" aks-uami" ,"uami_resource_group" :" rg-demo" ,"client_id" :" 1234-5678" }
64
+ ]
65
+ }
66
+ ]
67
+ }
68
+ }
72
69
```
73
70
74
- This becomes the ** ArgoCD source path** , from which the app syncs after every deployment.
71
+ ### ArgoCD / Misc
72
+ | Name | Required | Type | Default | Description |
73
+ | --------------------| ----------| --------| ---------| -------------|
74
+ | ` argocd_auth_token ` | ❌ | string | – | Direct token for ArgoCD auth |
75
+ | ` argocd_username ` | ❌ | string | – | Username (basic auth fallback) |
76
+ | ` argocd_password ` | ❌ | string | – | Password (basic auth fallback) |
77
+ | ` kustomize_version ` | ❌ | string | ` 5.0.1 ` | Kustomize version |
78
+ | ` skip_status_check ` | ❌ | string | ` false ` | Skip waiting for ArgoCD sync |
79
+ | ` insecure_argo ` | ❌ | boolean | ` false ` | Skip TLS verification |
80
+ | ` convert_jinja ` | ❌ | boolean | ` false ` | Convert ` {{ var }} ` → ` ${var} ` before templating |
81
+ | ` debug ` | ❌ | boolean | ` false ` | Print debug structure |
75
82
76
83
---
77
84
78
- ## 🌍 Environment Mapping
79
-
80
- Your CD repo must define:
81
-
82
- ```
83
- ${{ cd_repo }}/config/env-map.yaml
84
- ```
85
-
86
- With contents like:
87
- ``` yaml
88
- dev :
89
- cluster : aks-west-europe
90
- dns_zone : internal.demo.affinity7software.com
91
- prod :
92
- cluster : aks-prod-eu
93
- dns_zone : prod.example.com
94
- ` ` `
85
+ ## 🔐 Required Secrets
95
86
96
- This file maps logical environments (like ` dev`, `prod`) to:
97
- - `cluster` : used in naming the ArgoCD app and web UI
98
- - `dns_zone` : used to compute the full ArgoCD web endpoint
87
+ | Name | Description |
88
+ | ----------------------------------------| -------------|
89
+ | ` CONTINUOUS_DEPLOYMENT_GH_APP_ID ` | GitHub App ID used to push to the CD repo |
90
+ | ` CONTINUOUS_DEPLOYMENT_GH_APP_PRIVATE_KEY ` | GitHub App private key |
99
91
100
- > 💡 This is used to support different clusters and hosted DNS zones (Azure DNS or Route53) per environment.
92
+ ### 🧩 Optional Secrets
93
+ | Name | Description |
94
+ | --------------------| -------------|
95
+ | ` ARGOCD_CA_CERT ` | PEM CA cert to verify ArgoCD endpoint |
96
+ | ` ARGOCD_USERNAME ` | Fallback ArgoCD username |
97
+ | ` ARGOCD_PASSWORD ` | Fallback ArgoCD password |
101
98
102
99
---
103
100
104
- # # 🛠 Actions Used
101
+ ## 📦 Artifact Uploads
105
102
106
- | Action | Version | Description |
107
- |------------------------------------------------------------------------|---------|-----------------------------------------------------------------------------|
108
- | [actions/checkout](https://github.com/actions/checkout) | `v4` | Used to clone both source and CD repositories |
109
- | [tibdex/github-app-token](https://github.com/tibdex/github-app-token) | `v1` | Generates a GitHub App token to push to the CD repo |
110
- | [imranismail/setup-kustomize](https://github.com/imranismail/setup-kustomize) | `v2` | Installs the desired version of Kustomize |
111
- | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `v4` | Stores rendered and built outputs for debugging |
103
+ | Artifact Name | Description |
104
+ | -----------------------------| -------------|
105
+ | ` templated-source-manifests ` | All files after envsubst templating |
106
+ | ` built-kustomize-manifest ` | Final rendered output of ` kustomize build ` |
112
107
113
108
---
114
109
115
110
## 🔄 Deployment Flow Summary
116
111
117
- 1. **Clone the source repo and CD repo**
118
- 2. **Read cluster and DNS zone info** from `${{ cd_repo }}/config/env-map.yaml`
119
- 3. **Template all `${}` variables** using `envsubst` (only if present in supported file types)
120
- 4. **Copy** templated manifests to :
112
+ 1 . Checkout ** source** and ** CD repos**
113
+ 2 . Parse ** env_map JSON** and select cluster
114
+ 3 . Export ** UAMI env vars** if provided
115
+ 4 . Convert Jinja → envsubst (if enabled)
116
+ 5 . Template manifests (` envsubst ` )
117
+ 6 . Copy to CD repo path:
121
118
```
122
- ${{ cd_repo }}/${ cluster}/${ namespace}/${ application} /
119
+ continuous-deployment/< cluster>/< namespace>/< application> /
123
120
```
124
- 5. **Patch image tags** in the `overlay_dir` if `image_tag` is provided
125
- 6. **Run `kustomize build .`** on the overlay
126
- - The result is saved as `build-output.yaml` (uploaded as an artifact)
127
- - If build fails, the action will stop before contacting ArgoCD
128
- 7. **Commit and push** the rendered code to the CD repo
129
- 8. **ArgoCD app is created if it does not exist**, using the rendered template :
130
- ` ` `
131
- gitopsmanager/k8s-deploy/templates/argocd-application-template.json
132
- ` ` `
133
- The file is rendered using `envsubst` with variables from the environment.
134
- 9. **ArgoCD sync is triggered via REST API**
135
- 10. **Sync status is polled**, unless `skip_status_check : true`
136
-
137
- ---
138
-
139
- # # 📦 Artifact Uploads
140
-
141
- Two useful artifacts are uploaded after every run :
142
-
143
- | Artifact Name | Description |
144
- |-----------------------------|-------------------------------------------------------------|
145
- | `templated-source-manifests` | All files after `envsubst` templating |
146
- | `built-kustomize-manifest` | Final rendered output of `kustomize build` |
147
-
148
- > These allow you to troubleshoot errors with ArgoCD sync or validate the rendered output locally.
121
+ 7 . Patch image tags (if provided)
122
+ 8 . Run ` kustomize build `
123
+ 9 . Commit & push to CD repo
124
+ 10 . Create ArgoCD app if missing
125
+ 11 . Trigger ArgoCD sync
126
+ 12 . Wait for sync (unless skipped)
149
127
150
128
---
151
129
@@ -154,17 +132,16 @@ Two useful artifacts are uploaded after every run:
154
132
``` yaml
155
133
jobs :
156
134
deploy :
157
- uses: gitopsmanager/k8s-deploy/.github/workflows/deploy.yaml@v1
135
+ uses : gitopsmanager/k8s-deploy/.github/workflows/deploy.yaml@v2
158
136
with :
159
137
environment : dev
160
138
application : my-app
161
139
namespace : my-namespace
162
140
repo : my-org/my-app
163
- repo_path : manifests
141
+ deployFilesPath : manifests/overlays/dev
164
142
overlay_dir : dev
143
+ image_tag : abc123
165
144
secrets :
166
- ARGO_CD_ADMIN_USER: ${{ secrets.ARGO_CD_ADMIN_USER }}
167
- ARGO_CD_ADMIN_PASSWORD: ${{ secrets.ARGO_CD_ADMIN_PASSWORD }}
168
145
CONTINUOUS_DEPLOYMENT_GH_APP_ID : ${{ secrets.CD_GH_APP_ID }}
169
146
CONTINUOUS_DEPLOYMENT_GH_APP_PRIVATE_KEY : ${{ secrets.CD_GH_APP_KEY }}
170
147
ARGOCD_CA_CERT : ${{ secrets.ARGOCD_CA_CERT }}
@@ -174,57 +151,43 @@ jobs:
174
151
175
152
## 🏗 ArgoCD Requirements
176
153
177
- You **must** install ArgoCD with the following ingress hostname format :
154
+ ArgoCD ingress must match :
178
155
179
156
` ` `
180
157
https://${cluster}-argocd-argocd-web-ui.${dns_zone}
181
158
```
182
159
183
- For example :
160
+ Example :
184
161
```
185
162
https://aks-west-europe-argocd-argocd-web-ui.internal.demo.affinity7software.com
186
163
```
187
164
188
- > 🧠 This is how the workflow constructs the URL to talk to the ArgoCD API. If your ingress differs, you'll need to update the URL logic in `deploy.yaml`.
189
-
190
165
---
191
166
192
167
## 📦 ArgoCD App Details
193
168
194
- The created ArgoCD Application will have :
195
-
196
- | Field | Value |
197
- |--------------|-----------------------------------------------------------------------|
198
- | `project` | `default` |
199
- | `name` | `${namespace}-${application}` |
200
- | `source.repoURL` | `https://github.com/${cd_repo}` |
201
- | `source.path` | `${cluster}/${namespace}/${application}/overlays/${overlay_dir}` |
202
- | `destination.server` | `https://kubernetes.default.svc` |
203
- | `destination.namespace` | value from `inputs.namespace` |
169
+ | Field | Value |
170
+ | --------------| -------|
171
+ | ` project ` | ` default ` |
172
+ | ` name ` | ` ${namespace}-${application} ` |
173
+ | ` source.repoURL ` | ` https://github.com/${cd_repo} ` |
174
+ | ` source.path ` | ` ${cluster}/${namespace}/${application}/... ` |
175
+ | ` destination.server ` | ` https://kubernetes.default.svc ` |
176
+ | ` destination.namespace ` | ` ${namespace} ` |
204
177
205
178
---
206
- # ## 🔖 Versioning
207
179
208
- This workflow is published with Git tags for stable releases.
209
-
210
- - ` @v1` – Tracks the latest stable version in the v1.x series (recommended)
211
- - Semantic tags like `@v1.0.0` will be published in the future for reproducible builds
212
-
213
- # ### Example:
214
- ` ` ` yaml
215
- uses: gitopsmanager/k8s-deploy/.github/workflows/deploy.yaml@v1
216
- ` ` `
180
+ ### 🔖 Versioning
217
181
218
- > ✅ Use `@v1` for stability and latest updates. Semantic version tags (e.g., `v1.0.0`) will be available as additional pinning options in future releases.
182
+ - ` @v2 ` – Latest ** beta** version
183
+ - ` @v1 ` – Latest stable v1 series
219
184
220
185
---
221
186
222
- # # License
223
-
224
- This project is licensed under the MIT License. See [LICENSE](./LICENSE) for details.
187
+ ## 📜 License
225
188
226
- Third-party components used in GitHub Actions workflows and automation are documented in :
227
- - [THIRD-PARTY-ACTIONS-AND-TOOLS.md](./THIRD-PARTY-ACTIONS-AND-TOOLS.md)
189
+ Licensed under MIT. See [ LICENSE ] ( ./LICENSE ) .
190
+ Third-party actions are listed in [ THIRD-PARTY-ACTIONS-AND-TOOLS.md] ( ./THIRD-PARTY-ACTIONS-AND-TOOLS.md ) .
228
191
229
192
230
193
0 commit comments