Terraform-to-Azure CI/CD Architecture¶
This CI/CD system is built around two modular GitHub Actions workflows:
-
Detect Changed
.tfvars
Files- Watches for
.tfvars
changes in PRs or pushes tomain
. - Identifies changed files and triggers targeted processing.
- Watches for
-
Process Changed
.tfvars
Files- Runs for each changed file.
- Handles validation, linting, security scanning, cost estimation, and conditional apply/destroy to Azure.
The design ensures fast, targeted, and secure deployments without affecting unrelated environments.
- Design Pattern: Automate Terraform Deployments: (1/2) Detect
- Design Pattern: Automate Terraform Deployments: (2/2) Process
- Grinntec GitHub Repo
Workflow Responsibilities¶
Workflow | Responsibility | Key Outputs |
---|---|---|
Detect Changed .tfvars Files |
Identify changed .tfvars files and trigger processing. |
JSON array of changed file paths. |
Process Changed .tfvars Files |
Fully process one .tfvars file: validate, scan, plan, cost, and deploy/destroy. |
Updated Azure infrastructure or destroyed resources. |
Security Model¶
- OIDC Authentication – No static Azure credentials.
- Scoped Secrets – Only required secrets passed to jobs.
- Concurrency Control – Prevents overlapping runs for the same file.
- State Isolation – Backend config ensures environment separation.
Benefits¶
- Targeted Deployments – Only changed environments are processed.
- Parallel Execution – Multiple
.tfvars
changes run simultaneously. - Modular & Maintainable – Easy to extend or modify.
- Security-First – OIDC, least privilege, secret minimization.
- Cost Awareness – Infracost integrated before apply.
Swimlane Diagram¶
flowchart TB
%% Developer lane
subgraph Dev[Developer]
A[Commit changes to repo]
B[Push to main or open PR]
A --> B
end
%% Workflow 1 lane
subgraph W1[Workflow 1 Detect Changed tfvars]
C[Trigger on tfvars change]
D[Checkout and sync repo]
E[Detect changed tfvars files]
F[Exit workflow]
G[Matrix job one per file]
C --> D --> E
E -->|No changes| F
E -->|Changes found| G
end
%% Workflow 2 lane
subgraph W2[Workflow 2 Process Changed tfvars]
H[Azure login OIDC]
I[Checkout repo]
J[Show file and read CI mode]
K[Configure git for private modules]
L[Cache providers and setup terraform]
M[Ensure lockfile exists]
N[Extract variables from tfvars]
O[Create backend config]
P[Terraform format lint validate]
Q[Terraform plan pre apply]
R[Security scan checkov]
S[Cost estimation infracost]
U{CI mode}
W[Terraform plan only]
X[Terraform apply]
Y[Terraform destroy]
Z[Azure infra updated]
H --> I --> J --> K --> L --> M --> N --> O --> P --> Q --> R --> S --> U
U -->|plan| W --> Z
U -->|apply| X --> Z
U -->|destroy| Y --> Z
end
%% Cross‑lane connections
B --> C
G --> H
%% Colour definitions
classDef dev fill:#d0e6ff,stroke:#003366,stroke-width:1px;
classDef w1 fill:#d5f5e3,stroke:#145a32,stroke-width:1px;
classDef w2 fill:#fdebd0,stroke:#7d6608,stroke-width:1px;
classDef decision fill:#fff3cd,stroke:#7d6608,stroke-width:1px;
%% Assign colours
class A,B dev;
class C,D,E,F,G w1;
class H,I,J,K,L,M,N,O,P,Q,R,S,W,X,Y,Z w2;
class U decision;