commit 9af750af3f9ed6cbd918bc694ef7b42ce3a4c7f4 Author: 5vl Date: Thu Sep 10 13:57:05 2026 +0200 Initial Helm and Kargo setup diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..445b562 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.secret.yaml +.env diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 0000000..cda93f0 --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: kub-web-test +description: Small Helm/Kargo/Argo CD test application +type: application +version: 0.1.0 +appVersion: "1.0.0" diff --git a/README.md b/README.md new file mode 100644 index 0000000..a1e32e0 --- /dev/null +++ b/README.md @@ -0,0 +1,154 @@ +\ +# kub-web-test + +Two Git branches, three deployed environments. + +## Branches + +- `dev` — development changes go here +- `prod` — Kargo writes promoted content here + +There is deliberately **no staging branch**. + +## Sites / Kargo Stages + +- DEV — `http://web-dev.max.test.scrumdapp.open-ict.hu` +- STAGING — `http://web-staging.max.test.scrumdapp.open-ict.hu` +- PROD — `http://web-prod.max.test.scrumdapp.open-ict.hu` + +```text +push to dev + | + v +Warehouse + | + v (automatic) + DEV + | + v (manual) + STAGING + | + v (manual) + PROD + | + +--> writes promoted content to prod branch +``` + +Staging is pinned by Kargo to the exact commit selected from `dev`. +Prod permanently tracks the `prod` branch. + +## Initial Git setup + +```bash +git init +git remote add origin https://git.5vl.nl/5vl/kub-web-test.git + +git checkout -b dev +git add . +git commit -m "Initial Helm and Kargo setup" +git push -u origin dev + +# Seed prod once so Argo CD has something to deploy initially. +git checkout -b prod +git push -u origin prod + +git checkout dev +``` + +After that, do your normal work on `dev`. + +## Bootstrap Kargo project + +```bash +kubectl apply -f bootstrap/00-kargo-project.yaml +kubectl get namespace web +``` + +## Kargo Git credentials + +Kargo needs write permission because the prod promotion pushes to `prod`. + +Do not commit the real token. + +```bash +read -s -p "Git token: " GIT_TOKEN +echo + +kubectl create secret generic kub-web-test-git \ + -n web \ + --from-literal=repoURL=https://git.5vl.nl/5vl/kub-web-test.git \ + --from-literal=username=5vl \ + --from-literal=password="$GIT_TOKEN" + +kubectl label secret kub-web-test-git \ + -n web \ + kargo.akuity.io/cred-type=git +``` + +## Argo CD repository credentials + +If the repository is private: + +```bash +kubectl create secret generic kub-web-test-repository \ + -n argocd \ + --from-literal=type=git \ + --from-literal=url=https://git.5vl.nl/5vl/kub-web-test.git \ + --from-literal=username=5vl \ + --from-literal=password="$GIT_TOKEN" + +kubectl label secret kub-web-test-repository \ + -n argocd \ + argocd.argoproj.io/secret-type=repository +``` + +Then: + +```bash +unset GIT_TOKEN +``` + +## Create Argo CD apps and Kargo pipeline + +```bash +kubectl apply -f bootstrap/01-argocd-applications.yaml +kubectl apply -f bootstrap/02-kargo-pipeline.yaml +``` + +Check: + +```bash +kubectl get applications -n argocd +kubectl get warehouse -n web +kubectl get stages -n web +kubectl get freight -n web +``` + +## Test the flow + +Make any change on `dev`: + +```bash +git checkout dev +# edit something +git add . +git commit -m "Test deployment" +git push +``` + +Then: + +1. Kargo discovers the commit as Freight. +2. `dev` auto-promotes it. +3. Check the DEV site. +4. Manually promote that Freight to `staging`. +5. Check the STAGING site. +6. Manually promote the same Freight to `prod`. +7. Kargo copies that selected revision into the `prod` branch and pushes it. +8. Argo CD syncs the PROD site from `prod`. + +The three Kubernetes namespaces are: + +- `web-dev` +- `web-staging` +- `web-prod` diff --git a/bootstrap/00-kargo-project.yaml b/bootstrap/00-kargo-project.yaml new file mode 100644 index 0000000..7af35e7 --- /dev/null +++ b/bootstrap/00-kargo-project.yaml @@ -0,0 +1,5 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: Project + +metadata: + name: web diff --git a/bootstrap/01-argocd-applications.yaml b/bootstrap/01-argocd-applications.yaml new file mode 100644 index 0000000..81308c8 --- /dev/null +++ b/bootstrap/01-argocd-applications.yaml @@ -0,0 +1,83 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: web-dev + namespace: argocd + annotations: + kargo.akuity.io/authorized-stage: web:dev +spec: + project: default + destination: + server: https://kubernetes.default.svc + namespace: web-dev + source: + repoURL: https://git.5vl.nl/5vl/kub-web-test.git + targetRevision: dev + path: . + helm: + releaseName: web-dev + valueFiles: + - values-dev.yaml + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: web-staging + namespace: argocd + annotations: + kargo.akuity.io/authorized-stage: web:staging +spec: + project: default + destination: + server: https://kubernetes.default.svc + namespace: web-staging + source: + repoURL: https://git.5vl.nl/5vl/kub-web-test.git + # Baseline only. Kargo pins this live to the exact promoted dev commit. + targetRevision: prod + path: . + helm: + releaseName: web-staging + valueFiles: + - values-staging.yaml + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: web-prod + namespace: argocd + annotations: + kargo.akuity.io/authorized-stage: web:prod +spec: + project: default + destination: + server: https://kubernetes.default.svc + namespace: web-prod + source: + repoURL: https://git.5vl.nl/5vl/kub-web-test.git + targetRevision: prod + path: . + helm: + releaseName: web-prod + valueFiles: + - values-prod.yaml + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/bootstrap/02-kargo-pipeline.yaml b/bootstrap/02-kargo-pipeline.yaml new file mode 100644 index 0000000..8b75037 --- /dev/null +++ b/bootstrap/02-kargo-pipeline.yaml @@ -0,0 +1,184 @@ +apiVersion: kargo.akuity.io/v1alpha1 +kind: ProjectConfig +metadata: + name: web + namespace: web +spec: + promotionPolicies: + - stageSelector: + name: dev + autoPromotionEnabled: true + - stageSelector: + name: staging + autoPromotionEnabled: false + - stageSelector: + name: prod + autoPromotionEnabled: false + +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: Warehouse +metadata: + name: web + namespace: web +spec: + subscriptions: + - git: + repoURL: https://git.5vl.nl/5vl/kub-web-test.git + branch: dev + includePaths: + - Chart.yaml + - values.yaml + - values-dev.yaml + - values-staging.yaml + - values-prod.yaml + - templates + +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: dev + namespace: web +spec: + requestedFreight: + - origin: + kind: Warehouse + name: web + sources: + direct: true + promotionTemplate: + spec: + vars: + - name: repoURL + value: https://git.5vl.nl/5vl/kub-web-test.git + steps: + - uses: argocd-update + config: + apps: + - name: web-dev + sources: + - repoURL: ${{ vars.repoURL }} + desiredRevision: ${{ commitFrom(vars.repoURL).ID }} + +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: staging + namespace: web +spec: + requestedFreight: + - origin: + kind: Warehouse + name: web + sources: + stages: + - dev + promotionTemplate: + spec: + vars: + - name: repoURL + value: https://git.5vl.nl/5vl/kub-web-test.git + steps: + - uses: argocd-update + config: + apps: + - name: web-staging + sources: + - repoURL: ${{ vars.repoURL }} + desiredRevision: ${{ commitFrom(vars.repoURL).ID }} + updateTargetRevision: true + +--- +apiVersion: kargo.akuity.io/v1alpha1 +kind: Stage +metadata: + name: prod + namespace: web +spec: + requestedFreight: + - origin: + kind: Warehouse + name: web + sources: + stages: + - staging + promotionTemplate: + spec: + vars: + - name: repoURL + value: https://git.5vl.nl/5vl/kub-web-test.git + steps: + - uses: git-clone + config: + repoURL: ${{ vars.repoURL }} + author: + name: Kargo + email: kargo@max.test.scrumdapp.open-ict.hu + checkout: + - commit: ${{ commitFrom(vars.repoURL).ID }} + path: ./src + - branch: prod + create: true + path: ./out + + - uses: git-clear + config: + path: ./out + + - uses: copy + config: + inPath: ./src/Chart.yaml + outPath: ./out/Chart.yaml + - uses: copy + config: + inPath: ./src/values.yaml + outPath: ./out/values.yaml + - uses: copy + config: + inPath: ./src/values-dev.yaml + outPath: ./out/values-dev.yaml + - uses: copy + config: + inPath: ./src/values-staging.yaml + outPath: ./out/values-staging.yaml + - uses: copy + config: + inPath: ./src/values-prod.yaml + outPath: ./out/values-prod.yaml + - uses: copy + config: + inPath: ./src/templates + outPath: ./out/templates + - uses: copy + config: + inPath: ./src/bootstrap + outPath: ./out/bootstrap + - uses: copy + config: + inPath: ./src/README.md + outPath: ./out/README.md + - uses: copy + config: + inPath: ./src/.gitignore + outPath: ./out/.gitignore + + - uses: git-commit + as: commit + config: + path: ./out + message: Promote ${{ commitFrom(vars.repoURL).ID }} to prod + + - uses: git-push + config: + path: ./out + targetBranch: prod + + - uses: argocd-update + config: + apps: + - name: web-prod + sources: + - repoURL: ${{ vars.repoURL }} + desiredRevision: ${{ outputs.commit.commit }} diff --git a/bootstrap/argocd-repository.example.yaml b/bootstrap/argocd-repository.example.yaml new file mode 100644 index 0000000..a2b618e --- /dev/null +++ b/bootstrap/argocd-repository.example.yaml @@ -0,0 +1,13 @@ +# EXAMPLE ONLY. Do not commit a real token. +apiVersion: v1 +kind: Secret +metadata: + name: kub-web-test-repository + namespace: argocd + labels: + argocd.argoproj.io/secret-type: repository +stringData: + type: git + url: https://git.5vl.nl/5vl/kub-web-test.git + username: 5vl + password: REPLACE_WITH_GIT_TOKEN diff --git a/bootstrap/kargo-git-credentials.example.yaml b/bootstrap/kargo-git-credentials.example.yaml new file mode 100644 index 0000000..fe8dace --- /dev/null +++ b/bootstrap/kargo-git-credentials.example.yaml @@ -0,0 +1,13 @@ +# EXAMPLE ONLY. Do not commit a real token. +apiVersion: v1 +kind: Secret +metadata: + name: kub-web-test-git + namespace: web + labels: + kargo.akuity.io/cred-type: git +type: Opaque +stringData: + repoURL: https://git.5vl.nl/5vl/kub-web-test.git + username: 5vl + password: REPLACE_WITH_GIT_TOKEN diff --git a/templates/configmap.yaml b/templates/configmap.yaml new file mode 100644 index 0000000..b2b26e1 --- /dev/null +++ b/templates/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap + +metadata: + name: {{ .Release.Name }}-web-content + +data: + index.html: | + + + + + {{ .Values.environment }} - kub-web-test + + +

