Home
%3CLINGO-SUB%20id%3D%22lingo-sub-393986%22%20slang%3D%22en-US%22%3EHow%20to%20Use%20Azure%20Pipeline%20Task%20and%20Job%20Conditions%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-393986%22%20slang%3D%22en-US%22%3E%3CP%3EAn%20Azure%20Pipeline%20task%20is%20a%20single%20task%20to%20be%20performed%20in%20an%20Azure%20Pipeline.%20An%20Azure%20Pipeline%20Job%20is%20a%20grouping%20of%20tasks%20that%20run%20sequentially%20on%20the%20same%20target.%20In%20many%20cases%2C%20you%20will%20want%20to%20only%20execute%20a%20task%20or%20a%20job%20if%20a%20specific%20condition%20has%20been%20met.%20Azure%20Pipeline%20conditions%20allow%20us%20to%20define%20conditions%20under%20which%20a%20task%20or%20job%20will%20execute.%20For%20more%20information%20on%20Azure%20Pipeline%20conditions%2C%20see%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fpipelines%2Fprocess%2Fconditions%3FWT.mc_id%3DITOpsTalk-blog-nepeters%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%22%3EAzure%20Pipeline%20Conditions%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20this%20blog%2C%20I%20will%20detail%20a%20common%20situation%20in%20which%20pipeline%20conditions%20are%20helpful%2C%20the%20configuration%20of%20this%20condition%2C%20and%20will%20include%20documentation%20links%20for%20more%20information.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22commonusecasepullrequestvalidation%22%20id%3D%22toc-hId-1702889954%22%20id%3D%22toc-hId-1702889954%22%3ECommon%20Use%20Case%3A%20Pull%20Request%20Validation%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EI've%20been%20working%20with%20an%20Azure%20Build%20Pipeline%20that%20first%20tests%20several%20pieces%20of%20Python%20code%2C%20publishes%20the%20test%20results%20to%20the%20pipeline%2C%20and%20then%20packages%20up%20a%20Helm%20chart%20and%20three%20container%20images.%20These%20artifacts%20are%20then%20pushed%20to%20Azure%20Container%20Registry.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20627px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101611iC8D01D8E7CA807A9%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22pipeline.jpg%22%20title%3D%22pipeline.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EOn%20this%20pipeline%2C%20I%20have%20configured%20a%20trigger%20so%20that%20the%20Pipeline%20is%20run%20both%20when%20code%20is%20committed%20to%20the%20master%20branch%20of%20the%20associated%20repository%20%3CSTRONG%3EAND%3C%2FSTRONG%3E%20when%20a%20pull%20request%20is%20made%20against%20the%20master%20branch%20of%20the%20repository.%20This%20is%20cool%20because%20the%20pipeline%20will%20now%20run%20all%20unit%20tests%20when%20a%20pull%20request%20is%20created%2C%20and%20provide%20test%20results%20for%20review%20prior%20to%20merging%20the%20pull%20request.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101612i9D2148171CC34523%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22pr-validation.jpg%22%20title%3D%22pr-validation.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThings%20look%20good%2C%20however%2C%20I%20found%20that%20when%20a%20pull%20request%20is%20made%2C%20%3CSTRONG%3Enot%20only%3C%2FSTRONG%3E%20are%20the%20tests%20running%2C%20but%20the%20artifacts%20are%20built%20and%20pushed%20to%20the%20Azure%20Container%20Registry.%20This%20is%20not%20what%20I%20want%20to%20occur.%20I%20want%20the%20artifact%20jobs%20to%20%3CSTRONG%3Eonly%20run%3C%2FSTRONG%3E%20once%20a%20pull%20request%20has%20been%20merged%20to%20master.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EDigging%20into%20execution%20conditions%20for%20my%20artifact%20jobs%2C%20I%20found%20that%20the%20default%20condition%20is%2C%3CCODE%3EOnly%20when%20all%20previous%20jobs%20have%20succeeded%3C%2FCODE%3E%20which%20seems%20to%20be%20the%20culprit%20here.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20983px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101616iEC91B0147FE02D1D%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22default.jpg%22%20title%3D%22default.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ERather%20than%20executing%20when%20all%20previous%20jobs%20were%20successful%2C%20I%20want%20to%20only%20execute%20the%20artifact%20jobs%20when%20the%20previous%20jobs%20were%20successful%20%3CSTRONG%3Eand%3C%2FSTRONG%3E%20the%20trigger%20was%20not%20a%20pull%20request.%20For%20this%20configuration%2C%20we%20can%20use%20custom%20conditions.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22taskandjobconditions%22%20id%3D%22toc-hId--849267007%22%20id%3D%22toc-hId--849267007%22%3ETask%20and%20Job%20Conditions%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ETask%20and%20job%20conditions%20allow%20us%20to%20build%20custom%20and%20if%20needed%20complex%20conditions%20under%20which%20a%20task%20or%20job%20will%20run.%20Conditions%20are%20built%20using%20a%20series%20of%20pipeline%20expressions.%20Details%20on%20expression%20capability%20and%20syntax%20can%20be%20found%20at%20the%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdevops%2Fpipelines%2Fprocess%2Fexpressions%3FWT.mc_id%3DITOpsTalk-blog-nepeters%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%22%3EExpression%20documentation%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAfter%20some%20experimentation%2C%20I%20found%20that%20I%20can%20change%20the%20condition%20from%20%3CCODE%3EOnly%20when%20all%20previous%20jobs%20have%20succeeded%3C%2FCODE%3E%2C%20to%26nbsp%3B%3CCODE%3ECustom%20condition%20using%20variable%20expressions%3C%2FCODE%3E%2C%20and%20then%20provide%20the%20following%20condition%20to%20meet%20my%20expected%20result.%20This%20condition%20will%20trigger%20when%20the%20dependant%20jobs%20were%20successful%20%3CSTRONG%3Eand%3C%2FSTRONG%3E%20the%20build%20reason%20is%20not%20equal%20to%20a%20pull%20request.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3E%3CCODE%3Eand(succeeded()%2C%20ne(variables%5B'Build.Reason'%5D%2C%20'PullRequest'))%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20what%20the%20condition%20looks%20like%20in%20my%20build%20pipeline.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20978px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101617iAD6A99001CA2C6EF%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22condition.jpg%22%20title%3D%22condition.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIf%20using%20a%20YAML%20based%20pipeline%2C%20the%20configuration%20would%20look%20similar%20to%20this.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%3E%3CCODE%3E-%20job%3A%20Build%20Artifacts%0A%20%20dependsOn%3A%20Run%20Tests%0A%20%20condition%3A%20and(succeeded()%2C%20ne(variables%5B'Build.Reason'%5D%2C%20'PullRequest'))%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThis%20is%20just%20one%20simple%20example.%20Using%20the%20expression%26nbsp%3Blanguage%20you%20should%20be%20able%20to%20finely%26nbsp%3Bcontrol%26nbsp%3Bthe%20execution%20behavior%20of%20you%20Azure%20build%20and%20release%20pipelines.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFeel%20free%20to%20reach%20out%20in%20comments%20or%20on%20Twitter%20at%20%3CA%20href%3D%22https%3A%2F%2Ftwitter.com%2Fnepeters%22%20target%3D%22_self%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3E%40nepeters%3C%2FA%3E.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-393986%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20style%3D%22width%3A%20978px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101618iA8134299B4EA2D2C%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20alt%3D%22condition.jpg%22%20title%3D%22condition.jpg%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%3CSPAN%3EAzure%20Pipeline%20conditions%20allow%20us%20to%20define%20conditions%20under%20which%20a%20task%20or%20job%20will%20execute.%20In%20this%20blog%20post%2C%20I%20will%20detail%20a%20common%20situation%20in%20which%20pipeline%20conditions%20are%20helpful%2C%20the%20configuration%20of%20this%20condition%2C%20and%20will%20include%20documentation%20links%20for%20more%20information.%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-393986%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20DevOps%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ENeil%20Peterson%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft

