GitHub Actions CI/CD Architecture
1. Overview
This guide documents the CI/CD pipeline architecture used across Event and Membership Management projects. The system uses a combination of reusable workflows (defined centrally) and project-specific workflows that consume them.
1.1. Key Principles
-
DRY (Don’t Repeat Yourself) - Common build logic is centralized in reusable workflows
-
Consistency - All projects follow the same patterns and conventions
-
Conditional Execution - Only run tests for changed components (frontend/backend)
-
GitOps - Deployments are managed through ArgoCD and Git-based configuration
2. Workflow Architecture
The CI/CD system consists of two layers:
- Reusable Workflows (in
christhonie/event/.github/workflows/) -
Centrally managed, versioned workflow definitions that encapsulate common operations like testing, building, and deploying.
- Project Workflows (in each repository’s
.github/workflows/) -
Project-specific workflows that orchestrate the reusable workflows and define triggers.
3. Path Filtering Strategy
3.1. Excluding Non-Build Directories
Use paths-ignore at the workflow trigger level to prevent unnecessary builds when only documentation or configuration files change:
on:
push:
branches:
- develop
# NOTE: Keep paths-ignore in sync with push-main.yml and pr-non-main.yml
paths-ignore:
- '*.md'
- '*.adoc'
- '.devcontainer/**'
- '.husky/**'
- '.jhipster/**'
- 'docs/**'
- 'src/main/helm/**'
When modifying the paths-ignore list, update it in all workflow files that share this pattern. The sync note comment serves as a reminder.
|
3.2. Conditional Job Execution
Use the dorny/paths-filter action to conditionally run frontend or backend tests based on what files changed:
jobs:
paths-filter:
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
frontend:
- '.github/workflows/**'
- 'package*.json'
- 'angular.json'
- 'tsconfig*.json'
- 'webpack/**'
- 'src/main/webapp/**'
backend:
- '.github/workflows/**'
- 'pom.xml'
- 'src/main/java/**'
- 'src/main/resources/**'
- 'src/test/java/**'
- 'src/test/resources/**'
test-fe:
needs: paths-filter
if: needs.paths-filter.outputs.frontend == 'true'
uses: christhonie/event/.github/workflows/test-fe.yml@main
# ...
test-be:
needs: paths-filter
if: needs.paths-filter.outputs.backend == 'true'
uses: christhonie/event/.github/workflows/test-be.yml@main
# ...
4. Reusable Workflows Reference
The following reusable workflows are available in christhonie/event/.github/workflows/:
| Workflow | Purpose | Inputs | Secrets | Outputs |
|---|---|---|---|---|
|
Run backend tests using Maven |
|
|
- |
|
Run frontend tests using npm |
|
|
- |
|
Build and cache Maven artifacts |
|
|
cached target |
|
Deploy JAR to GitHub Packages |
|
|
- |
|
Build and push Docker image via JIB |
|
|
|
|
Package and push Helm charts |
|
|
- |
|
Update ArgoCD deployment manifests |
|
|
- |
|
Submit dependency graph to GitHub |
|
- |
- |
|
Upload build artifacts |
|
- |
- |
|
Complete GitFlow release process |
|
- |
- |
5. Pipeline Flows
5.1. Pull Request Pipeline
When a PR is created or updated against non-main branches:
PR created/updated
│
▼
paths-filter
│
├──► test-fe (if frontend changed)
│
└──► test-be (if backend changed)
│
▼
All tests must pass for merge
5.2. Develop Branch Pipeline
When code is pushed to the develop branch:
Push to develop
│
▼
paths-filter
│
├──► test-fe ──┐
│ │
└──► test-be ──┤
│
▼
package
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
publish docker-build dependencygraph
6. Consuming Workflows
6.1. Referencing Reusable Workflows
Project workflows reference reusable workflows using the uses keyword:
jobs:
test-be:
uses: christhonie/event/.github/workflows/test-be.yml@main
with:
maven-profiles: dev
jdk-version: '17'
secrets:
MAVEN_PASSWORD: ${{ secrets.EVENT_PACKAGE_REPO_TOKEN }}
6.2. Versioning Strategy
Recommended: Use @main to stay current with the latest reusable workflow improvements.
uses: christhonie/event/.github/workflows/test-be.yml@main
Alternative: Pin to a specific tag for stability when needed:
uses: christhonie/event/.github/workflows/[email protected]
7. Job Dependencies and Caching
7.1. Sequential Execution with needs
Use needs to define job dependencies:
jobs:
package:
uses: christhonie/event/.github/workflows/maven-package.yml@main
# ...
docker-build:
needs: [package] # Wait for package to complete
uses: christhonie/event/.github/workflows/docker-build.yml@main
# ...
8. Environment Variables Pattern
Centralize fallback logic at the job level to avoid repetition:
jobs:
helm-build:
runs-on: ubuntu-latest
env:
JDK_VERSION: ${{ inputs.jdk-version || '17' }}
MAVEN_PROFILES: ${{ inputs.maven-profiles || 'dev' }}
steps:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: ${{ env.JDK_VERSION }}
# ...
- name: Package Helm
run: mvn helm:package -P${{ env.MAVEN_PROFILES }}
9. Secrets Configuration
9.1. Required Secrets
| Secret | Purpose | Used By |
|---|---|---|
|
Built-in token for repository operations |
Git operations, GitHub API |
|
Standard secret name for GitHub Packages access (Maven/NPM) |
|
|
Docker Hub Personal Access Token |
|
|
Access to ArgoCD configuration repository |
|
9.2. Secret Variable Mapping
The EVENT_PACKAGE_REPO_TOKEN secret is internally mapped to workflow-specific variables:
# In workflow steps
secrets:
MAVEN_PASSWORD: ${{ secrets.EVENT_PACKAGE_REPO_TOKEN }}
NPM_PASSWORD: ${{ secrets.EVENT_PACKAGE_REPO_TOKEN }}
9.3. Maven Repository Configuration
The setup-java action creates a settings.xml file with credentials:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
server-id: github-christhonie
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Build with Maven
run: mvn --batch-mode package
env:
MAVEN_USERNAME: christhonie
MAVEN_PASSWORD: ${{ secrets.EVENT_PACKAGE_REPO_TOKEN }}
The generated settings.xml will contain:
<servers>
<server>
<id>github-christhonie</id>
<username>${env.MAVEN_USERNAME}</username>
<password>${env.MAVEN_PASSWORD}</password>
</server>
</servers>
10. Artifact Management
11. Docker Compose Version Synchronization
11.1. Pattern Overview
Projects can automatically synchronize Docker Compose file versions with POM versions:
-
Store image versions in
pom.xmlproperties (<revision>,<admin-service.version>) -
Workflow triggers when
pom.xmlchanges on develop branch -
Extract versions using grep/sed
-
Update Docker Compose files (
dev.yml,admin-service.yml) -
Auto-commit changes with bot attribution
11.2. Example Implementation
Reference: event-admin-ui/.github/workflows/sync-docker-versions.yml
name: '🔄 Sync Docker Compose Versions'
on:
push:
branches:
- develop
paths:
- 'pom.xml'
env:
DOCKER_REGISTRY: christhonie
GATEWAY_IMAGE_NAME: event-admin-ui
ADMIN_IMAGE_NAME: event-admin-service
jobs:
sync-versions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extract versions from POM
id: versions
run: |
REVISION=$(grep -oP '(?<=<revision>)[^<]+' pom.xml | head -1)
echo "revision=$REVISION" >> $GITHUB_OUTPUT
- name: Update Docker Compose files
run: |
sed -i "s|${DOCKER_REGISTRY}/${GATEWAY_IMAGE_NAME}:[^[:space:]]*|${DOCKER_REGISTRY}/${GATEWAY_IMAGE_NAME}:${{ steps.versions.outputs.revision }}|g" src/main/docker/dev.yml
- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git commit -am "[AutoTask] Sync Docker image versions"
git push
|
TODO: Standardize |
12. Version Strategy for Docker/Helm Artifacts
|
TODO: Implement build number conversion for SNAPSHOT versions:
|
13. Related Documentation
-
Development Workflow - GitFlow branching and release process
-
Helm Chart Patterns - Helm chart structure and configuration
-
ArgoCD Deployment - GitOps deployment patterns
-
Manual Helm Chart Release - Manual Helm release workflow