deployment dependencies condition skipped azure pipeline - azure-devops

Created a pipeline. Have 2 stages. the stage job is deployment second stage has a condition derived from the first stage variable. the pipeline sample is given below
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: Stage
jobs:
- deployment: Staging
displayName: Stage the WebApp
environment: stg
strategy:
runOnce:
deploy:
steps:
- bash: echo "##vso[task.setvariable variable=myStageOutputVar;isOutput=true]true"
env:
myVar: 'this is a stage output var'
name: printvar
- stage: Swap
dependsOn: Stage
condition: eq(dependencies.Stage.Staging.outputs['Staging.printvar.myStageOutputVar'], 'true')
variables:
myVarfromStage: $[ stageDependencies.Stage.Staging.outputs['Staging.printvar.myStageOutputVar'] ]
jobs:
- deployment: Production
displayName: Swap to production
environment: adt
strategy:
runOnce:
deploy:
steps:
- script: echo $(myVarfromStage)
the Swap - stage is getting skipped every time . Any changes need to do it in the condition ?

I suppose that you could look into this doc for the expression.
You will need to edit your condition as below. Notice Staging.Staging
- stage: Swap
dependsOn: Stage1
condition: eq(dependencies.Stage1.outputs['Staging.Staging.printvar.myStageOutputVar'], 'true')

Related

Azure Devops pipeline yml looping over stages

How can i loop over an array or through an object to create stages?
Below is a yml file that works. You can see the build stage loops over the parameters environments for jobs. IS it possible to achieve the same thing for the publishing stages?
The publishing stages require manual approval, must run in order and only when the previous stage is successfully complete?
parameters:
- name: 'environments'
type: object
default:
- environment: development
variableGroup: strata2-admin-spa-vg
dependsOn: 'build'
- environment: test
variableGroup: strata2-test-admin-spa-vg
dependsOn: 'development'
- environment: production
variableGroup: strata2-development-variables
dependsOn: 'development'
- name: 'buildTemplate'
type: string
default: buildTemplate.yml
- name: 'publishTemplate'
type: string
default: publishTemplate.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
stages:
- stage: build
displayName: Build stage
jobs:
# Can I do this for stages?
- ${{each build in parameters.environments}}:
- template: ${{parameters.buildTemplate}}
parameters:
environment: ${{build.environment}}
variableGroup: ${{build.variableGroup}}
# How to loop over parameters.environments to dynamically create stages
- stage: Publish_Development
displayName: Publish development environment
dependsOn: build
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Development_websites
variableGroup: strata2-admin-spa-vg
- stage: Publish_Test
displayName: Publish test environment
dependsOn: Publish_Dev
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Test_websites
variableGroup: strata2-test-admin-spa-vg
- stage: Publish_Production
displayName: Publish production environment
dependsOn: Publish_Test
jobs:
- template: ${{parameters.publishTemplate}}
parameters:
environment: Production_websites
variableGroup: strata2-development-variables
You can create a stages object the same way you created the environments object.
stages:
Publish_Development:
- stage: Publish_Development
- displayName: Publish development environment
- dependsOn:
- ...
Publish_Test
- stage: Publish_Development
- ...
Then you can loop over the stages object like you did with environments.
- ${{each stage in parameters.stages}}:
- stage: ${{ stage.stage }}
displayName: ${{ stage.displayName}}
dependsOn: ${{ stage.dependsOn}}
...
Managed to get this working for myself. Stages automatically generated based on numerical batch numbers, that run in parallel. Hope it helps someone out there.
- name: batches
displayName: BATCH
type: object
default:
- 1
- 2
- 3
stages:
- ${{ each stage in parameters.batches }}:
- stage: BATCH_${{ stage }}
dependsOn: []
jobs:
- job: PREP
steps:
- template: install.yml
- job: RUN
dependsOn: PREP
timeoutInMinutes: 300
steps:
- template: run.yml
parameters:
batch: ${{ stage }}
Would be nice if the batch numbers weren't displayed as an editable box when running the pipeline from Azure DevOps. I tried setting them as fixed values, but couldn't get that to work, so this is what I went with in the end.

How to dynamically reference previous jobs in Azure Pipelines if there are any in the current stage

