Infrastructure Changes Are Too Risky to Deploy Blindly? Validate and Test Bicep
A Bicep file can compile successfully and still contain an unintended infrastructure change. For example, a one-line edit could change storage redundancy or remove a container before anyone notices.
CloudTrips needs a repeatable safety gate that catches code regressions locally, checks the template with Azure, and shows the effect on live resources before deployment.
Understand the Three Checks
Each check answers a different question:
| Check | Question answered |
|---|---|
| Snapshot | Did the Bicep result change from the approved code baseline? |
| Preflight validation | Will Azure accept this template, configuration, and access? |
| What-if | How would the deployment change the current Azure resources? |
Snapshots are local and deterministic. Preflight and what-if contact Azure.
Make the Snapshot Command Available
Snapshots require Bicep CLI version 0.41.2 or later. Check the installed
version:
az bicep version
The Azure CLI installation used in this project stores the Bicep executable in
$HOME/.azure/bin. Run snapshot commands through that executable:
"$HOME/.azure/bin/bicep" --version
If the file does not exist, install it:
az bicep install
If the reported version is older than 0.41.2, run az bicep upgrade.
Capture the Approved TEST Baseline
From cloudtrips-bicep, create a snapshot:
"$HOME/.azure/bin/bicep" snapshot environments/test.bicepparam \
--mode overwrite \
--subscription-id 00000000-0000-0000-0000-000000000000 \
--resource-group rg-cloudtrips-bicep-test-weu \
--location westeurope \
--deployment-name deploy-cloudtrips-storage-test
This creates environments/test.snapshot.json. Commit this file because it is
the approved test baseline, not disposable build output.
The zero-filled subscription ID is deliberate. Snapshot runs locally and does
not authenticate with that ID. It supplies stable context for expressions such
as resourceGroup().id and uniqueString(), so every developer produces the
same result. The snapshot is not expected to contain the live storage-account
name.
Do not edit the generated JSON manually.
Confirm That Unchanged Code Passes
Validate the current Bicep result against the snapshot:
"$HOME/.azure/bin/bicep" snapshot environments/test.bicepparam \
--mode validate \
--subscription-id 00000000-0000-0000-0000-000000000000 \
--resource-group rg-cloudtrips-bicep-test-weu \
--location westeurope \
--deployment-name deploy-cloudtrips-storage-test
No output and exit code 0 mean that the current result matches the baseline.
Always reuse exactly the same context values when validating it.
Prove That the Test Detects a Risk
Temporarily change this line in environments/test.bicepparam:
param storageSku = 'Standard_GRS'
Run the same snapshot command with --mode validate. It should fail and show
the storage SKU changing from Standard_LRS to Standard_GRS.

Restore the approved value:
param storageSku = 'Standard_LRS'
Run snapshot validation again. It should now succeed with no output. Use
--mode overwrite only after a change has been reviewed and intentionally
approved; never overwrite the baseline simply to silence a failed test.
Run Azure Preflight Validation
Select the real TEST subscription and ask Azure to validate the deployment:
az account set \
--subscription "<CloudTrips TEST subscription name or ID>"
az deployment group validate \
--name validate-cloudtrips-storage-test \
--resource-group rg-cloudtrips-bicep-test-weu \
--parameters environments/test.bicepparam \
--validation-level Provider \
--query "properties.provisioningState" \
--output tsv
Provider performs template, resource-provider, and permission checks. A
successful result is Succeeded, but it does not prove that the live
environment is unchanged.
Compare with the Live Environment
Finish with what-if:
az deployment group what-if \
--resource-group rg-cloudtrips-bicep-test-weu \
--parameters environments/test.bicepparam \
--validation-level Provider
Review every proposed change. The known Storage provider defaults can still appear as noise, but there must be no unexpected create, delete, replacement, SKU, container, or tag change.

CloudTrips now has three separate gates: snapshot catches unintended code changes, preflight checks whether Azure accepts the deployment, and what-if compares the approved code with live resources. A later automation trip can run the same checks for every pull request.