CI/CD

The built-in CI validates and tests Terraform (terraform fmt, terraform validate, tflint, terraform test). Ansible is never run in CI — all make bootstrap / make deploy operations are local only.

Example workflows for terraform plan (on PRs) and terraform apply (manual dispatch) are included as .example.yml files — copy them to enable (see Required Secrets below).

An optional GitOps deployment workflow is also included — copy .github/workflows/deploy.yml.example to .github/workflows/deploy.yml to enable automatic Ansible-based deployments on push. See GitOps auto-deploy for setup instructions.

Terraform Plan (example — copy to enable)

Copy .github/workflows/terraform-plan.yml.example to .github/workflows/terraform-plan.yml. When a pull request touches terraform/**, the workflow runs automatically and posts the plan diff as a PR comment.

Terraform Apply (example — copy to enable)

Copy .github/workflows/terraform-apply.yml.example to .github/workflows/terraform-apply.yml. Then trigger manually after merging:

  1. Go to ActionsTerraform ApplyRun workflow
  2. Select the branch and click Run workflow

The apply workflow uses a production environment — you can configure approval gates in SettingsEnvironmentsproduction.

Required GitHub Variables

Set these in SettingsVariables and secretsActionsVariables (not secrets — WIF is keyless):

VariableValue
GCP_WIF_PROVIDERFull resource name of the WIF provider (output from my-gcp-project, e.g. projects/<proj-number>/locations/global/workloadIdentityPools/github/providers/github)
GCP_SERVICE_ACCOUNTAutomation SA email (e.g. automation@<project>.iam.gserviceaccount.com)

Required GitHub Secrets

These are for the Terraform CI workflows only:

SecretDescription
HCLOUD_TOKENHetzner Cloud API token
SSH_KEY_FINGERPRINTSSH key fingerprint registered in Hetzner

The optional GitOps deployment workflow requires additional secrets (SSH_PRIVATE_KEY, SOPS_AGE_KEY, and optionally Tailscale OAuth credentials). See GitOps auto-deploy.