Previously
In one of my previous blogs I talked about deploying .Bicep files the easy way with YAML based Azure Pipelines. Now let's have look at YAML a bit more, specifically focusing on the conditional part of Stages, Jobs and Steps.
Hierarchies within YAML
When writing a YAML for your CI/CD within Azure DevOps with Azure Pipelines for example. You might want to use multiple Stages, such as Build & Deploy, or something more advanced as a DTAP (Development, Test, Acceptance, Production). Each of these Stages might have multiple Jobs that needs to happen before you can continue to the next and each of these Jobs might have multiple Steps (via tasks) to execute specific code or steps.
It basically comes down to the following:
YAML can have multiple Stages Stages can have multiple Jobs Jobs can have multiple Steps
Below you will find an example of the hierarchy within YAML.
stages:
- stage: StageA #Highest in the hierarchy
jobs:
- job: JobA #Step lower
steps:
- task: Bash@3 #Lowest in the hierarchy
name: Task_A
inputs:
targetType: inline
script: echo 'Task A'
Dependencies and conditions
Stages can depend on each other, the same goes for Jobs and Tasks. Conditions can go paired with dependencies, but are not required. Within conditions you can do certain checks, such as checking whether something was successful or failed or you can just always execute it.
Below a simple example of dependencies and conditions for Stages, Jobs and Steps:
trigger:
- none
pool:
vmImage: ubuntu-latest
stages:
- stage: StageA
jobs:
- job: JobA
steps:
- task: Bash@3
name: Task_A
inputs:
targetType: inline
script: echo 'Task A'
- stage: StageB
dependsOn: StageA
condition: succeeded() #failed(') #Always()
jobs:
- job: JobB
steps:
- task: Bash@3
name: Task_B
inputs:
targetType: inline
script: echo 'Task B'
- job: JobB2
dependsOn: JobB
condition: succeeded() #failed() #Always()
steps:
- task: Bash@3
name: Task_B2
inputs:
targetType: inline
script: echo 'Task B2'
- stage: StageC
jobs:
- job: JobC
steps:
- task: Bash@3
name: Task_C
inputs:
targetType: inline
script: echo 'Task C'
- task: Bash@3
name: Task_C2
condition: succeeded() #failed() #Always()
inputs:
targetType: inline
script: echo 'Task C2'
In the above example I make reference to a single dependency, but it is also possible for a Stage, Job or Step to depend on multiple others. This can simply be done by adding them underneath each other as such:
dependsOn:
- StageA #JobA
- StageB #JobB
For more information on dependencies and conditions you can check here.
Variables
Conditions can also be more complex, for example when they check variables or even variables from a different Stages, Jobs or Steps and vice versa. In the following examples we will look at some of these:
Stage to Stage variable in conditions
trigger:
- none
pool:
vmImage: ubuntu-latest
stages:
- stage: StageA
jobs:
- job: JobA
steps:
- task: Bash@3
name: Task_A
inputs:
targetType: inline
script: |
myVar=true
echo "##vso[task.setvariable variable=myVar;isOutput=true]$myVar"
- stage: StageB
dependsOn: StageA
condition: eq(dependencies.StageA.outputs['JobA.Task_A.myVar'], 'true')
jobs:
- job: JobB
steps:
- task: Bash@3
name: Task_B
inputs:
targetType: inline
script: |
echo 'I may run now!'
Job to Job variables in conditions
trigger:
- none
pool:
vmImage: ubuntu-latest
stages:
- stage: StageA
jobs:
- job: JobA
steps:
- task: Bash@3
name: Task_A
inputs:
targetType: inline
script: |
myVar=true
echo "##vso[task.setvariable variable=myVar;isOutput=true]$myVar"
- job: JobB
dependsOn: JobA
condition: eq(dependencies.JobA.outputs['Task_A.myVar'], 'true')
steps:
- task: Bash@3
name: Task_B
inputs:
targetType: inline
script: |
echo 'I may run now!'
Step to Step variable in conditions
trigger:
- none
pool:
vmImage: ubuntu-latest
stages:
- stage: StageA
jobs:
- job: JobA
steps:
- task: Bash@3
name: Task_A
inputs:
targetType: inline
script: |
myVar=true
echo "##vso[task.setvariable variable=myVar;isOutput=true]$myVar"
- task: Bash@3
name: Task_B
condition: eq(variables['Task_A.myVar'], 'true')
inputs:
targetType: inline
script: |
echo 'I may run now!'
In the above examples, it is obvious that I use the eq (equal) expression, but there are a lot of expressions possible. For more information about expressions you can look here.
What's next?
The holidays are about to start, let's see if an interesting subject comes to mind that I can write about.