Skip to content

CI/CD Workflow Overview

Purpose

This document explains the complete structure and execution flow of the ci-cd.yml GitHub Actions workflow, which handles versioning, building, and deploying all SyRF services.

Workflow File

Location: .github/workflows/ci-cd.yml

Trigger: Push to main branch, or manual workflow dispatch

Complete Workflow Structure

┌─────────────────────────────────────────────────────────────────┐
│ 1. detect-changes                                               │
│    Path-based filtering determines which services changed       │
│    Outputs: api_changed, pm_changed, quartz_changed,            │
│             web_changed, s3_notifier_changed                    │
└─────────────────────────────────────────────────────────────────┘
    ┌─────────────────────────┼─────────────────────────┐
    │                         │                         │
    ▼                         ▼                         ▼
┌────────────────┐  ┌─────────────────┐  ┌─────────────────────────┐
│ 2. version-*   │  │ 2.5 test-dotnet │  │ 2e. version-s3-notifier │
│  (parallel)    │  │  (parallel)     │  │   (if s3_notifier       │
│                │  │                 │  │    changed)             │
│ version-api    │  │ - Run xUnit     │  │                         │
│ version-pm     │  │ - Upload        │  │ Uses GitVersion         │
│ version-quartz │  │   coverage      │  │ Outputs: version, sha   │
│ version-web    │  │                 │  └────────────┬────────────┘
│                │  ├─────────────────┤               │
│ Uses GitVersion│  │ 2.5 test-web    │               │
│ Outputs:       │  │  (parallel)     │               │
│  version, sha  │  │                 │               │
└───────┬────────┘  │ - Run Vitest    │               │
        │           │ - Upload        │               │
        │           │   coverage      │               │
        │           └────────┬────────┘               │
        │                    │                        │
        │    ┌───────────────┴───────────────┐        │
        │    │ BLOCKS BUILD IF TESTS FAIL    │        │
        │    └───────────────┬───────────────┘        │
        │                    │                        │
        ▼                    ▼                        ▼
┌───────────────────────────────────────┐  ┌─────────────────────────┐
│ 3. build-and-push-images              │  │ 4. deploy-lambda        │
│    (Docker services)                  │  │    (S3 Notifier only)   │
│                                       │  │                         │
│ - Build .NET images                   │  │ - Build Lambda package  │
│ - Push to GHCR                        │  │ - Deploy to AWS Lambda  │
│ - Tags: version, version-sha          │  │ - Upload package        │
│                                       │  │                         │
│ REQUIRES: test-dotnet AND test-web    │  │                         │
│           to pass (or be skipped)     │  │                         │
└─────────────────┬─────────────────────┘  └───────────┬─────────────┘
                  │                                    │
                  ├────────────┬───────────────────────┘
                  │            │
       ┌──────────▼────────┐   │
       │ 5. promote-to-    │   │
       │    staging        │   │
       │  (Docker only)    │   │
       │                   │   │
       │ - Clone gitops    │   │
       │ - Update values   │   │
       │ - Create PR       │   │
       └──────────┬────────┘   │
              │           │
              └─────┬─────┘
     ┌──────────────▼────────────────────┐
     │ 6. create-and-push-tags           │
     │    (Runs AFTER all builds)        │
     │                                   │
     │ ONLY creates tags if both:        │
     │ 1. Versioning succeeded           │
     │ 2. Build/deployment succeeded     │
     │                                   │
     │ Tags: {service}-v{version}        │
     │ NO ORPHANED TAGS                  │
     └──────────────┬────────────────────┘
     ┌──────────────▼────────────────────┐
     │ 7. create-lambda-release          │
     │    (S3 Notifier only)             │
     │                                   │
     │ - Download Lambda package         │
     │ - Create GitHub Release           │
     │ - Attach package as artifact      │
     └───────────────────────────────────┘

Job Details

1. detect-changes

Purpose: Determine which services need building based on changes since last tag

Implementation: Uses tag-based detection script (.github/scripts/detect-service-changes.sh)

How it works:

  1. For each service, find the last matching git tag (e.g., api-v8.21.0)
  2. Compare source files against that tag using git diff
  3. Check if Docker image exists in GHCR for that version
  4. Determine action: build, retag, skip

