How to implement conditional run-time approval in Azure DevOps pipelines?
I need to configure a job in Azure DevOps that requires approval only when a runtime variable has a specific value. According to the documentation, approvals are evaluated at compile time, which means even if my condition returns false, the approval is still required to start the job, even if the job doesn’t perform any actions.
Is there a workaround to implement conditional run-time approvals in Azure DevOps pipelines?
Conditional run-time approval in Azure DevOps pipelines presents a significant challenge due to the way Azure Pipelines evaluates conditions. While there isn’t direct support for conditional approvals, several effective workarounds can achieve similar functionality.
Azure Pipelines evaluates conditions before pipeline execution, which means runtime variables cannot be used directly in approval conditions. The Microsoft Learn documentation explicitly states: “Conditions are evaluated to determine whether to start a stage, job, or step. Therefore, nothing computed during the runtime of a stage, job, or step is available to use within that same stage, job, or step.”
Here are the most effective workarounds for implementing conditional run-time approvals:
Contents
- Understanding the Core Limitation
- Workaround 1: Stage Dependency Variables
- Workaround 2: Parameter-Based Conditional Logic
- Workaround 3: AgentLess Job Manual Approvals
- Workaround 4: Template-Based Conditional Stages
- Best Practices and Recommendations
- Alternative Approaches
- Conclusion
Understanding the Core Limitation
Azure Pipelines uses a two-phase evaluation system:
- Compile-time evaluation: Conditions are evaluated before execution to determine what should run
- Runtime evaluation: Variables and expressions are evaluated during execution
This separation means that variables set during runtime cannot influence decisions made at compile time, such as whether to require approval. As explained in the official documentation, “if you set a variable in a job using a runtime expression with $[ ] syntax, you can’t use that variable in conditions within that job.”
Workaround 1: Stage Dependency Variables
The most robust approach is to use stage dependency variables to pass runtime information between stages and make approval decisions based on those values.
stages:
- stage: evaluation_stage
jobs:
- job: determine_approval
steps:
- task: PowerShell@2
name: set_approval_flag
inputs:
targetType: inline
pwsh: true
script: |
$requireApproval = $true # Logic to determine if approval is needed
echo "##vso[task.setvariable variable=needApproval;isOutput=true]$requireApproval"
- stage: deployment_stage
dependsOn: evaluation_stage
condition: eq(dependencies.evaluation_stage.outputs['determine_approval.set_approval_flag.needApproval'], 'true')
jobs:
- deployment: deploy_job
environment: production
strategy:
runOnce:
deploy:
steps:
- task: ManualIntervention@0
name: manual_approval
inputs:
instructions: 'Please review and approve this deployment'
This approach works because:
- The evaluation stage runs first and computes the approval requirement
- The result is passed as an output variable
- The deployment stage condition checks this output before deciding whether to run
- If the condition is true, the approval gate is executed
According to Black Marble’s blog, “AgentLess job manual approvals are evaluated after the job condition, so do not suffer the same problem.”
Workaround 2: Parameter-Based Conditional Logic
Using parameters with runtime evaluation can provide conditional behavior, though with some limitations:
parameters:
- name: requireApproval
type: boolean
default: false
stages:
- stage: deployment
condition: eq('${{ parameters.requireApproval }}', 'true')
jobs:
- deployment: deploy_job
environment: production
strategy:
runOnce:
deploy:
steps:
- task: ManualIntervention@0
inputs:
instructions: 'Manual approval required'
To make this work at runtime, you can use the Azure DevOps REST API or Azure CLI to set the parameter value:
az pipelines run --parameters requireApproval=true --branch main
This approach is limited because parameters are typically set before execution, but it can work when combined with appropriate default values and external logic.
Workaround 3: AgentLess Job Manual Approvals
For deployment jobs, you can use AgentLess jobs with manual approvals that are evaluated after the job condition:
stages:
- stage: conditional_approval
jobs:
- deployment: deploy_with_approval
environment: production
pool: none # AgentLess job
strategy:
runOnce:
deploy:
steps:
- task: PowerShell@2
name: check_conditions
inputs:
targetType: inline
pwsh: true
script: |
# Runtime condition evaluation
$shouldApprove = $true # Your logic here
if ($shouldApprove) {
echo "##vso[task.logissue type=warning]Manual approval required"
echo "##vso[task.complete result=SucceededWithIssues;]"
} else {
echo "##vso[task.complete result=Succeeded;]"
}
- task: ManualIntervention@0
condition: eq(dependencies['deploy_with_approval'].result, 'SucceededWithIssues')
inputs:
instructions: 'Please review and approve this deployment'
This approach leverages the fact that AgentLess jobs don’t suffer from the same condition evaluation limitations as regular jobs.
Workaround 4: Template-Based Conditional Stages
Using templates with conditional expressions allows for more flexible approval logic:
# templates/conditional-approval.yml
parameters:
- name: approvalRequired
type: boolean
default: false
stages:
- stage: deploy
condition: eq('${{ parameters.approvalRequired }}', 'true')
jobs:
- deployment: deploy_job
environment: production
strategy:
runOnce:
deploy:
steps:
- task: ManualIntervention@0
inputs:
instructions: 'Manual approval required'
# main pipeline
stages:
- template: templates/conditional-approval.yml
parameters:
approvalRequired: true
This approach allows you to dynamically include or exclude approval stages based on runtime conditions.
Best Practices and Recommendations
Based on the research findings, here are the key recommendations:
- Use Stage Dependency Variables: This is the most reliable approach for conditional approvals
- Separate Evaluation Logic: Create dedicated stages/jobs to compute conditions before making approval decisions
- Leverage AgentLess Jobs: For deployment scenarios, AgentLess jobs with manual approvals work well
- Plan for Pipeline Architecture: Design your pipeline with conditional execution in mind from the beginning
The Microsoft Learn documentation emphasizes: “You need to assign a default value in your YAML file or when you run your pipeline. If you don’t assign a default value or set default to false, the first available value is used.”
Alternative Approaches
If the above workarounds don’t meet your needs, consider these alternatives:
External Approval Service
Integrate with an external approval service that can make decisions based on runtime conditions and trigger pipeline execution accordingly.
Multi-Pipeline Approach
Break your deployment into separate pipelines:
- A pipeline that evaluates conditions and sets appropriate variables
- A second pipeline that executes based on those variables and includes approval logic
Azure Policy Integration
Use Azure Policy to control deployment permissions based on conditions that can be evaluated at runtime.
Conclusion
While Azure DevOps doesn’t natively support conditional run-time approvals, several effective workarounds exist:
- Stage Dependency Variables - Most reliable approach for complex scenarios
- Parameter-Based Logic - Simpler but with limitations
- AgentLess Job Approvals - Ideal for deployment jobs
- Template-Based Conditional Stages - Flexible and reusable
The key is to separate condition evaluation from approval execution, using Azure Pipelines’ dependency system to pass runtime information between pipeline stages. As one Stack Overflow contributor noted, “While Shayki is correct that it is not supported - there is a workaround that I am currently using.”
For mission-critical scenarios, consider combining these approaches with external approval systems or breaking the process into multiple pipelines to achieve the desired conditional approval behavior.
Sources
- Pipeline conditions - Azure Pipelines | Microsoft Learn
- Using Azure DevOps Stage Dependency Variables with Conditional Stage and Job Execution | Black Marble
- Conditional Stage Execution in Azure DevOps Pipelines - Stack Overflow
- Conditional Approval gate in deployment jobs in azure pipelines - Stack Overflow
- Azure DevOps YAML conditional Stages, Jobs and Steps - CloudShift
- Expressions - Azure Pipelines | Microsoft Learn
- Conditional execution for stage - Azure DevOps - GeralexGR
- Use runtime and type-safe parameters - Azure Pipelines | Microsoft Learn