From 8b54ac1b30ede08691d9d846cff9af095c1dbd54 Mon Sep 17 00:00:00 2001 From: Jonathan Dieu Date: Wed, 1 Jul 2026 19:58:00 -0700 Subject: [PATCH 1/4] feat: workload ApplicationSet + charts (portfolio, plausible, overengineered, mealie, changedetection, api) --- argocd/apps/workloads/appset.yaml | 63 +++++++++++++++++++ charts/workloads/api/Chart.yaml | 4 ++ charts/workloads/api/values.yaml | 7 +++ charts/workloads/changedetection/Chart.yaml | 4 ++ .../changedetection/templates/deployment.yaml | 34 ++++++++++ .../changedetection/templates/httproute.yaml | 14 +++++ .../changedetection/templates/pvc.yaml | 12 ++++ .../changedetection/templates/service.yaml | 10 +++ charts/workloads/changedetection/values.yaml | 18 ++++++ charts/workloads/mealie/Chart.yaml | 4 ++ .../mealie/templates/deployment.yaml | 37 +++++++++++ .../workloads/mealie/templates/httproute.yaml | 14 +++++ charts/workloads/mealie/templates/pvc.yaml | 12 ++++ .../workloads/mealie/templates/service.yaml | 10 +++ charts/workloads/mealie/values.yaml | 23 +++++++ charts/workloads/overengineered/Chart.yaml | 4 ++ charts/workloads/overengineered/values.yaml | 11 ++++ charts/workloads/plausible/Chart.yaml | 7 +++ charts/workloads/plausible/values.yaml | 9 +++ charts/workloads/portfolio/Chart.yaml | 4 ++ charts/workloads/portfolio/values.yaml | 8 +++ 21 files changed, 309 insertions(+) create mode 100644 argocd/apps/workloads/appset.yaml create mode 100644 charts/workloads/api/Chart.yaml create mode 100644 charts/workloads/api/values.yaml create mode 100644 charts/workloads/changedetection/Chart.yaml create mode 100644 charts/workloads/changedetection/templates/deployment.yaml create mode 100644 charts/workloads/changedetection/templates/httproute.yaml create mode 100644 charts/workloads/changedetection/templates/pvc.yaml create mode 100644 charts/workloads/changedetection/templates/service.yaml create mode 100644 charts/workloads/changedetection/values.yaml create mode 100644 charts/workloads/mealie/Chart.yaml create mode 100644 charts/workloads/mealie/templates/deployment.yaml create mode 100644 charts/workloads/mealie/templates/httproute.yaml create mode 100644 charts/workloads/mealie/templates/pvc.yaml create mode 100644 charts/workloads/mealie/templates/service.yaml create mode 100644 charts/workloads/mealie/values.yaml create mode 100644 charts/workloads/overengineered/Chart.yaml create mode 100644 charts/workloads/overengineered/values.yaml create mode 100644 charts/workloads/plausible/Chart.yaml create mode 100644 charts/workloads/plausible/values.yaml create mode 100644 charts/workloads/portfolio/Chart.yaml create mode 100644 charts/workloads/portfolio/values.yaml diff --git a/argocd/apps/workloads/appset.yaml b/argocd/apps/workloads/appset.yaml new file mode 100644 index 0000000..11385c5 --- /dev/null +++ b/argocd/apps/workloads/appset.yaml @@ -0,0 +1,63 @@ +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: workloads + namespace: argocd +spec: + goTemplate: true + generators: + - matrix: + generators: + - clusters: + selector: + matchExpressions: + - {key: purpose, operator: In, values: [prod, stage]} + - list: + elements: + - app: portfolio + namespace: portfolio + wave: "0" + - app: api + namespace: api + wave: "0" + - app: overengineered + namespace: overengineered + wave: "0" + - app: mealie + namespace: mealie + wave: "0" + - app: plausible + namespace: plausible + wave: "0" + - app: changedetection + namespace: changedetection + wave: "0" + template: + metadata: + name: "{{ .app }}-{{ .name }}" + annotations: + argocd.argoproj.io/sync-wave: "{{ .wave }}" + spec: + project: default + sources: + - repoURL: https://github.com/jonathandieu/dieubernetes + targetRevision: HEAD + ref: values + - repoURL: https://github.com/jonathandieu/dieubernetes + targetRevision: HEAD + path: "charts/workloads/{{ .app }}" + helm: + valueFiles: + - values.yaml + - "$values/clusters/{{ .name }}/overrides/{{ .app }}.yaml" + ignoreMissingValueFiles: true + destination: + server: "{{ .server }}" + namespace: "{{ .namespace }}" + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true diff --git a/charts/workloads/api/Chart.yaml b/charts/workloads/api/Chart.yaml new file mode 100644 index 0000000..84b245b --- /dev/null +++ b/charts/workloads/api/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: api +description: api.dieu.dev — portfolio content API (projects, work history) +version: 0.1.0 diff --git a/charts/workloads/api/values.yaml b/charts/workloads/api/values.yaml new file mode 100644 index 0000000..6ddb36b --- /dev/null +++ b/charts/workloads/api/values.yaml @@ -0,0 +1,7 @@ +image: + repository: ghcr.io/jonathandieu/api + tag: latest + +httproute: + hostnames: + - api.dieu.dev diff --git a/charts/workloads/changedetection/Chart.yaml b/charts/workloads/changedetection/Chart.yaml new file mode 100644 index 0000000..72f529f --- /dev/null +++ b/charts/workloads/changedetection/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: changedetection +description: changedetection.io — website change monitoring (custom chart, no official upstream) +version: 0.1.0 diff --git a/charts/workloads/changedetection/templates/deployment.yaml b/charts/workloads/changedetection/templates/deployment.yaml new file mode 100644 index 0000000..0a205b2 --- /dev/null +++ b/charts/workloads/changedetection/templates/deployment.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicas }} + strategy: + type: Recreate # single instance, PVC can't be multi-attached + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + spec: + containers: + - name: changedetection + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: 5000 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: datastore + mountPath: /datastore + volumes: + - name: datastore + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Release.Name }} + {{- else }} + emptyDir: {} + {{- end }} diff --git a/charts/workloads/changedetection/templates/httproute.yaml b/charts/workloads/changedetection/templates/httproute.yaml new file mode 100644 index 0000000..c41fa53 --- /dev/null +++ b/charts/workloads/changedetection/templates/httproute.yaml @@ -0,0 +1,14 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .Release.Name }} +spec: + parentRefs: + - name: envoy-gateway + namespace: envoy-gateway-system + hostnames: + {{- toYaml .Values.httproute.hostnames | nindent 4 }} + rules: + - backendRefs: + - name: {{ .Release.Name }} + port: 5000 diff --git a/charts/workloads/changedetection/templates/pvc.yaml b/charts/workloads/changedetection/templates/pvc.yaml new file mode 100644 index 0000000..926dff0 --- /dev/null +++ b/charts/workloads/changedetection/templates/pvc.yaml @@ -0,0 +1,12 @@ +{{- if .Values.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- end }} diff --git a/charts/workloads/changedetection/templates/service.yaml b/charts/workloads/changedetection/templates/service.yaml new file mode 100644 index 0000000..5cd93ea --- /dev/null +++ b/charts/workloads/changedetection/templates/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} +spec: + selector: + app: {{ .Release.Name }} + ports: + - port: 5000 + targetPort: 5000 diff --git a/charts/workloads/changedetection/values.yaml b/charts/workloads/changedetection/values.yaml new file mode 100644 index 0000000..0d307ee --- /dev/null +++ b/charts/workloads/changedetection/values.yaml @@ -0,0 +1,18 @@ +image: + repository: ghcr.io/dgtlmoon/changedetection.io + tag: "" # managed by Kargo + +replicas: 1 + +httproute: + hostnames: + - changes.dieu.dev + +persistence: + enabled: true + size: 1Gi + +resources: + requests: + cpu: 50m + memory: 128Mi diff --git a/charts/workloads/mealie/Chart.yaml b/charts/workloads/mealie/Chart.yaml new file mode 100644 index 0000000..34a5f00 --- /dev/null +++ b/charts/workloads/mealie/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: mealie +description: Mealie — self-hosted recipe manager (custom chart, no reliable upstream) +version: 0.1.0 diff --git a/charts/workloads/mealie/templates/deployment.yaml b/charts/workloads/mealie/templates/deployment.yaml new file mode 100644 index 0000000..7645ed8 --- /dev/null +++ b/charts/workloads/mealie/templates/deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ .Release.Name }} + spec: + containers: + - name: mealie + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: 9000 + env: + {{- range $k, $v := .Values.env }} + - name: {{ $k }} + value: {{ $v | quote }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: data + mountPath: /app/data + volumes: + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Release.Name }} + {{- else }} + emptyDir: {} + {{- end }} diff --git a/charts/workloads/mealie/templates/httproute.yaml b/charts/workloads/mealie/templates/httproute.yaml new file mode 100644 index 0000000..700e055 --- /dev/null +++ b/charts/workloads/mealie/templates/httproute.yaml @@ -0,0 +1,14 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .Release.Name }} +spec: + parentRefs: + - name: envoy-gateway + namespace: envoy-gateway-system + hostnames: + {{- toYaml .Values.httproute.hostnames | nindent 4 }} + rules: + - backendRefs: + - name: {{ .Release.Name }} + port: 9000 diff --git a/charts/workloads/mealie/templates/pvc.yaml b/charts/workloads/mealie/templates/pvc.yaml new file mode 100644 index 0000000..926dff0 --- /dev/null +++ b/charts/workloads/mealie/templates/pvc.yaml @@ -0,0 +1,12 @@ +{{- if .Values.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ .Release.Name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- end }} diff --git a/charts/workloads/mealie/templates/service.yaml b/charts/workloads/mealie/templates/service.yaml new file mode 100644 index 0000000..b062609 --- /dev/null +++ b/charts/workloads/mealie/templates/service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} +spec: + selector: + app: {{ .Release.Name }} + ports: + - port: 9000 + targetPort: 9000 diff --git a/charts/workloads/mealie/values.yaml b/charts/workloads/mealie/values.yaml new file mode 100644 index 0000000..183549b --- /dev/null +++ b/charts/workloads/mealie/values.yaml @@ -0,0 +1,23 @@ +image: + repository: ghcr.io/mealie-recipes/mealie + tag: "" # managed by Kargo + +replicas: 1 + +env: + ALLOW_SIGNUP: "false" + BASE_URL: "https://recipes.dieu.dev" + DB_ENGINE: sqlite + +httproute: + hostnames: + - recipes.dieu.dev + +persistence: + enabled: true + size: 1Gi + +resources: + requests: + cpu: 100m + memory: 256Mi diff --git a/charts/workloads/overengineered/Chart.yaml b/charts/workloads/overengineered/Chart.yaml new file mode 100644 index 0000000..14a336d --- /dev/null +++ b/charts/workloads/overengineered/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: overengineered +description: overengineered.dieu.dev — live cluster dashboard + architecture explainer +version: 0.1.0 diff --git a/charts/workloads/overengineered/values.yaml b/charts/workloads/overengineered/values.yaml new file mode 100644 index 0000000..cc7f030 --- /dev/null +++ b/charts/workloads/overengineered/values.yaml @@ -0,0 +1,11 @@ +image: + repository: ghcr.io/jonathandieu/overengineered + tag: latest + +httproute: + hostnames: + - overengineered.dieu.dev + +# status.dieu.dev is a Cloudflare Worker — configured at deploy time, not here +env: + STATUS_API_URL: "https://status.dieu.dev" diff --git a/charts/workloads/plausible/Chart.yaml b/charts/workloads/plausible/Chart.yaml new file mode 100644 index 0000000..0b8394c --- /dev/null +++ b/charts/workloads/plausible/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: plausible +version: 0.1.0 +dependencies: + - name: plausible-analytics + version: "0.4.2" + repository: https://8gears.container-registry.com/chartrepo/library diff --git a/charts/workloads/plausible/values.yaml b/charts/workloads/plausible/values.yaml new file mode 100644 index 0000000..404f3be --- /dev/null +++ b/charts/workloads/plausible/values.yaml @@ -0,0 +1,9 @@ +plausible-analytics: # 8gears/plausible-analytics + image: + tag: "" # managed by Kargo + + ingress: + enabled: false # routing via Envoy Gateway HTTPRoute + + baseURL: "https://analytics.dieu.dev" + disableRegistration: true diff --git a/charts/workloads/portfolio/Chart.yaml b/charts/workloads/portfolio/Chart.yaml new file mode 100644 index 0000000..1f57c04 --- /dev/null +++ b/charts/workloads/portfolio/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: portfolio +description: Personal portfolio site — dieu.dev +version: 0.1.0 diff --git a/charts/workloads/portfolio/values.yaml b/charts/workloads/portfolio/values.yaml new file mode 100644 index 0000000..5548465 --- /dev/null +++ b/charts/workloads/portfolio/values.yaml @@ -0,0 +1,8 @@ +image: + repository: ghcr.io/jonathandieu/portfolio + tag: latest + +httproute: + hostnames: + - dieu.dev + - www.dieu.dev From 34ca73e40ce53a2bfd97f28f7ceeb77514416e83 Mon Sep 17 00:00:00 2001 From: Jonathan Dieu Date: Thu, 2 Jul 2026 07:46:02 -0700 Subject: [PATCH 2/4] fix(plausible): point at imio's mirror, 8gears chartrepo is dead 8gears.container-registry.com/chartrepo/library now serves a Harbor web UI instead of a valid Helm index. imio.github.io/helm-charts mirrors the same plausible-analytics chart at the identical version (0.4.2), so values.yaml needs no changes. --- charts/workloads/plausible/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/workloads/plausible/Chart.yaml b/charts/workloads/plausible/Chart.yaml index 0b8394c..094b0e6 100644 --- a/charts/workloads/plausible/Chart.yaml +++ b/charts/workloads/plausible/Chart.yaml @@ -4,4 +4,4 @@ version: 0.1.0 dependencies: - name: plausible-analytics version: "0.4.2" - repository: https://8gears.container-registry.com/chartrepo/library + repository: https://imio.github.io/helm-charts From 176550f2e7916ea20d146444503d3389eaf2c282 Mon Sep 17 00:00:00 2001 From: Jonathan Dieu Date: Fri, 3 Jul 2026 19:02:47 -0700 Subject: [PATCH 3/4] fix(workloads): drop portfolio, api, overengineered until images exist None of the three have a source repo or built image yet. Keeping mealie, plausible, and changedetection, which use real upstream images. --- argocd/apps/workloads/appset.yaml | 9 --------- charts/workloads/api/Chart.yaml | 4 ---- charts/workloads/api/values.yaml | 7 ------- charts/workloads/overengineered/Chart.yaml | 4 ---- charts/workloads/overengineered/values.yaml | 11 ----------- charts/workloads/portfolio/Chart.yaml | 4 ---- charts/workloads/portfolio/values.yaml | 8 -------- 7 files changed, 47 deletions(-) delete mode 100644 charts/workloads/api/Chart.yaml delete mode 100644 charts/workloads/api/values.yaml delete mode 100644 charts/workloads/overengineered/Chart.yaml delete mode 100644 charts/workloads/overengineered/values.yaml delete mode 100644 charts/workloads/portfolio/Chart.yaml delete mode 100644 charts/workloads/portfolio/values.yaml diff --git a/argocd/apps/workloads/appset.yaml b/argocd/apps/workloads/appset.yaml index 11385c5..c4f8bb0 100644 --- a/argocd/apps/workloads/appset.yaml +++ b/argocd/apps/workloads/appset.yaml @@ -14,15 +14,6 @@ spec: - {key: purpose, operator: In, values: [prod, stage]} - list: elements: - - app: portfolio - namespace: portfolio - wave: "0" - - app: api - namespace: api - wave: "0" - - app: overengineered - namespace: overengineered - wave: "0" - app: mealie namespace: mealie wave: "0" diff --git a/charts/workloads/api/Chart.yaml b/charts/workloads/api/Chart.yaml deleted file mode 100644 index 84b245b..0000000 --- a/charts/workloads/api/Chart.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v2 -name: api -description: api.dieu.dev — portfolio content API (projects, work history) -version: 0.1.0 diff --git a/charts/workloads/api/values.yaml b/charts/workloads/api/values.yaml deleted file mode 100644 index 6ddb36b..0000000 --- a/charts/workloads/api/values.yaml +++ /dev/null @@ -1,7 +0,0 @@ -image: - repository: ghcr.io/jonathandieu/api - tag: latest - -httproute: - hostnames: - - api.dieu.dev diff --git a/charts/workloads/overengineered/Chart.yaml b/charts/workloads/overengineered/Chart.yaml deleted file mode 100644 index 14a336d..0000000 --- a/charts/workloads/overengineered/Chart.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v2 -name: overengineered -description: overengineered.dieu.dev — live cluster dashboard + architecture explainer -version: 0.1.0 diff --git a/charts/workloads/overengineered/values.yaml b/charts/workloads/overengineered/values.yaml deleted file mode 100644 index cc7f030..0000000 --- a/charts/workloads/overengineered/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -image: - repository: ghcr.io/jonathandieu/overengineered - tag: latest - -httproute: - hostnames: - - overengineered.dieu.dev - -# status.dieu.dev is a Cloudflare Worker — configured at deploy time, not here -env: - STATUS_API_URL: "https://status.dieu.dev" diff --git a/charts/workloads/portfolio/Chart.yaml b/charts/workloads/portfolio/Chart.yaml deleted file mode 100644 index 1f57c04..0000000 --- a/charts/workloads/portfolio/Chart.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v2 -name: portfolio -description: Personal portfolio site — dieu.dev -version: 0.1.0 diff --git a/charts/workloads/portfolio/values.yaml b/charts/workloads/portfolio/values.yaml deleted file mode 100644 index 5548465..0000000 --- a/charts/workloads/portfolio/values.yaml +++ /dev/null @@ -1,8 +0,0 @@ -image: - repository: ghcr.io/jonathandieu/portfolio - tag: latest - -httproute: - hostnames: - - dieu.dev - - www.dieu.dev From 01bcf62b1194a8c1607e607f0a54f354c8cac5b4 Mon Sep 17 00:00:00 2001 From: Jonathan Dieu Date: Fri, 3 Jul 2026 20:17:12 -0700 Subject: [PATCH 4/4] fix: address copilot review comments on workload charts Fall back to :latest when image.tag is empty, so mealie and changedetection can deploy before Kargo's first promotion sets a real tag. Add Recreate strategy to mealie, matching changedetection, to avoid multi-attach errors on a ReadWriteOnce PVC. Pin releaseName on the workloads appset for stable resource naming. Add plausible's missing HTTPRoute, it had no route into the cluster at all. --- argocd/apps/workloads/appset.yaml | 1 + .../changedetection/templates/deployment.yaml | 2 +- charts/workloads/mealie/templates/deployment.yaml | 4 +++- .../workloads/plausible/templates/httproute.yaml | 14 ++++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 charts/workloads/plausible/templates/httproute.yaml diff --git a/argocd/apps/workloads/appset.yaml b/argocd/apps/workloads/appset.yaml index c4f8bb0..f1013a8 100644 --- a/argocd/apps/workloads/appset.yaml +++ b/argocd/apps/workloads/appset.yaml @@ -38,6 +38,7 @@ spec: targetRevision: HEAD path: "charts/workloads/{{ .app }}" helm: + releaseName: "{{ .app }}" valueFiles: - values.yaml - "$values/clusters/{{ .name }}/overrides/{{ .app }}.yaml" diff --git a/charts/workloads/changedetection/templates/deployment.yaml b/charts/workloads/changedetection/templates/deployment.yaml index 0a205b2..ea34fa2 100644 --- a/charts/workloads/changedetection/templates/deployment.yaml +++ b/charts/workloads/changedetection/templates/deployment.yaml @@ -16,7 +16,7 @@ spec: spec: containers: - name: changedetection - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default "latest" }}" ports: - containerPort: 5000 resources: diff --git a/charts/workloads/mealie/templates/deployment.yaml b/charts/workloads/mealie/templates/deployment.yaml index 7645ed8..a22e0b0 100644 --- a/charts/workloads/mealie/templates/deployment.yaml +++ b/charts/workloads/mealie/templates/deployment.yaml @@ -4,6 +4,8 @@ metadata: name: {{ .Release.Name }} spec: replicas: {{ .Values.replicas }} + strategy: + type: Recreate # single instance, PVC can't be multi-attached selector: matchLabels: app: {{ .Release.Name }} @@ -14,7 +16,7 @@ spec: spec: containers: - name: mealie - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default "latest" }}" ports: - containerPort: 9000 env: diff --git a/charts/workloads/plausible/templates/httproute.yaml b/charts/workloads/plausible/templates/httproute.yaml new file mode 100644 index 0000000..03289af --- /dev/null +++ b/charts/workloads/plausible/templates/httproute.yaml @@ -0,0 +1,14 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .Release.Name }} +spec: + parentRefs: + - name: envoy-gateway + namespace: envoy-gateway-system + hostnames: + - analytics.dieu.dev + rules: + - backendRefs: + - name: {{ .Release.Name }}-plausible-analytics + port: 80