A cookiecutter template for creating standardized GitOps repositories for BC Government Justice applications deployed on OpenShift/Kubernetes.
The ag-helm-templates shared library is now published to GitHub Container Registry. No need to copy shared-lib folders anymore!
📦 Package: oci://ghcr.io/bcgov-c/helm/ag-helm-templates:1.0.3
See HELM_PACKAGE_GUIDE.md for details.
One command to test everything:
bash scripts/test-complete-deployment.shThis validates the complete workflow: generation, deployment, and verification.
For a single-page overview of which tools/policies run in CI, how to run the same checks locally, and how to troubleshoot failures, see:
docs/validation-and-policy-scans.md
- Standardized Helm Charts using the ag-helm shared library
- Support for Frontend + Backend + Database architectures
- Environment-specific configurations (dev, test, prod)
- Horizontal Pod Autoscaling (HPA) ready
- OpenShift Routes for external access
- Network Policies for security
- Service Accounts for RBAC
- Cookiecutter -
pip install cookiecutter - Helm 3.x
- kubectl configured for your cluster
- Your License Plate (provided by platform team)
# Clone this template repository
git clone <template-repo-url>
cd ministry-gitops-jag-template-main
# Generate a GitOps repo (includes charts + deploy values + Argo CD)
cookiecutter ./gitops-repo --no-input \
app_name=myapp \
licence_plate=abc123 \
github_org=bcgov-cEdit the generated values file (myapp-gitops/deploy/dev_values.yaml):
frontend:
enabled: true
image:
repository: docker.io/myorg
name: my-frontend-app
tag: "v1.0.0"
route:
host: myapp-abc123-dev.apps.emerald.devops.gov.bc.ca
backend:
enabled: true
image:
repository: docker.io/myorg
name: my-backend-api
tag: "v1.0.0"
database:
connectionString: "Host=myapp-postgresql;Port=5432;..."# The ag-helm dependency is now fetched from GHCR automatically!
cd myapp-charts/gitops
helm dependency update
# Deploy to dev
helm install myapp . \
--values ../../myapp-deploy/dev_values.yaml \
--namespace abc123-dev \
--create-namespace
# Verify
kubectl get pods -n abc123-devNote: No need to manually copy shared-lib/ag-helm anymore! The cookiecutter template is configured to pull from oci://ghcr.io/bcgov-c/helm/ag-helm-templates automatically.
Reusable Helm templates for consistent deployments across all Justice applications:
- Standardized Deployments - Container configurations, security contexts, resource limits
- Service Discovery - Kubernetes services with consistent naming
- Autoscaling - HPA configurations for CPU/memory-based scaling
- Network Policies - Default security rules for pod communication
To add a new service (e.g., "worker"):
1. Add values configuration:
worker:
enabled: true
image:
repository: docker.io/myorg
name: my-worker
tag: latest
service:
port: 80812. Create deployment template (worker-deployment.yaml):
{{- if .Values.worker.enabled }}
{{- $p := dict "Values" .Values.worker -}}
{{- $_ := set $p "ApplicationGroup" (default .Values.project "app") -}}
{{- $_ := set $p "Name" (default "worker" .Values.worker.image.name) -}}
{{- $_ := set $p "Registry" .Values.worker.image.repository -}}
{{- $_ := set $p "ModuleValues" (dict
"image" (dict "tag" .Values.worker.image.tag "pullPolicy" .Values.worker.image.pullPolicy)
"replicas" .Values.worker.replicaCount
"resources" .Values.worker.resources
) -}}
{{ include "ag-template.deployment" $p }}
{{- end }}3. Deploy:
helm upgrade myapp . --values dev_values.yamlSee Architecture Documentation for detailed instructions.
- Developer Cookbook (Emerald / Zero-Trust) - End-to-end onboarding and working patterns
- Getting Started Guide - First-time setup and deployment
- Repository Structure - Naming conventions and folder structure
- Architecture - How the template works and using ag-helm
- Template Structure - Understanding template files
- Configuration Guide - Complete values reference
- Deployment Guide - Step-by-step deployment instructions
- Troubleshooting - Common issues and solutions
- CHANGELOG.md - Recent fixes and improvements
Fixed critical cookiecutter template syntax errors:
✅ Fixed Files:
frontend-route.yaml- Escaped Helm syntax, added closing tagbackend-hpa.yaml- Escaped Helm syntax, added closing tagfrontend-hpa.yaml- Escaped Helm syntax, added closing tag
✅ Fixed Image Paths:
- Deployment templates now use
image.namefrom values - Supports custom Docker image names
✅ Fixed Security Context:
- Changed
runAsNonRoot: falseto allow standard Docker images - Changed
readOnlyRootFilesystem: falsefor writable containers
✅ Fixed PostgreSQL:
- Uses
postgres:16(official image) instead of unavailable Bitnami image
See CHANGELOG.md for complete details.
Validates the complete workflow:
cd ministry-gitops-jag-template-main
bash scripts/test-complete-deployment.shWhat it tests:
- ✅ Cookiecutter generation
- ✅ Helm chart deployment
- ✅ Frontend deployment (1/1 ready)
- ✅ Backend deployment (1/1 ready)
- ✅ PostgreSQL deployment (1/1 ready)
- ✅ HPAs configured
- ✅ Services exposed
bash scripts/test-unified-gitops-chart.shTests individual scenarios:
- Frontend-only deployment
- Backend-only deployment
- Full-stack deployment
┌─────────────────────────────────────────┐
│ Environment Values Files │
│ (dev_values.yaml, prod_values.yaml) │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Application Templates │
│ (frontend-deployment.yaml, etc.) │
│ - Uses cookiecutter for generation │
│ - Uses Helm for deployment │
└──────────────┬──────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ ag-helm Shared Library │
│ (Reusable Helm template functions) │
│ - ag-template.deployment │
│ - ag-template.service │
│ - ag-template.hpa │
└──────────────────────────────────────────┘
ministry-gitops-jag-template-main/
├── charts/ # Helm chart templates
│ └── {{cookiecutter.charts_dir}}/
│ └── gitops/
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/ # Kubernetes manifests
│
├── deploy/ # Environment configurations
│ └── {{cookiecutter.deploy_dir}}/
│ ├── dev_values.yaml
│ ├── test_values.yaml
│ └── prod_values.yaml
│
├── shared-lib/ # Shared libraries
│ └── ag-helm/ # ag-helm Helm library
│
├── scripts/ # Utility scripts
│ ├── test-complete-deployment.sh
│ └── test-unified-gitops-chart.sh
│
├── docs/ # Documentation
│ ├── getting-started.md
│ ├── architecture.md
│ ├── configuration-guide.md
│ └── ...
│
├── README.md # This file
└── CHANGELOG.md # Version history
frontend:
enabled: true
backend:
enabled: false
postgresql:
enabled: falsefrontend:
enabled: false
backend:
enabled: true
database:
connectionString: "Host=myapp-postgresql;..."
postgresql:
enabled: truefrontend:
enabled: true
apiUrl: "myapp-backend:8080"
backend:
enabled: true
database:
connectionString: "Host=myapp-postgresql;..."
postgresql:
enabled: true{licence_plate}-{environment}
Examples: abc123-dev, abc123-test, abc123-prod
{app}-{licence_plate}-{environment}.apps.{cluster}.devops.gov.bc.ca
Examples:
myapp-abc123-dev.apps.emerald.devops.gov.bc.camyapp-abc123-prod.apps.gold.devops.gov.bc.ca
See Repository Structure for complete naming standards.
Found a bug or have a suggestion? Please open an issue with:
- Description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Environment details (Helm version, cluster type, etc.)
To modify the template:
- Make changes to templates in
charts/ordeploy/ - Test with
scripts/test-complete-deployment.sh - Update documentation
- Update CHANGELOG.md
[Specify License]
For help:
- Check Troubleshooting Guide
- Review Documentation
- Contact platform team
- Open an issue
Template Version: 1.0.0 (2026-02-10)
Maintained by: BC Government Justice Digital Services