I am trying to set up an azure yaml pipeline that uses two deployment templates for two respective jobs (test and deploy). The jobs should be run in sequence for each stage, as the test-job creates an artifact that the deploy-job consumes. This works nicely.
However, for one environment I have split the deployment into two stages, one stage that only runs tests and one stage that runs the actual deployment. The problem I run into is that my deploy-job has a "dependson" which references the test-job. Because of this, my pipeline is invalid when I add the these two stages for my environment.
My question is if there is some sort of dynamic "dependson" reference for a job, something like "depends on any previous jobs in this stage, if there are any"?
Snippets of code from the yaml-files below for reference:
Main.yaml
#This first stage would work as it uses both templates in succession
stages:
- stage: BothTemplates
displayName: 'Run both templates'
jobs:
- template: TemplateTest.yml
- template: TemplateDeploy.yml #depends on the job in TemplateTest.yml
# The pipeline is invalid because of OnlyDeploy, as the TemplateDeploy.yml depends in the job "Test", which does not exist in the OnlyDeploy-context
- stage: OnlyTest
dependsOn: BothTemplates
displayName: 'Run only test template'
jobs:
- template: TemplateTest.yml
- stage: OnlyDeploy
dependsOn: OnlyTest
displayName: 'Run only deploy template'
jobs:
- template: TemplateDeploy.yml
TemplateTest.yaml
jobs:
- deployment: Test
dependsOn:
displayName: Test
continueOnError: false
strategy:
runOnce:
deploy:
steps:
#Here the steps for the tests are
Current TemplateDeploy.yaml
jobs:
- deployment: Deploy
dependsOn: Test
displayName: Deploy
continueOnError: false
strategy:
runOnce:
deploy:
steps:
#Here the steps for the deployment are
My idea would be to change TemplateDeploy.yaml to something like this:
jobs:
- deployment: Deploy
dependsOn: previousJob() #Wait until previous job in stage has finished, if there are any
displayName: Deploy
continueOnError: false
strategy:
runOnce:
deploy:
steps:
#Here the steps for the deployment are
Since you already have dependencies between stages
- stage: OnlyTest
dependsOn: BothTemplates
displayName: 'Run only test template'
jobs:
- template: TemplateTest.yml
- stage: OnlyDeploy
dependsOn: OnlyTest
displayName: 'Run only deploy template'
jobs:
- template: TemplateDeploy.yml
I think that you actually don't need here dependency to a job on TemplateDeploy.yml but if you want to make this dependent on previous jobs you can achieve this using parameters
parameters:
- name: makeExplicitDependency
displayName: 'Make excplicit job dependency'
type: boolean
default: true
jobs:
- deployment: Deploy
${{ if eq(parameters.makeExplicitDependency, true) }}:
dependsOn: Test
displayName: Deploy
continueOnError: false
strategy:
runOnce:
deploy:
steps:
#Here the steps for the deployment are
and then:
stages:
- stage: BothTemplates
displayName: 'Run both templates'
jobs:
- template: TemplateTest.yaml
- template: TemplateDeploy.yaml #depends on the job in TemplateTest.yml
- stage: OnlyTest
dependsOn: BothTemplates
displayName: 'Run only test template'
jobs:
- template: TemplateTest.yaml
- stage: OnlyDeploy
dependsOn: OnlyTest
displayName: 'Run only deploy template'
jobs:
- template: TemplateDeploy.yaml
parameters:
makeExplicitDependency: false
So removing dependsOn works like your expected dependsOn: previousJob() #Wait until previous job in stage has finished, if there are any

Azure DevOps pipelines stages

I got a setup where I want to trigger the CI to build on each pull request to our Bitbucket Cloud repository. In the same setup I also have three different stages that's I would like to trigger manually when we would like to build the artefact to deploy to our environments.
The problem I got is that the pull request trigger doesn't trigger after I added stages in our build. This is how the configuration looks like:
pr:
branches:
include:
- '*'
pool:
vmImage: 'macos-latest'
stages:
- stage: CI
displayName: 'Continues build'
jobs:
- job: C1
steps:
- template: azure-pipelines-ios.yml
parameters:
environment: 'ci'
- task: PublishBuildArtifacts#1
- stage: Test
displayName: 'Building for Test'
jobs:
- job: T1
steps:
- template: azure-pipelines-ios.yml
parameters:
environment: 'test'
- task: PublishBuildArtifacts#1
- stage: Stage
displayName: 'Building for Stage'
jobs:
- job: S1
steps:
- template: azure-pipelines-ios.yml
parameters:
environment: 'stage'
- task: PublishBuildArtifacts#1
I would like to trigger the CI stage build on each pull request. How do I do that?
If you want to skip other stages for you should use condition:
pr:
branches:
include:
- '*'
pool:
vmImage: 'macos-latest'
stages:
- stage: CI
displayName: 'Continues build'
condition: eq(variables['Build.Reason'], 'PullRequest')
jobs:
- job: C1
steps:
- script: echo "Hello $(System.StageName)"
- stage: Test
displayName: 'Building for Test'
condition: ne(variables['Build.Reason'], 'PullRequest')
jobs:
- job: T1
steps:
- script: echo "Hello $(System.StageName)"
- stage: Stage
displayName: 'Building for Stage'
condition: ne(variables['Build.Reason'], 'PullRequest')
jobs:
- job: S1
steps:
- script: echo "Hello $(System.StageName)"

Deselect Stages By Default

