Skip to content

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-trigger file to heezy-k8s

heezy-k8s

Auto-deploy orchestration: .gitea/workflows/auto-deploy.yaml

  • Trigger: .deploy-trigger file 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 gitea remote first, then origin (GitHub backup)
  • Never use kubectl apply or terraform apply directly - always via pipeline
  • Act runner v0.6.1 does NOT support reusable workflows - inline everything
  • DOCKER_HOST=tcp://172.17.0.1:2375 required 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);