Understanding and Using Variables in Azure Pipelines
Variables are a fundamental concept in Azure Pipelines, allowing you to parameterize your build and release processes. They help manage configuration settings, secrets, and dynamic values, making your pipelines more flexible, reusable, and maintainable.
Why Use Variables?
- Parameterization: Easily change values without modifying pipeline definitions.
- Reusability: Create reusable pipeline components by abstracting common settings.
- Security: Securely store and manage sensitive information like API keys and connection strings.
- Readability: Improve the clarity of your pipeline configurations.
- Dynamic Values: Utilize built-in system variables for context-aware information.
Types of Variables
Azure Pipelines supports several types of variables, each with its own purpose and scope.
Pipeline Variables
Defined directly within your pipeline YAML or JSON definition.
- Scope: Entire pipeline run.
- Example: Version numbers, build configurations.
Stage Variables
Defined for a specific stage in a multi-stage pipeline.
- Scope: A single stage.
- Example: Environment-specific deployment paths.
Job Variables
Defined for a specific job within a stage.
- Scope: A single job.
- Example: Agent pool selection for a specific task.
Task Variables
Typically set by tasks themselves and accessible by subsequent tasks.
- Scope: Within the task or job.
- Example: Output from a script.
System Variables
Azure Pipelines provides a rich set of built-in system variables that offer information about the build or release context. These variables are automatically populated and can be accessed directly.
Some common system variables include:
Build.BuildId: The ID of the build.Build.SourceBranch: The branch the build is running for.Build.Repository.Name: The name of the repository.System.TeamFoundationCollectionUri: The URI of the Azure DevOps collection.Release.Environment.Name: The name of the deployment environment.
You can find a comprehensive list in the official Azure Pipelines documentation.
Variable Scope and Precedence
Understanding variable scope and how they interact is crucial for avoiding unexpected behavior.
Scope Hierarchy
Variables are resolved based on their scope, with more specific scopes overriding broader ones.
- Job Variables > Stage Variables > Pipeline Variables
Precedence Rules
If a variable name exists in multiple scopes, the one with the tighter scope (more specific) takes precedence. For example, a job variable named 'MyVar' will override a pipeline variable named 'MyVar'.
Runtime vs. Definition Time
Most variables are evaluated at runtime. However, some are set at definition time. Be mindful of when your variables are being resolved.
Defining and Using Variables
In YAML Pipelines
Variables are typically defined in the variables block at the root level, or within stages, jobs, or templates.
variables:
vmImageName: 'ubuntu-latest'
buildConfiguration: 'Release'
stages:
- stage: Build
jobs:
- job: BuildJob
pool:
vmImage: $(vmImageName)
steps:
- script: echo Building $(buildConfiguration) configuration...
displayName: 'Show Build Configuration'
In Classic Pipelines (UI)
You can define variables through the pipeline editor's "Variables" tab. You can also define them per stage and per agent job.
Secret Variables
For sensitive information, use secret variables. These are encrypted and masked in logs and UI. You can define them in the "Variables" section of your pipeline or as Library Secret Variables.
variables:
- name: apiToken
value: 'your_secret_api_token'
isSecret: true
When using a secret variable, it's best practice to mark it as a secret to prevent exposure in logs.
Runtime Parameters
For interactive prompts during pipeline execution, use runtime parameters. These are defined in the pipeline definition and allow users to provide values when queuing the pipeline.
parameters:
- name: environment
displayName: 'Deployment Environment'
type: string
default: 'dev'
values:
- dev
- staging
- prod
variables:
deployTarget: ${{ parameters.environment }}
stages:
- stage: Deploy
jobs:
- job: DeployJob
steps:
- script: echo Deploying to ${{ variables.deployTarget }}...
displayName: 'Show Deployment Target'
Best Practices
- Use meaningful names: Clearly indicate the purpose of each variable.
- Group related variables: Organize variables logically using variable groups.
- Leverage secret variables: Never hardcode secrets directly in your pipeline definitions.
- Understand scope: Be aware of where your variables are defined and how they are resolved.
- Use parameters for user input: Provide flexibility for pipeline execution.