Versions
The Data and ETL Blueprint pins the same tools as the Azure Enterprise Baseline (OpenTofu 1.12.6, Terragrunt 1.1.6, azurerm ~> 5.7), adds the Databricks provider ~> 1.135, runs the job on the latest Databricks long-term support (LTS) runtime and the trigger on Python 3.12. Every Python library, pre-commit hook and GitHub Action is pinned to an exact version in the code, so a plan or a build means the same thing on every machine.
Where the pins live
root.hcl generates a versions.tf with the OpenTofu and azurerm pins 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"
}
}
}
EOF
}
The two Databricks modules ship their own versions.tf, which replaces the generated one because they need a second provider. They repeat the azurerm pin exactly, and scripts/check-module-versions.py fails in pre-commit and in the plan workflow when they drift apart:
terraform {
required_version = ">= 1.12.6"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 5.7"
}
databricks = {
source = "databricks/databricks"
version = "~> 1.135"
}
}
}
Tools and providers
| Component | Version |
|---|---|
| OpenTofu | 1.12.6 (up to, not including, 2.0.0) |
| Terragrunt | 1.1.6 or later |
hashicorp/azurerm | ~> 5.7 |
databricks/databricks | ~> 1.135 (databricks-catalog and databricks-job only) |
| tflint | 0.64.0, with the azurerm ruleset 0.32.0 |
The plan, apply and drift-detection workflows install exactly OpenTofu 1.12.6 and Terragrunt 1.1.6, and the plan workflow's lint job adds tflint 0.64.0. Each Terragrunt and tflint download is verified against its release checksum. The Databricks resources have no tflint ruleset; tofu validate checks them.
Platform versions
| Component | Version |
|---|---|
| Azure Databricks workspace | Premium |
| Databricks runtime | The latest LTS runtime, looked up at plan time (databricks_spark_version with long_term_support = true) |
| Serverless environment | Version 3, used only when the spark_serverless switch is on |
| Container Apps | Workload profiles environment, Consumption profile |
| Trigger base image | python:3.12-slim, with Debian security updates applied at build time |
The runtime follows Databricks: a new LTS release shows up as a change to the job cluster's spark_version in the next plan. Review it like any other change before it merges.
Application runtime
| Component | Version |
|---|---|
| Python | >= 3.12 (pyproject.toml), 3.12 in CI |
azure-identity | 1.26.0 |
azure-keyvault-secrets | 4.11.3 |
azure-storage-blob | 12.31.0 |
azure-storage-queue | 12.18.0 |
databricks-sdk | 0.146.0 |
| PySpark for local tests | 4.0.4, on Java 17 |
| Ruff | 0.16.10, target py312, line length 120 |
| pytest | 9.1.1 |
The trigger image installs exactly the versions in src/trigger/requirements.txt. The image is built once per merge and promoted unchanged, so every stage runs the same dependency set. The transform itself uses plain PySpark and runs on whatever Spark the Databricks runtime provides.
Pre-commit hooks
| Hook source | Version | Repository |
|---|---|---|
pre-commit/pre-commit-hooks | v6.0.0 | Both |
tofuutils/pre-commit-opentofu | v2.4.2 | Infrastructure |
antonbabenko/pre-commit-terraform | v1.109.1 | Infrastructure |
bridgecrewio/checkov | 3.3.19 | Infrastructure |
bridgecrewio/checkov | 3.3.22 | Code |
astral-sh/ruff-pre-commit | v0.16.10 | Code |
The infrastructure repository adds four local hooks that run its guard scripts: mock outputs, stack layout, module provider versions and required inputs.
GitHub Actions
| Action | Version |
|---|---|
actions/checkout | v7.0.1 |
actions/setup-python | v7.0.0 |
actions/setup-java | v6.0.1 |
azure/login | v3.1.0 |
docker/setup-buildx-action | v4.4.1 |
docker/build-push-action | v7.4.0 |
aquasecurity/trivy-action | v0.36.0 |
bridgecrewio/checkov-action | v12.3128.0 |
opentofu/setup-opentofu | v2.0.2 |
actions/upload-artifact | v7.0.1 |
actions/github-script | v9.0.0 |
Each is referenced by its full commit SHA with the version in a comment, so a moved tag cannot change what runs.
How versions change
A version change is its own pull request. For the infrastructure it is planned against all three stages before it merges; for the code it goes through the normal build and release path. The Baseline's pins are in its version matrix, the policy is on the versioning policy page, and the versions across all BuiltForProd repositories are in the release notes.