Skip to content

Commit 11be72c

Browse files
changed readme
1 parent 9ec341a commit 11be72c

File tree

2 files changed

+121
-157
lines changed

2 files changed

+121
-157
lines changed

.github/workflows/deploy.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# deploy.yaml
2+
# Copyright (c) 2025 Affinity7 Consulting Ltd
23
# Version: v2 (reusable, minimal auth precedence)
34
# SPDX-License-Identifier: MIT
45

README.md

Lines changed: 120 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,129 @@
1-
# 🚀 Reusable GitHub Workflow: Kubernetes App Deployment with ArgoCD
1+
# 🚀 Reusable GitHub Workflow: Kubernetes App Deployment with ArgoCD (v2 BETA)
22

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.
45

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.
68
79
---
810

911
## ⚙️ Inputs
1012

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+
}
7269
```
7370

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 |
7582

7683
---
7784

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
9586

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 |
9991

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 |
10198

10299
---
103100

104-
## 🛠 Actions Used
101+
## 📦 Artifact Uploads
105102

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` |
112107

113108
---
114109

115110
## 🔄 Deployment Flow Summary
116111

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:
121118
```
122-
${{ cd_repo }}/${cluster}/${namespace}/${application}/
119+
continuous-deployment/<cluster>/<namespace>/<application>/
123120
```
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)
149127

150128
---
151129

@@ -154,17 +132,16 @@ Two useful artifacts are uploaded after every run:
154132
```yaml
155133
jobs:
156134
deploy:
157-
uses: gitopsmanager/k8s-deploy/.github/workflows/deploy.yaml@v1
135+
uses: gitopsmanager/k8s-deploy/.github/workflows/deploy.yaml@v2
158136
with:
159137
environment: dev
160138
application: my-app
161139
namespace: my-namespace
162140
repo: my-org/my-app
163-
repo_path: manifests
141+
deployFilesPath: manifests/overlays/dev
164142
overlay_dir: dev
143+
image_tag: abc123
165144
secrets:
166-
ARGO_CD_ADMIN_USER: ${{ secrets.ARGO_CD_ADMIN_USER }}
167-
ARGO_CD_ADMIN_PASSWORD: ${{ secrets.ARGO_CD_ADMIN_PASSWORD }}
168145
CONTINUOUS_DEPLOYMENT_GH_APP_ID: ${{ secrets.CD_GH_APP_ID }}
169146
CONTINUOUS_DEPLOYMENT_GH_APP_PRIVATE_KEY: ${{ secrets.CD_GH_APP_KEY }}
170147
ARGOCD_CA_CERT: ${{ secrets.ARGOCD_CA_CERT }}
@@ -174,57 +151,43 @@ jobs:
174151
175152
## 🏗 ArgoCD Requirements
176153
177-
You **must** install ArgoCD with the following ingress hostname format:
154+
ArgoCD ingress must match:
178155
179156
```
180157
https://${cluster}-argocd-argocd-web-ui.${dns_zone}
181158
```
182159

183-
For example:
160+
Example:
184161
```
185162
https://aks-west-europe-argocd-argocd-web-ui.internal.demo.affinity7software.com
186163
```
187164

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-
190165
---
191166

192167
## 📦 ArgoCD App Details
193168

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}` |
204177

205178
---
206-
### 🔖 Versioning
207179

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
217181

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
219184

220185
---
221186

222-
## License
223-
224-
This project is licensed under the MIT License. See [LICENSE](./LICENSE) for details.
187+
## 📜 License
225188

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).
228191

229192

230193

0 commit comments

Comments
 (0)