I am building a CI/CD pipeline with the following steps:
- Check for any changes.
- If changes are found, deploy.
This setup is intended for multiple environments. However, I am encountering an issue when there are more than one environment to deploy:
The deployment for the first environment from the template works as expected. However, the second environment, despite detecting changes, does not initiate the deployment and is marked as "skipped". First env always work like a charm:
Here’s a simplified version of my pipeline configuration:
trigger:
batch: true
branches:
include:
- main
pr:
branches:
include:
- main
stages:
- template: templates/deploy.yml
parameters:
environment: Dev
- template: templates/deploy.yml
parameters:
environment: Uat
and deploy.yml
template:
stages:
- stage: Terraform_Plan_${{ parameters.environment }}
displayName: Plan
condition: always()
jobs:
- job: Terraform_Plan_${{ parameters.environment }}
displayName: Plan Terraform
pool: 'selfhosted'
steps:
- powershell: |
# set it to true or false
Write-Host "##vso[task.setvariable variable=anyTfChanges;isOutput=true]true"
displayName: Detect any Terraform changes
name: anyTfChanges
- stage: Any_Tf_Changes_${{ parameters.environment }}
displayName: Terraform Changes
dependsOn: Terraform_Plan_${{ parameters.environment }}
variables:
anyTfChanges: $[ stageDependencies.Terraform_Plan_${{ parameters.environment }}.Terraform_Plan_${{ parameters.environment }}.outputs['anyTfChanges.anyTfChanges'] ]
condition: and(eq('true', 'true'), eq(dependencies.Terraform_Plan_${{ parameters.environment }}.outputs['Terraform_Plan_${{ parameters.environment }}.anyTfChanges.anyTfChanges'], 'true'))
jobs:
- job: Terraform_Changes_${{ parameters.environment }}
displayName: Detect Terraform Changes
steps:
- checkout: none
- powershell: |
Write-Host "hello world"
displayName: Terraform changes detected
- stage: Terraform_Apply_${{ parameters.environment }}
displayName: Apply ${{ parameters.environment }}
dependsOn: Any_Tf_Changes_${{ parameters.environment }}
jobs:
- deployment: Apply
environment: ${{ parameters.environmentDisplayName }}
displayName: Apply Terraform
pool: 'selfhosted'
strategy:
runOnce:
deploy:
steps:
- checkout: self
- script: |
Write-Host "hello world"
Could I be overlooking something in my configuration that causes the pipeline to behave this way for subsequent environments? Any insights or suggestions would be appreciated!
EDIT1
It only works for first stage:
And when next one has changes. For third one (prod) it does not work when middle stage doesnt have changes
Also when i have two stages, and no changes in first one i can not deploy to second stage because apply
stage is skipped
EDIT2
When i commented depends on:
in apply stage, it still does not work:
2
Answers
From Define conditions:
The
Apply Prd
stage has no conditions set and some of the previous stages were skipped, so that’s why the stage was skipped:Fixing the pipeline
The below example pipeline was used to test the dependencies between stages.
Set
applyChanges
value totrue
orfalse
to simulate changes in each environment:azure-pipeline.yml
templates/deploy.yml
Please note that I’ve changed the names of the stages, jobs and tasks to make it easier to understand.
Running the pipeline:
Based on the documents Conditions – Azure Pipelines | Microsoft Learn and Define variables – Azure Pipelines | Microsoft Learn, please pay attention to the YAML pipeline default behaviors:
Terraform_Apply_${{ parameters.environment }}
, by default, it depends on the stage just before it in the YAML file.Terraform_Apply_${{ parameters.environment }}
, it will use the default condition, which means this stage runs if all direct and indirect dependencies have succeeded, as if you specifiedcondition: succeeded()
.condition
property for a stage / job / step, you overwrite its defaultcondition: succeeded()
. Therefore, you may consider adding the same condition in stageTerraform_Apply_${{ parameters.environment }}
as that you defined for stageAny_Tf_Changes_${{ parameters.environment }}
.Any_Tf_Changes_${{ parameters.environment }}
when writing your own conditions, since overwriting the default condition can lead to your stage running even if the build is cancelled or failed.With those being said, if your actual expectation is to run the stage
Terraform_Apply_${{ parameters.environment }}
only when the stageAny_Tf_Changes_${{ parameters.environment }}
is succeeded, you can try adding the expressioneq(dependencies.Any_Tf_Changes_${{ parameters.environment }}.result, 'Succeeded')
orsucceeded('Any_Tf_Changes_${{ parameters.environment }}')
for apply stage. Here is the part of stageTerraform_Apply_${{ parameters.environment }}
of the YAML pipeline for your reference.