{{ .Values.environment }}

+

kub-web-test deployed with Helm, Argo CD and Kargo.

+ + diff --git a/templates/deployment.yaml b/templates/deployment.yaml new file mode 100644 index 0000000..0b35ff9 --- /dev/null +++ b/templates/deployment.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment + +metadata: + name: {{ .Release.Name }}-web + +spec: + replicas: {{ .Values.replicaCount }} + + selector: + matchLabels: + app: {{ .Release.Name }}-web + + template: + metadata: + labels: + app: {{ .Release.Name }}-web + + spec: + containers: + - name: nginx + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + + ports: + - containerPort: {{ .Values.service.port }} + + volumeMounts: + - name: web-content + mountPath: /usr/share/nginx/html + readOnly: true + + volumes: + - name: web-content + configMap: + name: {{ .Release.Name }}-web-content diff --git a/templates/ingress.yaml b/templates/ingress.yaml new file mode 100644 index 0000000..598a915 --- /dev/null +++ b/templates/ingress.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress + +metadata: + name: {{ .Release.Name }}-web + +spec: + ingressClassName: traefik + + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: {{ .Values.ingress.path }} + pathType: Prefix + backend: + service: + name: {{ .Release.Name }}-web + port: + number: {{ .Values.service.port }} diff --git a/templates/service.yaml b/templates/service.yaml new file mode 100644 index 0000000..c8539c7 --- /dev/null +++ b/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service + +metadata: + name: {{ .Release.Name }}-web + +spec: + selector: + app: {{ .Release.Name }}-web + + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} + + type: ClusterIP diff --git a/values-dev.yaml b/values-dev.yaml new file mode 100644 index 0000000..f2b4b55 --- /dev/null +++ b/values-dev.yaml @@ -0,0 +1,4 @@ +environment: DEV + +ingress: + host: web-dev.max.test.scrumdapp.open-ict.hu diff --git a/values-prod.yaml b/values-prod.yaml new file mode 100644 index 0000000..b495191 --- /dev/null +++ b/values-prod.yaml @@ -0,0 +1,4 @@ +environment: PROD + +ingress: + host: web-prod.max.test.scrumdapp.open-ict.hu diff --git a/values-staging.yaml b/values-staging.yaml new file mode 100644 index 0000000..b8bf121 --- /dev/null +++ b/values-staging.yaml @@ -0,0 +1,4 @@ +environment: STAGING + +ingress: + host: web-staging.max.test.scrumdapp.open-ict.hu diff --git a/values.yaml b/values.yaml new file mode 100644 index 0000000..5c0580c --- /dev/null +++ b/values.yaml @@ -0,0 +1,14 @@ +replicaCount: 2 + +image: + repository: nginx + tag: alpine + pullPolicy: IfNotPresent + +service: + port: 80 + +ingress: + path: / + +environment: LOCAL