CI/CD¶
Canonical repo: Gitea (http://192.168.1.15:30360/heezy-admin/)
Mirror: GitHub (github.com/trentnielsen) - read-only backup
All deployments run through Gitea act-runner. Workflows are configured per repo (heezy-containers, heezy-k8s, terraform-heezy, cloudflare-terraform).
Deployment Pipeline¶
heezy-containers (services)
push to gitea main
-> .gitea/workflows/deploy-<service>.yml
-> build job: Docker build + ECR push
-> deploy job: push .deploy-trigger to heezy-k8s repo
heezy-k8s (Kubernetes manifests)
.gitea/workflows/auto-deploy.yaml
trigger: receive .deploy-trigger file from heezy-containers
step 1: kubectl apply -k (kustomize)
step 2: kubectl rollout restart (force pod restart)
step 3: kubectl rollout status (wait for ready)
terraform-heezy (infrastructure)
.gitea/workflows/<environment>.yaml per env
terraform plan -> apply
cloudflare-terraform (CF Access + tunnel)
.gitea/workflows/deploy.yaml
terraform plan -> apply
Repos and Workflows¶
heezy-containers¶
Per-service deploy workflows: .gitea/workflows/deploy-<service>.yml
- Trigger: push to
gitea main - Build: Docker build, ECR push
- Deploy: Write
.deploy-triggerfile to heezy-k8s
heezy-k8s¶
Auto-deploy orchestration: .gitea/workflows/auto-deploy.yaml
- Trigger:
.deploy-triggerfile in repo - Steps:
kubectl apply -k(apply kustomized manifests)kubectl rollout restart deployment/<name>(restart pods)kubectl rollout status(wait for readiness)- Rollback: Git revert + push (old deploy-trigger removed, new one created on next service deploy)
terraform-heezy¶
Per-environment execution: .gitea/workflows/<environment>.yaml
- Workflows:
dev.yaml,staging.yaml,production.yaml - Trigger: push to
gitea main - Steps:
terraform plan->terraform apply(auto-approved for now)
cloudflare-terraform¶
Cloudflare Access + tunnel config: .gitea/workflows/deploy.yaml
- Manages CF Access policies, identity providers, tunnel config
- Protected sites: finance, receipts, cs16, blog, docs, heezy.info
Key Rules¶
- Always push to
gitearemote first, thenorigin(GitHub backup) - Never use
kubectl applyorterraform applydirectly - always via pipeline - Act runner v0.6.1 does NOT support reusable workflows - inline everything
DOCKER_HOST=tcp://172.17.0.1:2375required in all build jobs (Docker-in-Docker)GITEA_INSTANCE_URL=http://192.168.1.15:30360(NodePort - DinD can't resolve k8s DNS)
Known Issues¶
Gitea DB Sync Bug¶
Runners complete jobs but don't always update status in the database. Auto-fixed by gitea-db-sync CronJob every 5 minutes.
Manual fix if needed:
UPDATE action_task_step SET status=3 WHERE status=1 AND stopped > 0;
UPDATE action_task t SET status=3 WHERE status=1 AND stopped > 0
AND NOT EXISTS (SELECT 1 FROM action_task_step s WHERE s.task_id=t.id AND s.status NOT IN (3,4,6));
UPDATE action_run_job j SET status=3 WHERE status IN (1,2)
AND task_id IN (SELECT id FROM action_task WHERE status=3);
UPDATE action_run r SET status=3 WHERE status IN (1,2)
AND NOT EXISTS (SELECT 1 FROM action_run_job j WHERE j.run_id=r.id AND j.status NOT IN (3,4,6))
AND EXISTS (SELECT 1 FROM action_run_job j WHERE j.run_id=r.id);