name: Terraform Terragrunt (contour) # One workflow for ALL closed contours. Per-contour differentiation is done via # repository variables/secrets in each contour's Gitea — this is the downstream # runner contract: # vars: INFRA_ENV, RUNNER_LABEL, RUNNER_IMAGE # secrets: TF_STATE_S3_ENDPOINT, TF_STATE_S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, # VAULT_ADDR, VAULT_TOKEN, SOPS_AGE_KEY, KUBECONFIG_B64 (external runner # only), KUBE_CONTEXT (external runner only) # Infra-service admin creds are NOT passed as secrets — they are read from Vault # at run time (see the "Run ... stacks" step) so the single source of truth stays # in the contour Vault. on: pull_request: workflow_dispatch: branches: [contour] paths: - "live/**" - "modules/**" - "infrastructure.yaml" - "infrastructure-secrets.yaml" - "scripts/**" - ".gitea/workflows/**" push: branches: [contour] paths: - "live/**" - "modules/**" - "infrastructure.yaml" - "infrastructure-secrets.yaml" - "scripts/**" - ".gitea/workflows/**" env: TF_STATE_S3_REGION: ru-central1 INFRA_ENV: ${{ vars.INFRA_ENV }} jobs: validate: runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }} container: image: ${{ vars.RUNNER_IMAGE || 'cr.yandex/crp3ccidau046kdj8g9q/terraform/terragrunt:v9.11' }} env: TF_STATE_S3_ENDPOINT: ${{ secrets.TF_STATE_S3_ENDPOINT }} TF_STATE_S3_BUCKET: ${{ secrets.TF_STATE_S3_BUCKET }} S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }} S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }} VAULT_ADDR: ${{ secrets.VAULT_ADDR }} VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }} SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }} KUBE_CONTEXT: ${{ secrets.KUBE_CONTEXT }} KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }} KUBECONFIG: /workspace/.kube/config GIT_AUTH_TOKEN: ${{ github.token }} steps: - name: Checkout (without Node.js action) run: | if [ -f infrastructure.yaml ] && [ -d live ]; then echo "Workspace already contains repository files, skip checkout." exit 0 fi TOKEN="${GIT_AUTH_TOKEN:-${GITHUB_TOKEN:-${GITEA_TOKEN:-}}}" if [ -z "$TOKEN" ]; then echo "No token found for git checkout (github.token/GITHUB_TOKEN/GITEA_TOKEN)." exit 1 fi REPO_URL="${GITHUB_SERVER_URL%/}/${GITHUB_REPOSITORY}.git" git init . git remote add origin "$REPO_URL" 2>/dev/null || git remote set-url origin "$REPO_URL" git -c http.extraHeader="Authorization: token ${TOKEN}" fetch --depth=1 origin "${GITHUB_SHA}" git checkout -f FETCH_HEAD - name: Prepare kubeconfig run: | if [ -n "${KUBECONFIG_B64:-}" ]; then mkdir -p /workspace/.kube echo "$KUBECONFIG_B64" | base64 -d > /workspace/.kube/config chmod 600 /workspace/.kube/config else echo "No KUBECONFIG_B64 — in-cluster runner: kubernetes/vault providers use the pod ServiceAccount kubeconfig or in-cluster config." fi - name: Run validate for all stacks run: | . ./scripts/load_admin_creds.sh ./scripts/run_all_stacks.sh validate plan: needs: [validate] runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }} container: image: ${{ vars.RUNNER_IMAGE || 'cr.yandex/crp3ccidau046kdj8g9q/terraform/terragrunt:v9.11' }} env: TF_STATE_S3_ENDPOINT: ${{ secrets.TF_STATE_S3_ENDPOINT }} TF_STATE_S3_BUCKET: ${{ secrets.TF_STATE_S3_BUCKET }} S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }} S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }} VAULT_ADDR: ${{ secrets.VAULT_ADDR }} VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }} SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }} KUBE_CONTEXT: ${{ secrets.KUBE_CONTEXT }} KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }} KUBECONFIG: /workspace/.kube/config GIT_AUTH_TOKEN: ${{ github.token }} steps: - name: Checkout (without Node.js action) run: | if [ -f infrastructure.yaml ] && [ -d live ]; then echo "Workspace already contains repository files, skip checkout." exit 0 fi TOKEN="${GIT_AUTH_TOKEN:-${GITHUB_TOKEN:-${GITEA_TOKEN:-}}}" if [ -z "$TOKEN" ]; then echo "No token found for git checkout (github.token/GITHUB_TOKEN/GITEA_TOKEN)." exit 1 fi REPO_URL="${GITHUB_SERVER_URL%/}/${GITHUB_REPOSITORY}.git" git init . git remote add origin "$REPO_URL" 2>/dev/null || git remote set-url origin "$REPO_URL" git -c http.extraHeader="Authorization: token ${TOKEN}" fetch --depth=1 origin "${GITHUB_SHA}" git checkout -f FETCH_HEAD - name: Prepare kubeconfig run: | if [ -n "${KUBECONFIG_B64:-}" ]; then mkdir -p /workspace/.kube echo "$KUBECONFIG_B64" | base64 -d > /workspace/.kube/config chmod 600 /workspace/.kube/config fi - name: Run plan for all stacks run: | . ./scripts/load_admin_creds.sh ./scripts/run_all_stacks.sh plan apply: needs: [plan] if: github.event_name == 'push' runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }} container: image: ${{ vars.RUNNER_IMAGE || 'cr.yandex/crp3ccidau046kdj8g9q/terraform/terragrunt:v9.11' }} env: TF_STATE_S3_ENDPOINT: ${{ secrets.TF_STATE_S3_ENDPOINT }} TF_STATE_S3_BUCKET: ${{ secrets.TF_STATE_S3_BUCKET }} S3_ACCESS_KEY: ${{ secrets.S3_ACCESS_KEY }} S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }} VAULT_ADDR: ${{ secrets.VAULT_ADDR }} VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }} SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }} KUBE_CONTEXT: ${{ secrets.KUBE_CONTEXT }} KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }} KUBECONFIG: /workspace/.kube/config GIT_AUTH_TOKEN: ${{ github.token }} steps: - name: Checkout (without Node.js action) run: | if [ -f infrastructure.yaml ] && [ -d live ]; then echo "Workspace already contains repository files, skip checkout." exit 0 fi TOKEN="${GIT_AUTH_TOKEN:-${GITHUB_TOKEN:-${GITEA_TOKEN:-}}}" if [ -z "$TOKEN" ]; then echo "No token found for git checkout (github.token/GITHUB_TOKEN/GITEA_TOKEN)." exit 1 fi REPO_URL="${GITHUB_SERVER_URL%/}/${GITHUB_REPOSITORY}.git" git init . git remote add origin "$REPO_URL" 2>/dev/null || git remote set-url origin "$REPO_URL" git -c http.extraHeader="Authorization: token ${TOKEN}" fetch --depth=1 origin "${GITHUB_SHA}" git checkout -f FETCH_HEAD - name: Prepare kubeconfig run: | if [ -n "${KUBECONFIG_B64:-}" ]; then mkdir -p /workspace/.kube echo "$KUBECONFIG_B64" | base64 -d > /workspace/.kube/config chmod 600 /workspace/.kube/config fi - name: Run apply for all stacks run: | . ./scripts/load_admin_creds.sh ./scripts/run_all_stacks.sh apply