An Azure Pipeline task is a single task to be performed in an Azure Pipeline. An Azure Pipeline Job is a grouping of tasks that run sequentially on the same target. In many cases, you will want to only execute a task or a job if a specific condition has been met. Azure Pipeline conditions allow us to define conditions under which a task or job will execute. For more information on Azure Pipeline conditions, see Azure Pipeline Conditions.

 

In this blog, I will detail a common situation in which pipeline conditions are helpful, the configuration of this condition, and will include documentation links for more information.

 

Common Use Case: Pull Request Validation

 

I've been working with an Azure Build Pipeline that first tests several pieces of Python code, publishes the test results to the pipeline, and then packages up a Helm chart and three container images. These artifacts are then pushed to Azure Container Registry.

 

 

pipeline.jpg

 

On this pipeline, I have configured a trigger so that the Pipeline is run both when code is committed to the master branch of the associated repository AND when a pull request is made against the master branch of the repository. This is cool because the pipeline will now run all unit tests when a pull request is created, and provide test results for review prior to merging the pull request.

 

pr-validation.jpg

 

Things look good, however, I found that when a pull request is made, not only are the tests running, but the artifacts are built and pushed to the Azure Container Registry. This is not what I want to occur. I want the artifact jobs to only run once a pull request has been merged to master.

 

Digging into execution conditions for my artifact jobs, I found that the default condition is,Only when all previous jobs have succeeded which seems to be the culprit here.

 

default.jpg

 

Rather than executing when all previous jobs were successful, I want to only execute the artifact jobs when the previous jobs were successful and the trigger was not a pull request. For this configuration, we can use custom conditions.

 

Task and Job Conditions

 

Task and job conditions allow us to build custom and if needed complex conditions under which a task or job will run. Conditions are built using a series of pipeline expressions. Details on expression capability and syntax can be found at the Expression documentation.

 

After some experimentation, I found that I can change the condition from Only when all previous jobs have succeeded, to Custom condition using variable expressions, and then provide the following condition to meet my expected result. This condition will trigger when the dependant jobs were successful and the build reason is not equal to a pull request.

 

and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))

 

Here is what the condition looks like in my build pipeline.

 

condition.jpg

 

If using a YAML based pipeline, the configuration would look similar to this.

 

- job: Build Artifacts
  dependsOn: Run Tests
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))

 

This is just one simple example. Using the expression language you should be able to finely control the execution behavior of you Azure build and release pipelines.

 

Feel free to reach out in comments or on Twitter at @nepeters.