Versions
The Azure Baseline, release 1.0.0, pins every tool, provider, GitHub Action and pre-commit hook: OpenTofu 1.12.6, Terragrunt 1.1.6, hashicorp/azurerm ~> 5.7, hashicorp/azuread ~> 3.10 and Azure/azapi ~> 2.13. Engineers' machines, the CI workflows and the self-hosted runner image use the same versions, so a plan means the same thing everywhere.
Where the pins live
root.hcl is the only place OpenTofu, Terragrunt and the three Azure providers are pinned. It generates the provider requirements into every unit:
generate "versions" {
path = "versions.tf"
if_exists = "skip"
contents = <<-EOF
terraform {
required_version = ">= 1.12.6"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 5.7"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 3.10"
}
azapi = {
source = "Azure/azapi"
version = "~> 2.13"
}
}
}
EOF
}
A module ships its own versions.tf only when it needs something root.hcl cannot know, and then repeats the three pins exactly. Two modules declare the azurerm.hub provider alias (vnet-peering, private-dns-links). Four use hashicorp/time ~> 0.13 to wait for role assignments to propagate before the first data-plane write (key-vault, platform-key-vault, storage-account, container-apps-runners). A guard script checks the rule in pre-commit and CI. The reasons are recorded in tooling and version pinning.
Tools and providers
| Component | Version | Where it is pinned |
|---|---|---|
| OpenTofu | 1.12.6 | root.hcl constraint >= 1.12.6, < 2.0.0; exact version in the plan, apply and drift-detection workflows and the runner image |
| Terragrunt | 1.1.6 | root.hcl constraint >= 1.1.6; exact, checksum-verified download in the same three workflows and the runner image |
hashicorp/azurerm | ~> 5.7 | Generated by root.hcl into every unit |
hashicorp/azuread | ~> 3.10 | Generated by root.hcl into every unit |
Azure/azapi | ~> 2.13 | Generated by root.hcl into every unit |
hashicorp/time | ~> 0.13 | The versions.tf of the four modules that wait for role propagation |
| tflint | v0.64.0 | The plan workflow, checksum-verified |
tflint-ruleset-azurerm | 0.32.0 | .tflint.hcl |
| Python | 3.12 | The guard scripts, with pyyaml |
| Azure CLI | >= 2.75 | Operations from a workstation; 2.90.0 exactly in the runner image |
Runner image
The self-hosted runners start from runner-image/Dockerfile. Its base is ghcr.io/actions/actions-runner:2.337.0, pinned by tag and image digest together. The Azure CLI is one pinned release from Microsoft's signed package repository, and every other tool download is pinned by version and verified against its release SHA-256 checksum before it is installed:
| Tool | Version |
|---|---|
| Azure CLI | 2.90.0 |
| OpenTofu | 1.12.6 |
| Terragrunt | 1.1.6 |
| kubectl | v1.36.5 |
| kubelogin | v0.2.20 |
| Helm | v3.22.0 |
| sops | 3.13.3 |
| yq | v4.47.1 |
The build ends with a smoke test that runs every binary, so a broken download fails the image build rather than the first pipeline.
GitHub Actions
| Action | Version | Workflows |
|---|---|---|
actions/checkout | v7.0.1 | Plan, apply, drift detection, runner image |
azure/login | v3.1.0 | Plan, apply, drift detection, runner image |
opentofu/setup-opentofu | v2.0.2 | Plan, apply, drift detection |
actions/upload-artifact | v7.0.1 | Plan, apply (run reports) |
actions/github-script | v9.0.0 | Plan (pull request comment), drift detection (issue) |
bridgecrewio/checkov-action | v12.3128.0 | Plan |
aquasecurity/trivy-action | v0.36.0 | Plan |
infracost/actions/setup | v4.2.0 | Plan (installs the Infracost CLI) |
infracost/actions/comment | v4.2.0 | Plan (posts the cost comment) |
Each is referenced by its full commit SHA with the release tag in a trailing comment, so a moved tag cannot run different code. Terragrunt and tflint are not installed through an action: the workflows download the release binary and verify its checksum.
Pre-commit hooks
| Hook repository | Revision |
|---|---|
pre-commit/pre-commit-hooks | v6.0.0 |
tofuutils/pre-commit-opentofu | v2.4.2 |
antonbabenko/pre-commit-terraform | v1.109.1 |
bridgecrewio/checkov | 3.3.19 |
The repository's six guard scripts run as local hooks beside these, and again in the plan workflow.
How versions change
A version upgrade is its own pull request, reviewed as a plan before it merges. A provider upgrade changes root.hcl and every module versions.tf that repeats the pin in the same change. An OpenTofu or Terragrunt upgrade changes root.hcl, the plan, apply and drift-detection workflows, and the runner image's version and checksum together. The policy for each kind of change is on the versioning policy page, and the reasons for OpenTofu are in OpenTofu and Terraform.