Source Paths Checked:

  • api: src/services/api/**, src/libs/kernel/**, src/libs/mongo/**, etc.
  • pm: src/services/project-management/**, plus shared libraries
  • quartz: src/services/quartz/**, plus dependencies
  • web: src/services/web/**
  • user_guide: user-guide/**
  • docs: docs/**, mkdocs.yml
  • s3_notifier: src/services/s3-notifier/**, src/libs/s3-notifier/**

Outputs per service:

  • {service}_changed: Boolean (true if source or chart changed)
  • {service}_needs_build: Boolean (true if Docker build required)
  • {service}_needs_retag: Boolean (true if only chart changed, can retag)

Manual Override: Use workflow dispatch with force_rebuild_* options to bypass detection.

See ADR-007: Tag-Based Change Detection for details.

2. version-* Jobs (Parallel Execution)

Purpose: Calculate semantic version for each changed service

Jobs: version-api, version-pm, version-quartz, version-web, version-s3-notifier

Trigger: Only runs if corresponding service changed

Process:

  1. Checkout code with full git history (fetch-depth: 0)
  2. Install GitVersion 6.x
  3. Run GitVersion with service-specific config: src/services/{service}/GitVersion.yml
  4. Output calculated version and SHA

Outputs:

  • version: Semantic version (e.g., 1.2.3)
  • sha: Short commit SHA

GitVersion Config:

  • Mode: ContinuousDeployment
  • Tag prefix: {service}-v (e.g., api-v, s3-notifier-v)
  • Conventional commits: feat:, fix:, chore:

2.5. test-* Jobs (Test Phase)

Purpose: Run automated tests before Docker builds to catch issues early

Jobs: test-dotnet, test-web

Trigger: Only runs if corresponding services changed

test-dotnet

Trigger: If API, PM, Quartz, or S3 Notifier changed

Process:

  1. Checkout code
  2. Setup .NET 10.x
  3. Restore dependencies (dotnet restore syrf.sln)
  4. Build solution (dotnet build --configuration Release)
  5. Run tests with coverage (dotnet test with XPlat Code Coverage)
  6. Upload test results and coverage artifacts

Timeout: 10 minutes

Artifacts:

  • dotnet-test-results-{sha}: TRX test result files
  • dotnet-coverage-{sha}: Cobertura XML coverage files

test-web

Trigger: If web service changed

Process:

  1. Checkout code
  2. Setup Node.js 20
  3. Install dependencies (pnpm install --frozen-lockfile)
  4. Run Vitest tests with coverage (pnpm exec ng test --no-watch --coverage)
  5. Upload coverage artifacts

Timeout: 5 minutes

Artifacts:

  • web-coverage-{sha}: Coverage reports (lcov, cobertura, text)
  • web-test-results-{sha}: JUnit XML test results

Coverage Thresholds (configured in vitest.config.ts):

  • Statements: 50%
  • Branches: 40%
  • Functions: 50%
  • Lines: 50%

Tests fail if coverage drops below these thresholds.

Build Gate

The build-docker job requires tests to pass:

needs: [detect-changes, version, build-web-artifacts, test-dotnet, test-web]
if: |
  (needs.test-dotnet.result == 'success' || needs.test-dotnet.result == 'skipped') &&
  (needs.test-web.result == 'success' || needs.test-web.result == 'skipped')

If tests fail, Docker builds are blocked and deployment does not proceed.

See How to: Run Tests for local testing instructions.

3. build-and-push-images

Purpose: Build Docker images for all .NET and Angular services

Depends On: version-api, version-pm, version-quartz, version-web

Trigger: If ANY version job succeeded

Process:

  1. Setup Docker Buildx
  2. Login to GHCR (GitHub Container Registry)
  3. For each successfully versioned service:
  4. Build Docker image from Dockerfile
  5. Push to ghcr.io/camaradesuk/syrf-{service}
  6. Tag with: {version}, {version}-sha.{sha}, latest
  7. Use GitHub Actions cache for layer caching

Services Built:

  • API: .src/services/api/SyRF.API.Endpoint/Dockerfile
  • PM: ./src/services/project-management/SyRF.ProjectManagement.Endpoint/Dockerfile
  • Quartz: ./src/services/quartz/SyRF.Quartz/Dockerfile
  • Web: ./src/services/web/Dockerfile

Permissions: contents: read, packages: write

4. deploy-lambda

Purpose: Build and deploy S3 Notifier to AWS Lambda

Depends On: version-s3-notifier

Trigger: If version-s3-notifier succeeded

Process:

  1. Setup .NET 10.0
  2. Install Amazon.Lambda.Tools globally
  3. Restore dependencies
  4. Build Lambda package: dotnet lambda package
  5. Output: s3-notifier-{version}.zip
  6. Configuration: Release
  7. Framework: net10.0
  8. Deploy to AWS Lambda: dotnet lambda deploy-function
  9. Function name: syrfAppUploadS3Notifier
  10. Region: eu-west-1
  11. Runtime: dotnet10
  12. Tags: Version, SHA, Repository
  13. Upload package as GitHub artifact (90 day retention)

AWS Secrets Required:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

5. promote-to-staging

Purpose: Automatically create PR to cluster-gitops repository to deploy services to staging

Depends On: build-and-push-images, all version-* jobs (except s3-notifier)

Trigger: If build-and-push-images succeeded AND at least one Docker service versioned successfully

Process:

  1. Checkout cluster-gitops repository using GITOPS_PAT
  2. For each successfully built Docker service:
  3. Update environments/staging/{service}.values.yaml
  4. Replace image.tag with new version using sed
  5. Create pull request using peter-evans/create-pull-request action
  6. Branch: promote/staging-{run-number}
  7. Title: "Promote services to staging"
  8. Body: List of updated services with versions and source run link
  9. Labels: staging, automated, gitops
  10. Auto-delete branch after merge
  11. Output summary to GitHub Actions step summary

Services Updated (Docker only):

  • API: environments/staging/api.values.yaml
  • PM: environments/staging/project-management.values.yaml
  • Quartz: environments/staging/quartz.values.yaml
  • Web: environments/staging/web.values.yaml

Note: S3 Notifier (Lambda) is NOT promoted via GitOps - it deploys directly to AWS Lambda

GitHub Secret Required:

  • APP_ID: GitHub App ID for cluster-gitops authentication
  • APP_PRIVATE_KEY: GitHub App private key for cluster-gitops authentication
  • See setup-gitops-github-app.md for configuration instructions

Example PR Body:

## Automated Staging Promotion

This PR updates the staging environment with the latest service versions from the CI/CD pipeline.

**Source Run**: [123](https://github.com/camaradesuk/syrf/actions/runs/123)
**Source Commit**: abc123def456

### Services Updated

- API: `v8.21.0`
- Web: `v5.0.1`

### Deployment

Once merged, ArgoCD will automatically sync the changes to the staging cluster.

6. create-and-push-tags

Purpose: Create git tags ONLY for successful builds/deployments

Depends On: build-and-push-images, deploy-lambda, all version-* jobs

Trigger: always() (runs even if some jobs failed)

Process:

  1. Checkout code with full history
  2. Configure git user as github-actions[bot]
  3. For each service:
  4. Check BOTH conditions: a) Version job succeeded b) Build/deployment job succeeded
  5. If both true: Create annotated tag {service}-v{version}
  6. If either false: Skip (no tag created)
  7. Push all created tags to remote

Tag Logic (Docker Services):

if [ "${{ needs.version-api.result }}" = "success" ] &&
   [ "${{ needs.build-and-push-images.result }}" = "success" ]; then
  git tag -a "api-v${VERSION}" -m "Release API v${VERSION}"
fi

Tag Logic (Lambda):

if [ "${{ needs.version-s3-notifier.result }}" = "success" ] &&
   [ "${{ needs.deploy-lambda.result }}" = "success" ]; then
  git tag -a "s3-notifier-v${VERSION}" -m "Release S3 Notifier v${VERSION}"
fi

Summary Output: Shows which tags were created and which builds failed

6. create-lambda-release

Purpose: Create GitHub Release for S3 Notifier Lambda with package artifact

Depends On: create-and-push-tags, version-s3-notifier, deploy-lambda

Trigger: If all three dependencies succeeded

Process:

  1. Download Lambda package from GitHub artifact
  2. Create GitHub Release using softprops/action-gh-release
  3. Tag: s3-notifier-v{version}
  4. Name: S3 Notifier v{version}
  5. Body: Deployment details (function name, region, runtime, commit)
  6. Attach Lambda package (.zip file)
  7. Not a draft or prerelease

Permissions: contents: write

GitOps Promotion Workflow

The promotion workflow creates a declarative deployment pipeline:

  1. CI builds and pushes Docker images to GHCR
  2. Promotion job creates PR to cluster-gitops repository
  3. Human reviews and merges the PR (manual approval gate)
  4. ArgoCD detects change and syncs to Kubernetes cluster
  5. Services deployed to staging environment

This approach provides:

  • Audit trail: All deployments tracked via git history
  • Rollback capability: Revert PR to rollback deployment
  • Manual approval: Team can review before deployment
  • Declarative state: GitOps repository represents desired cluster state

Key Design Principles

1. No Orphaned Tags

Problem: Don't want git tags pointing to non-existent artifacts

Solution: Tags are created ONLY after successful builds/deployments

Example:

  • If API build fails → No api-vX.Y.Z tag created
  • If Lambda deployment fails → No s3-notifier-vX.Y.Z tag created
  • User sees clear indication in workflow summary

2. Partial Success Handling

Scenario: API builds successfully, PM build fails

Behavior:

  • API: ✅ Docker image pushed, ✅ tag created
  • PM: ❌ No Docker image, ❌ No tag created
  • Workflow continues (doesn't fail completely)
  • Summary shows which succeeded and which failed

3. Artifact Retention

Docker Images: Stored in GHCR indefinitely (until manually deleted)

Lambda Packages:

  • GitHub Artifacts: 90 days retention
  • GitHub Releases: Indefinite (attached to release)

4. Parallel Execution

Version Jobs: Run in parallel (5 jobs simultaneously)

Build Jobs: Sequential within job but parallel between services

Benefit: Faster overall workflow execution

Workflow Execution Examples

Example 1: API and PM Changed

1. detect-changes
   └─ api_changed=true, pm_changed=true

2. version-api (parallel with version-pm)
   └─ version=1.2.3, sha=abc123

3. version-pm
   └─ version=2.3.4, sha=abc123

4. build-and-push-images
   ├─ Build API → ghcr.io/camaradesuk/syrf-api:1.2.3
   └─ Build PM → ghcr.io/camaradesuk/syrf-pm:2.3.4

5. promote-to-staging
   ├─ Update api.values.yaml → tag: "1.2.3"
   ├─ Update project-management.values.yaml → tag: "2.3.4"
   └─ Create PR to cluster-gitops: "Promote services to staging"

6. create-and-push-tags
   ├─ Create tag: api-v1.2.3
   └─ Create tag: pm-v2.3.4

Example 2: S3 Notifier Changed

1. detect-changes
   └─ s3_notifier_changed=true

2. version-s3-notifier
   └─ version=1.0.5, sha=def456

3. deploy-lambda
   ├─ Build package: s3-notifier-1.0.5.zip
   ├─ Deploy to syrfAppUploadS3Notifier
   └─ Upload artifact

4. create-and-push-tags
   └─ Create tag: s3-notifier-v1.0.5

5. create-lambda-release
   ├─ Download s3-notifier-1.0.5.zip
   └─ Create GitHub Release with package

Example 3: Build Failure

1. detect-changes
   └─ api_changed=true

2. version-api
   └─ version=1.2.4, sha=ghi789

3. build-and-push-images
   └─ Build API → FAILS (Docker error)

4. create-and-push-tags
   └─ NO TAG CREATED (build failed)

Summary shows:
- ❌ API: v1.2.4 (Docker build failed - no tag created)

Monitoring and Debugging

View Workflow Run

  1. Go to Actions tab in GitHub
  2. Select Auto Version with GitVersion workflow
  3. Click on specific run

Check Job Status

  • Green checkmark: Job succeeded
  • Red X: Job failed
  • Yellow circle: Job skipped or in progress

Check Tag Creation

# Fetch latest tags
git fetch --tags

# List service tags
git tag -l "api-v*"
git tag -l "s3-notifier-v*"

Check Docker Images

# List images in GHCR
gh api /user/packages/container/syrf-api/versions

# Or use Docker
docker pull ghcr.io/camaradesuk/syrf-api:latest

Check Lambda Deployment

# Get Lambda function info
aws lambda get-function \
  --function-name syrfAppUploadS3Notifier \
  --region eu-west-1

# Check Lambda tags
aws lambda list-tags \
  --resource arn:aws:lambda:eu-west-1:ACCOUNT:function:syrfAppUploadS3Notifier

Check GitHub Releases

Visit: https://github.com/camaradesuk/syrf/releases

Look for releases with tag s3-notifier-v*

Troubleshooting

Tag Not Created

Check:

  1. Did version job succeed? (Check version-{service} job)
  2. Did build/deploy job succeed? (Check build-and-push-images or deploy-lambda)
  3. Both must be green for tag to be created

Fix: Fix the failing build/deployment job and rerun workflow

Docker Build Fails

Common Causes:

  • Syntax error in Dockerfile
  • Missing dependencies
  • Build context issues
  • Network/GHCR connectivity

Fix: Check build logs in build-and-push-images job

Lambda Deployment Fails

Common Causes:

  • Missing AWS credentials
  • Incorrect IAM permissions
  • Lambda function doesn't exist
  • Network issues

Fix: Check deploy-lambda job logs, verify AWS secrets

Release Not Created

Prerequisite: Tag must be created first

Check:

  1. Does s3-notifier-v{version} tag exist?
  2. Did create-lambda-release job run?
  3. Check job logs for errors

Promotion PR Not Created

Common Causes:

  • Missing or invalid GITOPS_PAT secret
  • build-and-push-images job failed
  • No Docker services built successfully (e.g., only Lambda changed)
  • Token doesn't have repo scope
  • Token doesn't have access to cluster-gitops repository

Fix:

  1. Check promote-to-staging job logs in GitHub Actions
  2. Verify APP_ID and APP_PRIVATE_KEY secrets exist and are accessible
  3. Ensure GitHub App has proper permissions (Contents: Read/Write, PRs: Read/Write)
  4. Verify at least one Docker service (API/PM/Quartz/Web) built successfully
  5. See setup-gitops-github-app.md for GitHub App configuration

Promotion PR Created But Values Not Updated

Symptom: PR exists but image tags in values files unchanged

Common Causes:

  • sed command pattern mismatch
  • Values file structure changed
  • Branch conflicts in cluster-gitops

Fix:

  1. Check PR diff in cluster-gitops repository
  2. Verify values file structure matches expected format:
image:
  tag: "1.2.3"  # This line must exist and match pattern
  1. Close conflicting PRs or branches in cluster-gitops

Staging Environment

Overview

Staging is a pre-production environment that receives automated deployments from the CI/CD pipeline after successful builds on main branch.

Staging vs Production

Aspect Staging Production
URL Pattern *.staging.syrf.org.uk *.syrf.org.uk
Namespace staging production
Promotion Automatic (PR auto-merges) Manual (requires review)
Database syrftest ⚠️ syrftest
RabbitMQ Vhost staging / (default)
Quartz Schema [staging] [production]
Replicas 1 per service 2+ per service
Resources Reduced Full allocation

⚠️ CRITICAL: Database Sharing

Staging shares the production database (syrftest). This is a known issue and represents a significant risk.

Implications:

  • Changes in staging can affect production data
  • Staging tests run against live user data
  • Schema migrations must be backwards-compatible
  • No isolated testing of data-destructive operations

Planned resolution: See MongoDB Testing Strategy for the plan to create syrf_staging database.

Staging Deployment Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Staging Deployment Flow                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. Push to main                                                            │
│            ↓                                                                │
│  2. CI/CD builds Docker images                                              │
│            ↓                                                                │
│  3. Images pushed to GHCR                                                   │
│     ghcr.io/camaradesuk/syrf-{service}:{version}                            │
│            ↓                                                                │
│  4. promote-to-staging job creates PR to cluster-gitops                     │
│     Updates: syrf/environments/staging/{service}/config.yaml                │
│            ↓                                                                │
│  5. PR validation passes (YAML lint, etc.)                                  │
│            ↓                                                                │
│  6. PR auto-merges (no human approval required for staging)                 │
│            ↓                                                                │
│  7. ArgoCD ApplicationSet detects config.yaml change                        │
│            ↓                                                                │
│  8. ArgoCD regenerates Application with new targetRevision                  │
│            ↓                                                                │
│  9. ArgoCD syncs: pulls Helm chart, deploys to staging namespace            │
│            ↓                                                                │
│  10. PostSync hook creates GitHub commit status (argocd/deploy-staging)     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Staging Version Files

Staging service versions are stored in the cluster-gitops repository:

cluster-gitops/syrf/environments/staging/
├── namespace.yaml              # Environment metadata
├── staging.values.yaml         # Environment-specific Helm values
├── api/
│   ├── config.yaml            # chartTag: "8.21.0" (updated by CI/CD)
│   └── values.yaml            # Service-specific overrides
├── project-management/
│   ├── config.yaml
│   └── values.yaml
├── quartz/
│   ├── config.yaml
│   └── values.yaml
└── web/
    ├── config.yaml
    └── values.yaml

Verifying Staging Deployment

Check deployment status:

# Via ArgoCD CLI (requires cluster access)
argocd app get syrf-staging-api

# Via kubectl
kubectl get deployments -n staging
kubectl get pods -n staging

# Check running versions
kubectl get deployment syrf-api -n staging -o jsonpath='{.spec.template.spec.containers[0].image}'

Check commit status in GitHub:

  • Navigate to the commit on main branch
  • Look for argocd/deploy-staging status check

Production Promotion

Overview

Production deployments require manual approval via PR merge in the cluster-gitops repository.

Promotion Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Production Promotion Flow                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. After successful staging promotion (PR merged)                          │
│            ↓                                                                │
│  2. promote-to-production job automatically triggers                        │
│            ↓                                                                │
│  3. Job copies service configs from staging to production                   │
│     syrf/environments/staging/{service}/config.yaml                         │
│                      ↓ copy values ↓                                        │
│     syrf/environments/production/{service}/config.yaml                      │
│            ↓                                                                │
│  4. Updates envName from "staging" to "production"                          │
│            ↓                                                                │
│  5. Creates PR to cluster-gitops                                            │
│     Labels: requires-review, automated                                      │
│            ↓                                                                │
│  6. Workflow completes (green checkmark)                                    │
│     PR is NOT auto-merged                                                   │
│            ↓                                                                │
│  ┌─────────────────────────────────────────────────────────────────────────┐│
│  │ 7. MANUAL GATE: Administrator reviews and merges PR                    ││
│  │    - Review what services are being updated                            ││
│  │    - Verify staging testing is complete                                ││
│  │    - Coordinate deployment timing                                      ││
│  └─────────────────────────────────────────────────────────────────────────┘│
│            ↓                                                                │
│  8. After merge, ArgoCD syncs to production namespace                       │
│            ↓                                                                │
│  9. PostSync hook creates GitHub commit status (argocd/deploy-production)   │
│            ↓                                                                │
│  10. PostSync hook creates GitHub Release (production only)                 │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Production Checklist

Before merging a production promotion PR:

  • Staging deployment verified working
  • Critical user flows tested in staging
  • No known regressions or blockers
  • Database migrations are backwards-compatible
  • On-call team aware of deployment
  • Deployment timing appropriate (avoid peak hours)

Rollback Procedure

Quick rollback (preferred):

  1. In cluster-gitops, find the previous production promotion PR
  2. Copy the old chartTag values from git history
  3. Create a new PR reverting the config.yaml changes
  4. Merge the revert PR
  5. ArgoCD will sync the previous versions

Alternative - via ArgoCD:

# List application history
argocd app history syrf-production-api

# Rollback to previous revision
argocd app rollback syrf-production-api {revision-number}

Note: ArgoCD rollback is temporary - the next sync will revert to git state. Always fix in git for permanent changes.

Environment Comparison

Complete Environment Matrix

Aspect Preview Staging Production
Trigger PR + preview label Push to main Manual PR merge
Namespace pr-{number} staging production
URL pr-{n}.syrf.org.uk staging.syrf.org.uk syrf.org.uk
MongoDB syrf_pr_{number} syrftest ⚠️ syrftest
Quartz Schema [preview_{number}] [staging] [production]
RabbitMQ pr-{number} staging /
Lambda *-pr-{number} (shared prod) syrfAppUploadS3Notifier
S3 Prefix preview/pr-{n}/ (shared prod) Projects/
Auto-cleanup Yes (on PR close) No No
GitHub Deployment Yes No (commit status) No (commit status + Release)
Replicas 1 1 2+
Resources Minimal Reduced Full
Data Seed/Snapshot Production ⚠️ Production

Data Isolation Status

Environment Database Isolation Risk Level
Preview syrf_pr_{number} ✅ Full Low
Staging syrftest ❌ Shares with production High
Production syrftest N/A (is production) N/A

Planned improvements: Staging will get its own syrf_staging database - see MongoDB Testing Strategy.

Maintenance

Adding a New Service

  1. Create service in src/services/{new-service}/
  2. Add GitVersion.yml to service folder
  3. Add Dockerfile (or Lambda configuration)
  4. Update detect-changes job with new path filter
  5. Add version-{new-service} job
  6. Add to either build-and-push-images or create new deployment job
  7. Add to create-and-push-tags logic
  8. Test with a commit to the new service

Modifying Tag Logic

Tags are created in create-and-push-tags job.

To change tag format or conditions:

  1. Edit .github/workflows/ci-cd.yml
  2. Find create-and-push-tags job
  3. Modify bash script in "Create and push tags" step
  4. Test thoroughly before merging

Changing Lambda Function Name

If Lambda function name changes:

  1. Update deploy-lambda job: dotnet lambda deploy-function {NEW_NAME}
  2. Update documentation
  3. Update AWS IAM policies
  4. Consider migration strategy for existing function