GitHub Actions CI/CD

GitHub Actions handles continuous integration and deployment. Each service repository contains branch-specific workflows that call reusable workflows from the parent POM repository (christhonie/event).

Reusable Workflows

Reusable workflows live in christhonie/event/.github/workflows/ and are called from service repositories using uses: christhonie/event/.github/workflows/<name>.yml@main.

maven-package.yml

Builds and packages the Maven project.

Input Description

maven-profiles

Maven profiles to activate (default: dev)

jdk-version

JDK version (default: 17)

require-npm

Whether to set up Node.js and npm (default: false)

node-version

Node.js version when npm is required (default: 22)

Key behaviour:

  • Caches Maven dependencies with run_id to refresh SNAPSHOTs each build

  • Removes cached SNAPSHOT directories before build

  • Caches the target/ directory for downstream jobs (docker-build, helm-build)

docker-build.yml

Builds a Docker image using Jib and pushes it to Docker Hub.

Input Description

maven-profiles

Maven profiles to activate (default: dev)

jdk-version

JDK version (default: 17)

Output Description

image-tag

The Docker image tag (Maven project version, e.g. 2.0.0-SNAPSHOT)

The image tag is the Maven project version, extracted via mvn help:evaluate. This output is consumed by the argocd-update job.

helm-build.yml

Packages the Helm chart and pushes it to Docker Hub as an OCI artifact. See Helm Configuration for chart structure details.

Output Description

chart-version

The Helm chart version that was packaged (e.g. 2.3.13-SNAPSHOT-RELEASE)

Key details:

  • Restores the cached target/ directory from maven-package

  • Creates a placeholder settings-security.xml (required by helm-maven-plugin 6.17.0)

  • Uses Helm CLI for registry login (not the Maven helm:registry-login goal, which stores credentials under the wrong registry key)

  • Uses continue-on-error: true to tolerate duplicate OCI tag pushes on SNAPSHOT rebuilds

  • Runs Helm goals in a single Maven invocation:

    mvn helm:init helm:package helm:push
The helm:registry-login goal is intentionally omitted. It stores credentials under registry-1.docker.io/christhonie instead of registry-1.docker.io, causing 401 errors on push. The workflow uses helm registry login CLI command before the Maven invocation instead.

argocd-update.yml

Updates the ArgoCD manifest in the GitOps repository to trigger a deployment.

Input Description

environment

Target environment (dev or stage)

service-name

Service name matching the ArgoCD manifest filename (e.g. membership-ui)

chart-version

Helm chart version to deploy — updates spec.source.targetRevision (optional)

image-tag

Docker image tag override (optional — chart appVersion is used when omitted)

build-sha

Git commit SHA for forcing SNAPSHOT rollouts (optional)

argocd-repo

ArgoCD repository (default: christhonie/idl-xnl-jhb-rc01)

This workflow:

  1. Checks out the ArgoCD repository using ARGOCD_REPO_TOKEN

  2. If chart-version is provided, updates .spec.source.targetRevision so ArgoCD pulls the correct chart from the OCI registry

  3. If image-tag is provided, updates .spec.source.helm.valuesObject.image.tag — typically omitted because the chart’s appVersion defaults to the correct Docker image tag

  4. If build-sha is provided, sets a podAnnotations."app.kubernetes.io/build-sha" value to force pod recreation even when the image tag is unchanged (important for SNAPSHOT rebuilds)

  5. Commits and pushes with retry logic (pull --rebase on conflict)

Branch Workflows

Each service has two main workflow files.

push-dev.yml (develop branch)

Triggered on push to develop. Runs the full CI pipeline including tests.

paths-filter ──► test-fe ──► package ──► docker-build ──► helm-build ──► update-argocd-dev
               └ test-be ──┘          ├── publish
                                      └── dependencygraph

Key features:

  • Path filtering: Uses dorny/paths-filter to skip unnecessary jobs (e.g. skip backend tests if only frontend changed)

  • Conditional execution: Test jobs only run when relevant files change; downstream jobs use always() with result checks to handle skipped dependencies

  • Helm chart built on every push: Ensures chart and Docker image are always in lock-step

  • ArgoCD update: Passes chart-version and build-sha: ${{ github.sha }} — the chart version sets targetRevision, and the build SHA forces SNAPSHOT rollouts

Example workflow call:

helm-build:
  name: Helm
  needs: [docker-build]
  if: always() && needs.docker-build.result == 'success'
  uses: christhonie/event/.github/workflows/helm-build.yml@main
  with:
    maven-profiles: dev,webapp
    jdk-version: 17
  secrets:
    DOCKER_PAT: ${{ secrets.DOCKER_PAT }}

update-argocd-dev:
  name: Deploy Dev
  needs: [helm-build]
  if: always() && needs.helm-build.result == 'success'
  uses: christhonie/event/.github/workflows/argocd-update.yml@main
  with:
    environment: dev
    service-name: membership-ui
    chart-version: ${{ needs.helm-build.outputs.chart-version }}
    build-sha: ${{ github.sha }}
  secrets:
    ARGOCD_REPO_TOKEN: ${{ secrets.ARGOCD_REPO_TOKEN }}

push-main.yml (main branch)

Triggered on push to main (typically via Gitflow release finish). No tests — assumes code was tested on develop.

package ──► docker-build ──► helm-build ──► update-argocd-stage
          ├── publish
          └── gitflow-release-finish

Key differences from develop:

  • Uses prod,webapp Maven profiles

  • Helm build depends on docker-build (same as develop)

  • Updates ArgoCD stage environment with chart-version only (no build-sha since image tag changes on release)

  • Triggers Gitflow release finish workflow

Required Secrets

Secret Purpose

EVENT_PACKAGE_REPO_TOKEN

GitHub Packages token for Maven dependencies (mapped to MAVEN_PASSWORD)

DOCKER_PAT

Docker Hub Personal Access Token for image and Helm chart push

ARGOCD_REPO_TOKEN

GitHub PAT with write access to the ArgoCD repository