GitOps Repository Structure¶
Overview¶
The cluster-gitops repository implements a production-ready GitOps workflow using ArgoCD ApplicationSets for automated application deployment across multiple environments.
Repository Structure¶
cluster-gitops/
├── applicationsets/ # ApplicationSet definitions
│ ├── syrf.yaml # SyRF services (auto-generated Applications)
│ ├── infrastructure.yaml # External infrastructure components
│ └── custom-charts.yaml # Custom Helm charts from this repo
│
├── infrastructure/ # External infrastructure component configs
│ ├── cert-manager/
│ │ ├── config.yaml # Points to external Helm chart
│ │ └── values.yaml # Values for external chart
│ ├── ingress-nginx/
│ ├── rabbitmq/
│ └── external-secrets-operator/
│
├── charts/ # Custom Helm charts (self-contained)
│ └── extra-secrets/
│ ├── Chart.yaml
│ ├── values.yaml # Default values
│ ├── values-staging.yaml # Environment overrides
│ ├── values-production.yaml
│ └── templates/
│
├── syrf/ # SyRF application configuration
│ ├── global.values.yaml # Values for ALL services in ALL environments
│ ├── services/ # Base service configurations
│ │ └── {service}/
│ │ ├── config.yaml # Service metadata (chart path, repo)
│ │ └── values.yaml # Base Helm values
│ └── environments/ # Per-environment configuration
│ ├── staging/
│ │ ├── namespace.yaml # Environment metadata
│ │ ├── staging.values.yaml # Environment-wide Helm values
│ │ └── {service}/ # Service configs (updated by CI/CD)
│ │ ├── config.yaml # Service version (chartTag)
│ │ └── values.yaml # Service-specific values
│ ├── production/
│ │ ├── production.values.yaml
│ │ └── ...
│ └── preview/
│ ├── preview.values.yaml
│ └── ...
│
├── argocd/
│ ├── projects/ # AppProject definitions (RBAC)
│ │ ├── syrf-staging.yaml
│ │ ├── syrf-production.yaml
│ │ ├── infrastructure.yaml
│ │ └── preview.yaml
│ ├── config/ # ArgoCD configuration
│ ├── resources/ # ArgoCD's own resources
│ └── bootstrap/
│
├── scripts/
│ └── promote-to-production.sh
│
└── docs/
├── architecture/
├── decisions/
└── how-to/
Design Principles¶
1. Separation of Concerns¶
Three ApplicationSets for Different Purposes:
- syrf.yaml - Application services from the syrf monorepo
- Auto-discovers services from
syrf/*/config.yaml - Creates Applications for each service × environment combination
-
Single source of truth:
environments/*/syrf.yamlfor versions -
infrastructure.yaml - External infrastructure components
- Deploys charts from public Helm registries (Bitnami, Jetstack, etc.)
- Configuration in
infrastructure/*/config.yaml -
Values in
infrastructure/*/values.yaml -
custom-charts.yaml - Custom charts maintained in this repo
- Auto-discovers charts from
charts/directory - Self-contained: chart + values together
- Use case: Migrated charts from Jenkins X, organization-specific wrappers
2. Value Hierarchy¶
Values merge in order (last wins):
1. Chart defaults (in monorepo chart)
↓
2. syrf/global.values.yaml (ALL services, ALL environments)
↓
3. syrf/services/{service}/values.yaml (THIS service base, ALL environments)
↓
4. syrf/environments/{env}/{env}.values.yaml (ALL services in THIS environment)
↓
5. syrf/environments/{env}/{service}/values.yaml (THIS service, THIS environment)
Example for API in Production:
- Chart defaults (from monorepo)
-
- syrf/global.values.yaml
-
- syrf/services/api/values.yaml
-
- syrf/environments/production/production.values.yaml
-
- syrf/environments/production/api/values.yaml
Naming Convention:
global.values.yaml- Universal defaults{env}.values.yaml- Environment-specific (staging.values.yaml, production.values.yaml)values.yaml- Base service or service-specific values
3. Single Source of Truth for Versions¶
Only environments/*/syrf.yaml changes on deployment:
# environments/staging/syrf.yaml
services:
- name: api
enabled: true
chartTag: api-v8.21.1 # ← CI/CD updates this line
Image tags are automatically derived from chartTags:
- api-v8.21.1 → image tag 8.21.1
- No duplication across multiple files
- Chart version and image version always match
4. RBAC with AppProjects¶
| AppProject | Purpose | Who Can Deploy | Sync Policy |
|---|---|---|---|
| syrf-staging | Staging applications | Developers + CI/CD | Auto-sync, 24/7 |
| syrf-production | Production applications | Platform team only | Manual approval, sync windows |
| infrastructure | Platform components | Platform team only | Manual sync only |
| preview | PR preview environments | Developers + CI/CD | Auto-sync, ephemeral |
Sync Windows: - Production: Blocked during business hours (9am-5pm Mon-Fri UTC) - Staging: Always allowed - Infrastructure: Always manual
Key Features¶
Auto-Discovery with ApplicationSets¶
Matrix Generator Pattern:
Environments × Services = Applications
(staging, production) × (api, web, pm, quartz, docs, user-guide)
= api-staging, api-production, web-staging, web-production, ...
Selective Deployment¶
Services can be selectively deployed per environment:
# environments/staging/syrf.yaml
services:
- name: api
enabled: true
chartTag: api-v8.21.1
- name: quartz
enabled: false # Not deployed to staging
ApplicationSet filters ensure only enabled services are deployed.
Optional Value Files¶
Uses Helm's ignoreMissingValueFiles: true feature:
- Service-specific values files are optional
- If syrf/api/values-staging.yaml doesn't exist, it's skipped
- Allows flexibility in value overrides
Deployment Workflows¶
Staging (Automatic)¶
1. Developer pushes to main branch
↓
2. CI/CD builds image and creates git tag
↓
3. CI/CD updates environments/staging/syrf.yaml with new chartTag
↓
4. GitHub webhook triggers ArgoCD
↓
5. ApplicationSet regenerates Application with new version
↓
6. ArgoCD syncs to cluster
Time: ~1-2 minutes
Production (Manual)¶
1. Run promotion script or manually edit environments/production/syrf.yaml
↓
2. Create PR for review
↓
3. Team reviews and approves
↓
4. Merge PR
↓
5. ArgoCD syncs (respects sync windows)
Time: Manual approval + sync window
Migration from Old Structure¶
Before¶
apps/
api-staging.yaml # Manual Application manifest
api-production.yaml # Manual Application manifest
web-staging.yaml
web-production.yaml
... (12+ files)
environments/
staging/
api.values.yaml # Version defined here
production/
api.values.yaml # Version defined here (drift risk)
Problems: - 12+ manually maintained Application manifests - Version duplication (chartTag in apps/, image tag in values/) - Add new service = create 2+ new files - Change common config = update 12+ files
After¶
applicationsets/
syrf.yaml # ONE ApplicationSet generates all
syrf/
api/
config.yaml # Static metadata
values.yaml # Static defaults
environments/
staging/
syrf.yaml # ALL service versions (single source of truth)
production/
syrf.yaml
Benefits: - 3 ApplicationSets instead of 12+ Application manifests - Single source of truth for versions - Add new service = create 1 config directory - Change common config = update 1 template - Auto-discovery from directory structure
Common Operations¶
Deploy New Service Version to Staging¶
Automatic via CI/CD:
# CI/CD does this automatically
yq eval -i '(.services[] | select(.name == "api") | .chartTag) = "api-v8.21.1"' \
environments/staging/syrf.yaml
git add environments/staging/syrf.yaml
git commit -m "chore(api): deploy v8.21.1 to staging"
git push
Promote to Production¶
Manual via script:
Add New Service¶
-
Create service config:
-
Add to environment lists:
-
Push to git → ApplicationSet creates Applications automatically
Add Custom Chart¶
-
Create chart structure:
-
Push to git → ApplicationSet discovers and deploys automatically
Related Documentation¶
- ApplicationSets Deep Dive - How ApplicationSets work
- ADR-001: Custom Chart Values Location - Why values are co-located
- Promotion Workflow - Staging → Production process
- Deploying Services - Day-to-day operations