adaptive.run TECH BLOG

Cloud can be tricky sometimes. Find out what scenarios we've ran into that are worth being mentioned and explained.

Using Environment Variables in Azure Bicep

Level: 200
Publishing date: 31-Jan-2025
Author: Catalin Popa

Azure Bicep allows you to retrieve environment variables during template compilation, enabling dynamic configurations without hardcoding values. This is especially useful when deploying through Azure Pipelines, where pipeline variables automatically become environment variables.

In this guide, we’ll cover:

      • How the readEnvironmentVariable() function works
      • Setting environment variables in an Azure Pipeline
      • Using environment variables in Bicepparam
      • Handling missing environment variables
      • Best practices for cross-platform compatibility
_______________________________________________________________________________

Understanding readEnvironmentVariable()

The readEnvironmentVariable() function retrieves values from the deployment environment and has the following syntax:

Bicep

readEnvironmentVariable(environmentVariableName: string, default: string)

      • The first parameter (environmentVariableName) is required and specifies the variable name.
      • The second parameter (default) is optional and sets a fallback value if the environment                     variable is not found.
      • The function returns a string, so when dealing with numbers or booleans, use int() or bool()             to cast values appropriately.

Key Limitations:

Environment variables are loaded at compile time, not runtime.
This function is only available in Bicepparam files, meaning it cannot be used directly in Bicep files.
_______________________________________________________________________________

Setting Environment Variables in an Azure Pipeline

Before retrieving environment variables in Bicep, they must be defined in the Azure DevOps pipeline. This example pipeline:

      1. Defines a parameterized Environment variable with a default value.
      2. Generates a random string dynamically using PowerShell.
      3. Executes a Bicep deployment, passing the environment variables.

Azure Pipeline Configuration (YAML)

parameters:
- name: Environment
type: string
default: dev
values:
- prod
- acc
- tst
- dev

pool:
vmImage: 'windows-latest'

variables:
- name: Environment
value: ${{ parameters.Environment }}

steps:
- powershell: |
$random = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object {[char]$_})
Write-Output "##vso[task.setvariable variable=RandomizedString]$random"
displayName: 'Generate a Random String'

- task: AzureCLI@2
inputs:
azureSubscription: 'spn-readEnvironmentVariable'
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
az deployment group create --template-file ./main.bicep --parameters ./config.bicepparam --resource-group rg-demo 

What Happens Here?

      • The Environment variable is passed from a YAML parameter and stored as an environment variable.
      • A randomized string (RandomizedString) is created dynamically using PowerShell.
      • Both variables become accessible in Bicep via readEnvironmentVariable().
_______________________________________________________________________________

Using Environment Variables in Bicepparam

Now that the variables are set in the pipeline, they can be retrieved in a Bicepparam file.
Bicepparam File (config.bicepparam)

using 'main.bicep'

var varEnvironment = readEnvironmentVariable('Environment', 'dev')

param parRandomizedString = readEnvironmentVariable('RandomizedString')
param parResourceName = 'my-resource-${varEnvironment}' 

Explanation:


varEnvironment stores the Environment variable, using "dev" as the default value.
parRandomizedString retrieves the RandomizedString variable from the pipeline.
parResourceName dynamically sets a resource name based on the environment variable.

This ensures that deployments can be customized dynamically without modifying the Bicep template.
_______________________________________________________________________________

Verifying the Output in Bicep

To confirm that the environment variables are properly set, the Bicep template (main.bicep) includes output values:

Bicep File (main.bicep)

param parRandomizedString string
param parResourceName string

output outRandomizedString string = parRandomizedString
output outResourceName string = parResourceName 

Expected Deployment Output:

outRandomizedString: "xYzAbCdEfG"
outResourceName: "my-resource-dev" 

This confirms that:

✔ The random string was successfully generated and retrieved.
✔ The environment variable (Environment) was correctly applied to the resource name.
________________________________________

Handling Missing Environment Variables

If an environment variable is not set, Bicep throws an error at compile time, specifically Error BCP338:

Error BCP338: Failed to evaluate parameter "NonExistingEnvVariable": Environment variable does not exist, and no default value set.

To prevent this issue, always provide a default fallback value:

var varEnvironment = readEnvironmentVariable('Environment', 'dev')

This ensures that if Environment is missing, "dev" is used instead.
_______________________________________________________________________________

Cross-Platform Considerations: Windows vs. Linux

The naming convention for environment variables differs between Windows and Linux:

🔹 Windows (windows-latest)
      • Variables are case-sensitive: $env:Environment, $env:RandomizedString
      • Matches the exact case defined in Azure DevOps
🔹 Linux (ubuntu-latest)
     • Variables are automatically converted to uppercase: $env:ENVIRONMENT,                                       $env:RANDOMIZEDSTRING
    • In Bicepparam, environment variable names must be uppercase when running on Linux.

Example Adjustments for Linux Compatibility

If deploying on Linux-based agents, update Bicepparam as follows:

var varEnvironment = readEnvironmentVariable('ENVIRONMENT', 'dev')
param parRandomizedString = readEnvironmentVariable('RANDOMIZEDSTRING') 

This ensures cross-platform compatibility, avoiding deployment issues.
_______________________________________________________________________________

Conclusion

Using environment variables in Azure Bicep allows for dynamic deployments, enhancing flexibility without modifying templates.

Key Takeaways:

✔ readEnvironmentVariable() retrieves environment variables during compilation
✔ Azure Pipelines can pass dynamic values as environment variables
✔ Providing a default value prevents errors if a variable is missing
✔ Cross-platform considerations are essential for Windows vs. Linux deployments

By leveraging this approach, your Azure Bicep templates become more dynamic and adaptable, allowing seamless parameterization and automation in your Infrastructure-as-Code (IaC) workflows.

Mobirise
adaptive.run

Transform your business.
Run adaptive.

Contact

Phone: +40 73 523 0005
Email: hello@adaptive.run

Mobirise Website Builder
Mobirise Website Builder

© Copyright  2019-2025 adaptive.run- All Rights Reserved