Thomas
Thomas

Reputation: 1831

Azure DevOps Pipeline structure for PRs in mono-repo

I have a mono-repo containing multiple sub-projects (Node/TypeScript if it matters). I'm trying to set up what I feel is a relatively simple pull request setup in Azure DevOps that is meant to deploy a PR environment for testing. It consists of 2 pipelines that I want to trigger one after the other in the PR. If either fail the PR should fail as well. The code is hosted in Azure DevOps Git.

Here are the steps I'm trying to achieve:

  1. PR is created with tag solution-a for merging from features/feature-x to dev branch
  2. Branch policy triggers the solution-a-pipeline based on the tag solution-a. A different pipeline should be triggered if the tag is different.
  3. solution-a-pipeline triggers infrastructure-pipeline and solution-a-build-pipeline in context of features/feature-x branch* in order.
  4. If solution-a-pipeline completes successfully (indirectly this means infrastructure-pipeline and solution-a-build-pipeline also completed successfully in order) the bulid is considered successful. Otherwise it fails and the PR cannot be completed.

*By "in context" I mean that the actual yaml file used for each pipeline is the one from the feature branch. This is because I want it to test any changes to the pipelines as well as any steps within the pipeline.

Is there a way to achieve this? I've been trying for days now using different combinations of pipeline files, templates, resources and triggers and I cannot seem to wrap my head around it.

Upvotes: 1

Views: 1484

Answers (2)

Thomas
Thomas

Reputation: 1831

I've managed to work around the problem. It involves several steps and some hard-coding, but I'm now able to tag a Pull Request with certain defined tags and have a Build Validation triggered pipeline run only the relevant parts as a result.

My setup consists of one big pr-pipeline.yml file that is triggered by the Build Validation of PRs to my dev branch. The trigger is manual, but required which allows the person issuing the PR to tag it accordingly before it begins.

Once the pipeline runs the very first step uses the Azure DevOps REST API to determine which tags are present on the associated PR by calling this endpoint:

https://dev.azure.com/$(organizationName)/$(System.TeamProjectId)/_apis/git/repositories/$(Build.Repository.ID)/pullRequests/$(System.PullRequest.PullRequestId)/labels?api-version=5.1-preview.1

Every parameter required except the organization name is provided by the predefined variables for the pipeline.

To call the endpoint I'm using the Personal Access Token (PAT) provided to the agent by Azure DevOps in the predefined variable System.AccessToken and a small PowerShell script:

$accessToken = "$(System.AccessToken)"
$basicAuth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$accessToken"))
$headers = @{Authorization = "Basic $basicAuth"}
$url = $(url)
$data = Invoke-WebRequest -Method Get -Uri $url -Headers $headers
Write-Host "##vso[task.setvariable variable=prlabels]$data"

Once I have my tags I extract each of them as a separate variable using a small PowerShell snippet. The prlabels variable is populated by :

$tagsJson = '$(prlabels)' | ConvertFrom-Json
$tags = $tagsJson.value | ForEach-Object { $_.name }
Write-Host "Tags: $($tags -join ";")"
$tags | ForEach-Object { Write-Host "##vso[task.setvariable variable=prlabel_$_;isOutput=true]true" }

If my pr is tagged with solution-a and solution-c this will result in the following output variables being defined:

prlabel_solution-a = true
prlabel_solution-c = true

Finally, I can use those output variables as conditions for triggering the relevant jobs that perform the actual build and deployments for the respective solutions. The job that fetches the tags is named PreReq and the task that outputs individual variables is named prlabels:

- job: DeploySolutionA
  dependsOn: PreReq
  condition: and(succeeded(), eq(dependencies.PreReq.outputs['prlabels.prlabel_solution-a'], 'true'))
  # ...

All of this together enables me to deploy one or more specific solutions in a PR based on what the user defines. It still requires the user to know of these labels, but at least they don't have to manually start each pipeline on each run outside of the PR.

Upvotes: 2

Leo Liu
Leo Liu

Reputation: 76890

Azure DevOps Pipeline structure for PRs in mono-repo

I could understand your requests, but AFAI for Azure devops, I do not believe there is such a way to achieve your needs at this moment.

There are three challenges here:

  1. We could not add a tag to a Pull Request, you could check this thread for details.

  2. We could not trigger different build pipeline based on the tags. There is no such condition for the option build validation.

  3. We could not set the order of the build validation. We could set multiple build pipeline in the build validation, but we could not set the order of them. If we add a build validation and use build completion to set the build order, but build validation will only verify the results of the build pipeline we added, not the results of other associated pipelines

In summary, I do not believe there is such a way to achieve your needs at this moment.

Hope this helps.

Upvotes: 0

Related Questions