Use one Azure DevOps pipeline to run PR and main builds separately
Introduction
For simplicity I want to have one Azure DevOps CI pipeline to build both PR and main branch of my Java app.
Problem
PR build should focus on building code and running tests and not perform deploy step (publish artefact to a repo) - in other words those PR and main build steps have to be different and not interfer.
Solution
Use condition feature of pipelines and check the reason of the build:
- if reason is PR (
eq(variables['Build.Reason'], 'PullRequest')
) - PR task should be executed and main should be skipped - if reason is not PR (
ne(variables['Build.Reason'], 'PullRequest')
) - main task should be executed and PR should be skipped
Example
azure-pipelines.yml
---
jobs:
- job: Windows2019_with_Java11
pool:
vmImage: 'windows-2019'
steps:
- task: Maven@3
displayName: 'Build/Verify PR'
condition: eq(variables['Build.Reason'], 'PullRequest')
inputs:
mavenPomFile: 'pom.xml'
goals: 'verify'
jdkVersionOption: '1.11'
- task: Maven@3
displayName: 'Build/Deploy'
condition: ne(variables['Build.Reason'], 'PullRequest')
inputs:
mavenPomFile: 'pom.xml'
goals: 'verify'
jdkVersionOption: '1.11'
- task: PublishTestResults@2
displayName: 'Publish Test Results **\TEST-*.xml'
inputs:
mergeTestResults: true
Great. It works!
Is there a way to eliminate dublication?
Yes - using templates feature of pipelines.
- Create steps.yml template file
- Extract build taks into template
- Parametrize template
- Replace tasks in azure-pipelines.yml with template
Example
steps.yml
---
parameters:
mavenTaskName: ''
mavenTaskGoals: ''
mavenTaskCondition: ''
steps:
- task: Maven@3
displayName: $
condition: $
inputs:
mavenPomFile: 'pom.xml'
goals: $
jdkVersionOption: '1.11'
azure-pipelines.yml
---
jobs:
- job: Windows2019_with_Java11
pool:
vmImage: 'windows-2019'
steps:
- template: steps.yml
parameters:
mavenTaskName: 'Build/Verify PR'
mavenTaskGoals: 'verify'
mavenTaskCondition: eq(variables['Build.Reason'], 'PullRequest')
- template: steps.yml
parameters:
mavenTaskName: 'Build/Deploy'
mavenTaskGoals: 'deploy'
mavenTaskCondition: ne(variables['Build.Reason'], 'PullRequest')
- task: PublishTestResults@2
displayName: 'Publish Test Results **\TEST-*.xml'
inputs:
mergeTestResults: true
That’s it.
Conclusion
- Keeping all steps in one pipeline config file (vs having multiple yml configs for different needs) should simplify maintenance.
- In case the steps for PR and main builds are significantly different the template can become too complex so having two separate pipeleines might be a better option.
- The approach descibed above is not the only or the best option - it is just an option.