Skip to content

Terraform Unified Workflow

Auto-generated by scripts/generate_docs.py — edit the workflow YAML, not this file.

File: .github/workflows/terraform-unified.yml

Description


Workflow: terraform-unified.yml — Main Infrastructure Orchestration

The single entry point for all Terraform operations across tenants and

customers. Supports plan / apply / destroy for any module or MODULE=ALL.

Input relationship:

TENANT_NAME + CLIENT_NAME + DEVOPS_ENV → configs///.json

MODULE → which submodule directory to target

TARGET_RAAS_ENV → env-raas sub-env (prod/nonprod/all)

MODULE=ALL behaviour:

Reads module list from the customer's JSON config (NOT from .gitmodules).

base-account and base-connectivity are excluded from ALL runs because they

are phase-1 modules managed separately.

For destroy, the module order is reversed so resources are torn down in the

correct dependency order.

env-raas special case:

env-raas contains both prod and nonprod sub-environments. When

TARGET_RAAS_ENV=all, the matrix fans out into two entries so both

sub-environments are processed in the same workflow run.

Security scan integration:

Optional Trivy scan runs before any Terraform operations when

SECURITY_SCAN=true. The terraform job is skipped if the scan fails or if

APPLY_FIXES=true (fixes must be applied in a separate run).


Triggers

Trigger types: workflow_dispatch

Manual Dispatch Inputs (workflow_dispatch)

Input Type Required Default Description
ACTION choice yes The Terraform action to perform. Options: plan, apply, destroy
TENANT_NAME string yes raas The customer tenant in which we are deploying to
CLIENT_NAME string yes rhapsody The customer in which we are deploying to
DEVOPS_ENV choice yes staging1 IaC environment (e.g., staging1, staging2, or prod). Options: staging1, staging2, staging3, prod
MODULE choice yes base-counter Specific Terraform module to target, or ALL/NONE. Options: NONE, base-account-phase1, base-connectivity-phase1, base-counter, base-core, base-diagnostics, env-raas, env-snapshots, base-cifs, base-sftp, base-expressroute, base-peering, base-routes, base-vpn, base-monitoring, env-upwind, env-raas-lb, env-raas-api, env-directcifs, env-filetransfer, base-fwrules, ALL
TARGET_RAAS_ENV choice yes all Target RaaS environment (prod/nonprod/all) for env-raas module state file. Options: prod, nonprod, all
SECURITY_SCAN choice yes false Execute infrastructure security scan (Trivy): 'true' or 'false' Options: true, false
AI_PROVIDER choice no copilot-cli AI provider for security scan remediation Options: copilot-cli, gemini, openai
APPLY_FIXES choice no false Apply AI-suggested security fixes (requires manual approval) Options: true, false
SAFETY_ENFORCE choice no true Block apply on an outage-class plan classification (the plan-safety gate). 'true' enforces; 'false' is the emergency kill-switch (gate becomes report-only). Options: true, false

Permissions

  • id-token: write
  • contents: read

Jobs

setup — Setup Deployment Matrix

Property Value
Runs on ubuntu-latest

Outputs:

  • matrix — ${{ steps.set-matrix.outputs.matrix }}
  • env_tier — ${{ steps.resolve-runner-env.outputs.env_tier }}
  • region — ${{ steps.fetch-region.outputs.region }}

Steps:

| Step | Action / Detail

---|---|---
1 | Checkout repository | actions/checkout@v4
2 | Fetch customer region from CosmosDB | Inline script: python3 -m venv /tmp/region-venv
3 | Resolve Runner Environment Tier | Inline script: env_tier="${{ github.event.inputs.DEVOPS_ENV }}"
4 | Setup Python for CosmosDB Query (conditional) | actions/setup-python@v5
5 | Determine Target Environments and Modules | Inline script: action="${INPUT_ACTION}"

security_scan — Security Scan

Property Value
Uses (reusable) ./.github/workflows/callable-security-scan.yml

Condition: github.event.inputs.SECURITY_SCAN == 'true'

Inputs passed (with):

  • MODULE: ${{ inputs.MODULE }}
  • TENANT_NAME: ${{ inputs.TENANT_NAME }}
  • CLIENT_NAME: ${{ inputs.CLIENT_NAME }}
  • DEVOPS_ENV: ${{ inputs.DEVOPS_ENV }}
  • AI_PROVIDER: ${{ inputs.AI_PROVIDER || 'copilot-cli' }}
  • APPLY_FIXES: ${{ inputs.APPLY_FIXES == 'true' }}

Secrets passed:

  • GEMINI_API_KEY
  • OPENAI_API_KEY
  • COPILOT_PAT_KEY
  • APP_PRIVATE_KEY

terraform — ${{ inputs.ACTION }} | ${{ matrix.module }} | ${{ matrix.environment }}${{ matrix.peering_name && format(' | {0}', matrix.peering_name) || '' }}

Property Value
Runs on self-hosted, terraform, ${{needs.setup.outputs.env_tier}}, ${{needs.setup.outputs.region}}, ${{inputs.TENANT_NAME}}
Depends on setup, security_scan
Environment ${{ inputs.TENANT_NAME }}

Condition: always() && (needs.security_scan.result == 'success' || needs.security_scan.result == 'skipped') && inputs.APPLY_FIXES != 'true'

Strategy:

  • fail-fast: True
  • max-parallel: 1
  • include: 43 entries

Steps:

| Step | Action / Detail

---|---|---
1 | Cleanup Step (conditional) | Inline script: rm -rf "${WORKSPACE_DIR}"/*
2 | Checkout Code | actions/checkout@v4
3 | Checkout with submodules | ./.github/actions/checkout-with-submodules
4 | Checkout Submodules | ./.github/actions/checkout-repos
5 | Fetch Azure Credentials | ./.github/actions/fetch-azure-credentials
6 | Setup Terraform Environment | ./.github/actions/setup-terraform-vars
7 | Initialize Terraform | ./.github/actions/terraform-init
8 | Plan Terraform (conditional) | ./.github/actions/terraform-plan
9 | Apply Terraform (conditional) | ./.github/actions/terraform-apply
10 | Destroy Terraform (conditional) | ./.github/actions/terraform-destroy
11 | 📊 AI Triage Summary (conditional) | Inline script: if [[ "$ACTION" == "plan" ]]; then
12 | Fail job if Terraform failed (conditional) | Inline script: echo "::error::Terraform ${INPUT_ACTION} failed for module ${MODULE_NAME}. See A

Secrets Referenced

  • ACTIVATION_KEY
  • APP_PRIVATE_KEY
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • COPILOT_PAT_KEY
  • CORALOGIX_API_KEY
  • COSMOSDB_CREDS_KEY_SECRET
  • GEMINI_API_KEY
  • OPENAI_API_KEY
  • RHN_ORG_ID
  • S1_API_KEY
  • S1_TOKEN
  • SSH_PUB_KEY
  • UPWIND_CLIENT_SECRET

Composite Actions Used


_📋Auto-Generated Documentation | Team: Azure Infrastructure | Generated by: AI Documentation Engine | Date: 2026-08-14 22:10 UTC _