2 minute read

This post will cover an actual implementation sample code for the development workflow covered in the article “How Microsoft develops with DevOps”.

A little backstory about how this post came to be: the existing development/release workflow in Azure DevOps for our team came from a legacy code base where the workflow required multiple PR and merging to be done. Typically this would be: create a feature/* branch, PR and merge into development, PR and merge from development into test and then finally PR and merge from test into main for production deployment.

We found this workflow to be quite cumbersome since it requires extra redundant work to raise another PR request when we want to promote our deployments. After a bit of research and comparison, we saw the post from Microsoft and how it was suitable for our particular needs (minimal PR/merges and versioned release). What was lacking though was an actual sample implementation on the post, thus the reason for this post.

Azure DevOps Pipeline

name: demo pipeline

pool:
  name: 'Azure Pipelines'
  vmImage: ubuntu-latest

trigger:
  - '*'

stages:
  - stage: build
    dependsOn: []
    # we dont want PR stage to run for main and release
    condition: and(ne(variables['Build.SourceBranchName'], 'main'), not(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')))
    jobs:
    - template: templates/build-template.yaml
    ...

  - stage: dev
    condition : eq(variables['Build.SourceBranchName'], 'main')
    jobs:
    - template: templates/infra-template.yaml 
    ...

  - stage: test
    dependsOn: dev
    condition: succeeded('dev')
    jobs:
    - template: templates/infra-template.yaml
    ...

  - stage: prod
    dependsOn: [] # not dependent on any other stage
    condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')
    jobs:
    - template: templates/build-template.yaml
    ...

Note the use of

trigger:
    - '*'

This is due to the fact that Azure DevOps YAML pipeline does not support PR triggers when you use Azure Repos (which we do use). Therefore the work around is to trigger the pipeline every single time and use the condition field in the stage to decide if it should execute. link

Pipeline runs image

Single pipeline run for feature/* image You can see from the images above that for a single run in the feature/* branch, only the build stage executes while the other ones are skipped.

Now, when a feature/* branch is created and pushed to the repo, it will automatically trigger the build stage. This is where you can run your linting checks, tests and display the infrastructure changes if it’s an IaC repo. From there, a single PR into the main branch is all that is required for it to go into the dev and test environments. Once we are ready, we then create a release/* branch off main to deploy to prod environment.

Updated: