Custom commit message tags to control your CI build on Azure DevOps

Having an extensive CI build for your pull requests on Azure DevOps can be a great way to guard the quality of your codebase. Compile errors, style errors and regression can all be caught before they reach the main code branch. However, running your full set of automated checks every time can cause unwanted delays in your development process. Using commit message tags can be a great way to avoid this problem.

A real world example

Firstly, I will show an example of how I am personally using this in my current project. Our pull request CI build includes the following tasks:

  • Build all backend projects
  • Run unit tests
  • Run unit-integration tests
  • Build frontend project

From this selection, the last two tasks take the longest time. However, not every backend project contains unit-integration tests and the front-end is often untouched in pull requests. This is why we have introduced the commit tags [skip-it] and [skip-fe] to skip the unit-integration tests and the frontend build respectively. This has majorly decreased the time we have to wait for the CI build of pull requests that do not contain front-end changes or changes to backend projects without unit-integration tests.

Set build variables based on custom commit tags

We use our custom commit tags simply by retrieving the latest commit message and checking if it contains any of our tags. This can be done by using the Azure DevOps Services REST API. Personally I used Powershell to create the script for these actions. Powershell is included with all the build agents, cross-platform and very flexible, I definitely recommend it for these types of scripts.

- powershell: | 
   $baseUrl = "$(env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$($env:SYSTEM_TEAMPROJECTID)/_apis/git/repositories/$($env:BUILD_REPOSITORY_ID)"
   $headers = @{ Authorization = "Bearer $($env:SYSTEM_ACCESSTOKEN)" }
   
   $url = "$($baseUrl)/pullrequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)?api-version=5.1"
   $pr = Invoke-RestMethod -Uri $url -Headers $headers
   
   $url = "$($baseUrl)/commits/$($pr.lastMergeSourceCommit.commitId)?api-version=5.1"
   $commit = Invoke-RestMethod -Uri $url -Headers $headers
   
   if ($commit.comment.ToLowerInvariant().Contains("[skip-it]")) {
     Write-Host "##vso[task.setvariable variable=skip_it]true"
   } else {
     Write-Host "##vso[task.setvariable variable=skip_it]false"
   }
  displayName: Process custom commit tags

We query the Azure DevOps Services twice; first to retrieve the details of the current pull request, and then to query the last commit to the pull request’s branch. We use the pull request data to retrieve the last commit ID and the commit data to retrieve the commit message. If the commit message contains our tag [skip-it] we create a build variable named skip_it with the value true.

Using build variables to skip a build task

Build tasks can have a condition to determine if they should run or not. This is done by adding the condition property.

- task: DotNetCoreCLI@2
  condition: and(succeeded(), ne(variables.skip_it, true))
  displayName: 'Run integration tests'
  inputs:
    command: test
    projects: '**/*IntegrationTests.csproj'

In this example the condition expression uses ne which means “not equal”. With this condition the task will only run if the build variable skip_it does not equal the value true. So now we just have to add [skip-it] to our commit message when we push to the pull request and it will skip the integration tests.

Posted by Pikedev

Geef een antwoord