In Azure Devops multistage YAML pipeline we got multiple environments.
In stages to run normally we do a build and deploy only in QA, so we need to deselect each stage manually. By default all stages are selected is it possible to have exact opposite, where all stages are deselected by default???
trigger: none
pr: none
stages:
- stage: 'Build'
jobs:
- deployment: 'Build'
pool:
name: Default
# testing
environment: INT
strategy:
runOnce:
deploy:
steps:
- checkout: none
- powershell: |
echo "Hello Testing"
Start-Sleep -Seconds 10
- stage: 'Sandbox'
jobs:
- job: 'Sandbox'
pool:
name: Default
steps:
- checkout: none
# testing
- powershell: |
echo "Hello Testing"
- stage: 'Test'
jobs:
- job: 'DEV'
pool:
name: Default
steps:
- checkout: none
- powershell: |
echo "Hello Testing"
- stage: 'QA'
dependsOn: ['Test','Test1','Test2']
jobs:
- job: 'QA'
pool:
name: Default
steps:
- checkout: none
# Testing
- powershell: |
echo "Hello Testing"
I am afraid that there is no UI (like stage to run) method that can meet your needs.
You could try to add parameters to your Yaml Sample.
Here is an example:
trigger: none
pr: none
parameters:
- name: stageTest
displayName: Run Stage test
type: boolean
default: false
- name: stageBuild
displayName: Run Stage build
type: boolean
default: false
stages:
- ${{ if eq(parameters.stageBuild, true) }}:
- stage: 'Build'
jobs:
- deployment: 'Build'
pool:
name: Default
environment: INT
strategy:
runOnce:
deploy:
steps:
- checkout: none
- powershell: |
echo "Hello Testing"
Start-Sleep -Seconds 10
- ${{ if eq(parameters.stageTest, true) }}:
- stage: Test
dependsOn: []
jobs:
- job: B1
steps:
- script: echo "B1"
The parameters are used to determine whether to run these stages. You could add expressions before the stage to check if the parameter value could meet expression.
The default value is false. This means that the stage will not run by default.
Here is the result:
You can select the stage you need to run by clicking the selection box.
Update
Workaround has some limitations. When the select stage has depenencies, you need to select all dependent stages to run.
For example:
- stage: 'QA'
dependsOn: ['Test','Test1','Test2']
On the other hand, I have created a suggestion ticket to report this feature request. Here is the suggestion ticket link: Pipeline Deselect Stages By Default You could vote and add comment in it .
I've used this solution to build a nuget-package, and:
always push packages from master
conditionally push packages from other branches
Using GitVersion ensures that the packages from other branches get prerelease version numbers, e.g. 2.2.12-my-branch-name.3 or 2.2.12-PullRequest7803.4. The main branch simply gets 2.2.12, so the master branch is recognized as a "regular" version.
The reason I'm repeating the answer above, is that I chose to make the stage conditional instead of using an if:
trigger:
- master
parameters:
- name: pushPackage
displayName: Push the NuGet package
type: boolean
default: false
stages:
- stage: Build
jobs:
- job: DoBuild
steps:
- script: echo "I'm building a NuGet package (versioned with GitVersion)"
- stage: Push
condition: and(succeeded('build'), or(eq('${{ parameters.pushPackage }}', true), eq(variables['build.sourceBranch'], 'refs/heads/master')))
jobs:
- job: DoPush
steps:
- script: echo "I'm pushing the NuGet package"
Like the other answer, this results in a dialog:
But what's different from the (equally valid) solution with '${{ if }}', is that the stage is always shown (even if it's skipped):

conditional build based on branch for multi stage pipeline using different templates under stages

How to trigger by branch to use specific template under "stages"?
trigger:
branches
include:
- ci
- prod
stages:
template: ci.yml
condition: and(eq(['build.sourceBranch'], 'ci'))
template: prod.yml
condition: and(eq(['build.sourceBranch'], 'prod'))
Tried above condition but didn't work. I was getting "unexpected value condition". Any help is appreciated
***** Tried one of the solution as by passing condition as parameter to the template:
stages:
template: ci.yml
parameters:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/ci'))
template: prod.yml
parameters:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/prod'))
Getting "unexpected parameter condition"
Pipeline structure:
master.yml (contains runtime parameters)
stages:
template: ci.yml
parameters:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/ci'))
template: prod.yml
parameters:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/prod'))
ci.yml
stages:
stage: BuildApp
stage: BuildWeb
stage: DeployLocal
prod.yml
stages:
stage: BuildApp
stage: BuildWeb
stage: DeployProd
How to trigger by branch to use specific template under "stages"?
To resolve this issue, we could add the condition on the job level, like:
stages:
- stage: Test1
jobs:
- job: ci
displayName: ci
pool:
name: MyPrivateAgent
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/ci'))
steps:
- template: ci.yml
- job: prod
displayName: prod
pool:
name: MyPrivateAgent
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/prod'))
steps:
- template: prod.yml
Check the document Specify conditions for some more details.
On the other hand, we could also set the condition as parameter to the template yml, like:
- template: ci.yml
parameters:
doTheThing: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/ci'))
The template yml file:
# template.yml
parameters:
doTheThing: 'false'
steps:
- script: echo This always happens!
displayName: Always
- script: echo Sometimes this happens!
condition: ${{ parameters.doTheThing }}
displayName: Only if true
You could check the thread YAML - Support conditions for templates for some more details.
Hope this helps.