ADR-001: CI/CD Implementation Approach¶
Status¶
Approved - Implemented
Context¶
The SyRF monorepo requires a comprehensive CI/CD pipeline that:
- Handles multiple services with independent versioning
- Builds and publishes Docker images
- Integrates with GitOps for Kubernetes deployment
- Avoids GitHub token limitations for workflow triggering
- Optimizes build times by detecting code vs non-code changes
Key challenges:
- GitHub's GITHUB_TOKEN doesn't trigger workflows when creating tags
- Monorepo requires path-based change detection
- Need to avoid rebuilding Docker images for non-code changes
Decision¶
Implement a single integrated workflow (auto-version.yml) that handles:
- Change detection (path-based)
- Version calculation (GitVersion)
- Tag creation
- Docker build and push
- Optional promotion PR creation
Workflow Architecture¶
name: Auto Version and Release
on:
push:
branches: [master]
paths:
- 'src/services/api/**'
- 'src/libs/**'
# Service-specific paths...
jobs:
detect-changes:
# Path-based change detection
version-and-release:
# Per-service: version → tag → build → push
Container Registry¶
Use GitHub Container Registry (GHCR):
- Registry:
ghcr.io - Organization:
camaradesuk - Image format:
ghcr.io/camaradesuk/syrf-{service} - Tags:
{version},{version}-sha.{shortsha},latest - Authentication:
GITHUB_TOKEN(no PAT required)
Chart Version Strategy¶
Helm Chart.yaml versions remain stable at 0.0.0:
- Version tracking via git tags only
- Deployments controlled by image tags
- Avoids unnecessary chart version bumps
Consequences¶
Positive¶
- Single Workflow: Avoids token triggering issues
- Path Filtering: Only builds changed services
- No PAT Required: Uses built-in GITHUB_TOKEN
- Build Optimization: Can retag for non-code changes
- GitOps Ready: Integrates with cluster-gitops repo
- Clear Flow: Linear progression through stages
Negative¶
- Large Workflow: More complex single file
- Sequential Steps: Can't parallelize version and build
- Monolithic: Harder to debug individual stages
Implementation Details¶
Change Detection¶
Services rebuild when these paths change:
api:
- src/services/api/**
- src/libs/kernel/**
- src/libs/mongo/**
- src/libs/appservices/**
# Dependencies based on DEPENDENCY-MAP.yaml
Build Optimization¶
Detect code vs non-code changes to avoid rebuilds:
# Compare files changed since last tag
LAST_TAG=$(git describe --tags --match "api-v*" --abbrev=0 HEAD~1)
CODE_CHANGES=$(git diff --name-only $LAST_TAG HEAD | grep -E '^src/')
if [ -z "$CODE_CHANGES" ]; then
# Retag existing image (saves 2-5 min)
crane cp ghcr.io/camaradesuk/syrf-api:$LAST_VERSION \
ghcr.io/camaradesuk/syrf-api:$NEW_VERSION
else
# Full Docker build required
docker build -t ghcr.io/camaradesuk/syrf-api:$NEW_VERSION .
fi
Docker Build Strategy¶
Multi-stage builds with caching:
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY --from=build /app .
ENTRYPOINT ["dotnet", "Service.dll"]
Promotion to Environments¶
After successful build:
- Create promotion PR to cluster-gitops
- Update
environments/{env}/{service}.values.yaml - Set
image.tag: {new-version} - ArgoCD syncs on merge
Alternatives Considered¶
Separate Workflows¶
Option: Keep version and release workflows separate
Rejected because:
- GITHUB_TOKEN can't trigger other workflows
- Would require PAT or GitHub App
- Added complexity and security concerns
Manual Triggering¶
Option: Require manual workflow_dispatch for releases
Rejected because:
- Reduces automation
- Prone to human error
- Slower feedback loop
Migration Status¶
Completed¶
- ✅ auto-version.yml workflow created
- ✅ Path-based change detection
- ✅ GitVersion integration
- ✅ Docker build implementation
- ✅ GHCR push configuration
- ✅ Multi-service support
Pending¶
- ⏳ Build optimization (retagging)
- ⏳ Promotion PR automation
- ⏳ S3-notifier service integration