ArgoCD Deployment

ArgoCD manages Kubernetes deployments using a GitOps pattern. Application manifests are stored in a dedicated repository and ArgoCD automatically syncs the desired state to the cluster.

Repository Structure

The ArgoCD manifests live in christhonie/idl-xnl-jhb-rc01:

argocd/
├── event-admin-service-dev.yml
├── event-admin-service-stage.yml
├── event-admin-service-prod.yml
├── membership-ui-dev.yml
├── membership-ui-stage.yml
├── membership-ui-prod.yml
├── registration-portal-dev.yml
├── registration-portal-stage.yml
└── registration-portal-prod.yml

Each file is a standalone ArgoCD Application resource. The naming convention is <service-name>-<environment>.yml.

App-of-Apps Pattern

An app-of-apps Application (named idl-xnl-jhb1-rc01) watches the argocd/ directory and manages all child Applications. This parent Application must have auto-sync enabled to pick up new or modified child manifests.

Application Manifest Structure

Each ArgoCD Application manifest follows this structure:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: membership-ui-dev              (1)
  namespace: argocd
spec:
  project: default
  destination:
    name: idl-xnl-jhb1-rc01            (2)
    namespace: event-dev                (3)
  source:
    repoURL: registry-1.docker.io      (4)
    chart: christhonie/membership-ui
    targetRevision: 2.0.0-SNAPSHOT-RELEASE  (5)
    helm:
      releaseName: dev-membership-ui
      valuesObject:                     (6)
        config:
          profiles: "dev,kubernetes,api-docs"
          existingsecret: event-admin-service
          db:
            url: mysql://host:port/db_name?params
            username: dev
          services:
            eventadminservice: http://dev-event-admin-service
            apikey: "..."
          mail:
            from: [email protected]
          logging:
            level:
              ROOT: DEBUG
        image:
          pullPolicy: Always              (1)
        imagePullSecrets:
          - name: christhonie-docker
        ingress:
          enabled: true
          className: "nginx"
          annotations:
            "cert-manager.io/cluster-issuer": "letsencrypt-prod"
            "external-dns.alpha.kubernetes.io/cloudflare-proxied": "false"
          hostname: service-dev.idealogic.co.za
          pathType: Prefix
          tls: true
        podAnnotations:                 (7)
          app.kubernetes.io/build-sha: <git-sha>
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false                 (8)
    syncOptions:
      - CreateNamespace=true
  revisionHistoryLimit: 3               (9)
1 Unique Application name: <service>-<env>
2 Target cluster name
3 Kubernetes namespace per environment
4 OCI registry for Helm charts
5 Chart version (Maven version + -RELEASE)
6 Helm values inline — overrides values.yaml from the chart
7 image.tag is intentionally omitted — the chart’s appVersion defaults to the correct Docker image tag via {{ .Values.image.tag | default .Chart.AppVersion }} in the deployment template
8 Pod annotation to force rollout on SNAPSHOT rebuilds (set by CI)
9 Prevent accidental deletion of all resources
10 Limit stored revision history

Environment Conventions

Setting Dev Stage Prod Notes

Namespace

event-dev

event-stage

event-prod

Spring Profiles

dev,kubernetes,api-docs

prod,kubernetes,api-docs

prod,kubernetes,api-docs

Dev includes api-docs

Logging Level

DEBUG

DEBUG

INFO

Prod must be INFO

Image Pull Policy

Always

Always

IfNotPresent

Prod uses fixed releases

build-sha Annotation

Yes

No

No

Only for SNAPSHOT rollouts

allowEmpty

false

false

false

Always set explicitly

Liquibase Contexts

dev,faker

(none)

(none)

Faker data only in dev

Database URL Pattern

Database URLs in ArgoCD manifests use the mysql:// format (without jdbc: prefix):

db:
  url: mysql://idealogic-prod.mysql.svc.cluster.local:6446/database_name?useUnicode=true&characterEncoding=utf8

The Helm chart’s ConfigMap template prepends jdbc: automatically:

url: {{ printf "jdbc:%s" .Values.config.db.url }}
The deployed Helm chart version must contain the printf template. If you change the manifest URL format before the chart is updated, the application will fail with URL must start with 'jdbc'.

Database Naming Convention

Service Database Username

admin-service

event_admin_service_dev

dev / event-admin-stage / event-admin-prod

membership-ui

membership_ui_dev

dev / event-membership-stage / event-membership-prod

registration-portal

registration_portal_dev

dev / event-portal-stage / event-portal-prod

Shared Secrets

Services in the same namespace share a Kubernetes Secret referenced by config.existingsecret. The secret contains the database password and other shared credentials.

SNAPSHOT Deployment Strategy

SNAPSHOT versions use the same image tag for every build. To force Kubernetes to pull the latest image and restart pods:

  1. The argocd-update.yml workflow sets chart-version (updating targetRevision) and build-sha (updating podAnnotations."app.kubernetes.io/build-sha")

  2. Since SNAPSHOT chart versions may already exist in the registry, the Helm push uses continue-on-error to tolerate duplicate tags

  3. The build-sha annotation change triggers a pod rollout even though the chart version and image tag are unchanged

  4. Image pull policy is set to Always for dev and stage environments

Forcing a Hard Refresh

If ArgoCD has cached a stale chart version, force a hard refresh:

export KUBECONFIG=/mnt/c/Users/chris/.kube/static/aks-rancher-idealogic.yaml

kubectl -n argocd patch application <app-name> \
    --type merge \
    -p '{"metadata":{"annotations":{"argocd.argoproj.io/refresh":"hard"}}}'

Monitoring Deployments

Check pod status on the workload cluster:

export KUBECONFIG=/mnt/c/Users/chris/.kube/static/idl-xnl-jhb1-01.yaml

# Check pods in a specific namespace
kubectl -n event-dev get pods

# View logs for a specific pod
kubectl -n event-dev logs <pod-name> --tail=100

# Check events for troubleshooting
kubectl -n event-dev get events --sort-by='.lastTimestamp'

Common Issues

Liquibase Checksum Mismatch

After upgrading JHipster, the Liquibase changeset order may change without altering the schema. Clear the checksum to allow re-validation:

UPDATE DATABASECHANGELOG SET MD5SUM = NULL WHERE ID = '00000000000001';
Chart Not Found

Ensure the Helm chart has been published with the exact version referenced in targetRevision. Charts are built on every push to both develop and main.