Azure DevOps Pipeline Task: PR title validation

2 minute read

Introduction

When we think about bringing new developers into our project, it is likely that they will work with different guidelines than they have before. Sometimes the sheer amount of guidelines is simply too much to follow correctly after days, weeks or even months. Especially if you are not working entirely on the new project, but rather as a stand-in, meaning it could be weeks or months without working on this particular project, giving you a much harder time to keep-up with the specific guidelines.

One of the guidelines can be a prefix of the commit message by the project ticket number. This might not be that relevant if the pull request forces you to merge by squash commit. In my last post I showed an example to validate the commit message. However, since that is done locally there is always the possibility that some Devs might just turn the Git hooks off. That’s why we’d like to enforce rules centralized, and what better way than to automate this?

Getting started

Let’s say we are forced to merge our pull requests via squash commit. This is already an enforced rule (“policy” in the likes of Azure DevOps) in the repository, usually applied to certain branches and tags.

Unfortunately there is no predefined variable for the pull request title in Azure DevOps yet. So we have to call the Azure DevOps API, get all the metadata of the specific pull request and essentially the title of the pull request, which we then validate by the defined Regex pattern, in this case: [OTTER-xxxxxx] while x stands for a number between 0 and 9. Also notice the whitespace after ].

Azure DevOps Pipeline Task

- task: PowerShell@2
  displayName: 'Validate PR title'
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)
    REGEX_VALIDATION: (\[OTTER\-[0-9]{1,6}\] \w+)
  inputs:
    failOnStdErr: true
    targetType: 'inline'
    script: |
      $url = "$($env:SYSTEM_COLLECTIONURI)_apis/git/repositories/$($env:BUILD_REPOSITORY_ID)/pullRequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)?api-version=4.0"

      if(![string]::IsNullOrEmpty($env:SYSTEM_PULLREQUEST_PULLREQUESTID)) {
        $pipeline = Invoke-RestMethod -Uri $url -Headers @{
          "Authorization"="Bearer $($env:SYSTEM_ACCESSTOKEN)"
        } -OutFile output.json

        $Content = Get-Content output.json -Encoding UTF8
        $jsonObj = $Content | ConvertFrom-Json
        $pr_title = $jsonObj.title

        $Regex = $env:REGEX_VALIDATION
        if ($pr_title -match $Regex) {
          Write-Host "The title of the pull request is valid."
        } else {
          Throw "Error: Invalid pull request title! Please prefix with a valid project ticket number."
        }
      }

The script isn’t optimized. There is an error while reading the json content from the http response. This is why I opted in for the quick workaround, saving the content in a file and reading it again. The error handling can be improved. Also the task needs to be executed only if there is an actual PR, otherwise this script doesn’t make sense which is why I just let it pass. (Maybe I update this script in the future).

Conclusion

These automations guide us through the various guidelines of each project/repository without having to read a lot of documentation and also help the teams managing the project to enforce their policies.

The developers get immediate feedback on their pull requests, which leads to fewer delays and more productivity. Now it’s your turn. Get creative and create your own tasks to enforce your rules.

Hope you learned something new.

See you around 🦦