Automated creation of GIT Pull Requests through Azure DevOps Build pipelines

Often, development teams based on typical branching models need to perform routine mergers of changes from the general integration branch (master) to their team branches to obtain changes from other teams and understand their impact on current work. It is better to do this more often to know about possible problems earlier. Team can do this manually, but it is often ignored. Additionally, we can automate this step with Rest API calls through PowerShell. It is enough to create one pull request (PR), and it will be periodically updated with new changes each time as new commit is added to the master branch. You can create PR through Azure DevOps build pipeline in several ways:

  1. Periodically with the build schedule.
  2. Based on continuous integration, where each new commit into the master branch creates PR into the team development branch.

To create a schedule-based build definition, perform the following steps:

  • Check that the build user has access to create PRs through the Contribute to pull requests permission.

Figure 1. Permission to work with PRs

  • Create a new build definition. In my case, through the classic editor.

Figure 2. Go to the classic editor

  • Specify the repository and branch as target to create PR from master.

Figure 3. The Repository and branch name

  • Select the empty set of steps.

Figure 4. The build definition without steps

  • Specify that you do not need to download source code. This option allows you to use the build pipeline as a task scheduler.

Figure 5. Skip download of source code

  • Allow build jobs to obtain a personal access token (PAT).

Figure 6. Option to get PAT

  • Specify the required time frame for the build definition.

Figure 7. The build definition schedule

  • Add only one PowerShell step with the Inline execution.

Figure 8. The PowerShell step

The script will perform the following steps:

  • Specify required parameters from predefined build pipeline variables (PAT, organization url, project name, repository name, and branch for PR). The source of the changes will be the master branch.

$token = $(System.AccessToken)

$branchTarget = $(Build.SourceBranch)

$branchSource = “refs/heads/master”

$branchTragetPath = $branchTarget -replace “refs/heads/”, “”

$teamProject = $(System.TeamProject)

$repoName = $(Build.Repository.Name)

$orgUrl = $(System.CollectionUri)

  • Checks whether there are new commits in the master branch through the Stats – Get method, the result of which contains the behindCount property.

$uriBranchStatus = $orgUrl/$teamProject/_apis/git/repositories/$repoName/stats/branches?name=$branchTragetPath&api-version=5.1″

resultStatus = Invoke-RestMethod -Uri $uriBranchStatus -Method Get -ContentType “application/json” -Headers @{Authorization=(“Basic {0}” -f $base64AuthInfo)}

if ($resultStatus.behindCount -eq 0)

{

    Write-Host “Current branch contains last changes from master”

    Return

}

  • Checks whether there is an active PR through the Pull Requests – Get Pull Requests method. The method returns an array of PRs that match a search criteria. If the array is empty, there are no PRs.

$uriCheckActivePR = $orgUrl/$teamProject/_apis/git/repositories/$repoName/pullrequests?searchCriteria.targetRefName=$branchTarget&searchCriteria.sourceRefName=$branchSource&api-version=5.1″

$resultActivePR = Invoke-RestMethod -Uri $uriCheckActivePR -Method Get -ContentType “application/json” -Headers @{Authorization=(“Basic {0}” -f $base64AuthInfo)}

if ($resultActivePR.count -gt 0)

{

    Write-Host “PR exists already”

    Return

}

  • Create PR through the Pull Requests – Create method, its body includes information about the source and target of PR.

$uriCreatePR = $orgUrl/$teamProject/_apis/git/repositories/$repoName/pullrequests?api-version=5.1″

$bodyCreatePR = “{sourceRefName:’$branchSource‘,targetRefName:’$branchTarget‘,title:’Sync changes from $branchSource‘}”

$result = Invoke-RestMethod -Uri $uriCreatePR -Method Post -ContentType “application/json” -Headers @{Authorization=(“Basic {0}” -f $base64AuthInfo)} -Body $bodyCreatePR

Write-Host “Created PR” $result.pullRequestId

The resulting step in the build definition:

Рисунок 9. The script in the build definition

The contents of the script is here: https://github.com/ashamrai/AzureDevOpsExtensions/blob/master/CustomPSTasks/CreatePRBuildTask.ps1