skip to Main Content

I have three level nested Azure DevOps yaml templates. In my second level nested template I want to conditionally call the third level template based on the target branch for pull request.

For e.g. level3@templates should only be called if pull request target branch is Main.

I know System.PullRequestTargetBranch is not available in templates. I am also familiar with

https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#runtime-expression-syntax

and limitations pre-defined variables have with nested templates

https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#system-variables-devops-services

I am hoping someone will be able to suggest some workaround for getting around this problem.

Will appreciate all the help.

My yaml is structured as below

main.yaml

resources:
  repositories:
    - repository: templates
      type: git
      name: MyProj/templates
      ref: refs/heads/main

extends:  
  template: extends/level1.yaml@templates
  parameters:     
    MY_STAGES:
      BUILD:
        displayName: "Build"
      L1Config:
          config1: "config1"

Level1.yaml

parameters:
  - name: MY_STAGES
    type: object
    default: {}
  - name: L1Config
    type: object
    default: {}
  
    
variables:  
  - name: var1
    value: "value1"
  - name: var2    
    value: "val2"

stages:
  - ${{ each MY_STAGE in parameters.MY_STAGES }}:
      - stage: ${{ MY_STAGE.key }}
        displayName: "Build"        
        jobs:
          - job: build_dev
            displayName: Build
            steps:
              - template: /jobs/level2@templates
                parameters:
                  L2Config: ${{ MY_STAGE.value.L1Config }}        

level2.yaml

parameters:
  - name: L2Config
    type: object
    default: {}
        
steps:
  - pwsh: Write-Host "Hello World!"   
  
  # This is the template I want to call conditionally, based on the PullRequest Target
  - ${{ if eq(variable['System.PullRequest.TargetBranch'], 'refs/heads/main') }}: 
    # I know above syntax does not work, I have just written it down as an example of what I wish had worked. 
    - template: /steps/level3@templates
      parameters:
        param1: value1

2

Answers


  1. Chosen as BEST ANSWER

    The System.PullRequestBranch information can be used in Task Conditions. So in effort to keep things simple, I have moved the check for PR Target branch to the task condition of task which needed this information.


  2. As you said, System.PullRequest.TargetBranch & System.PullRequest.SourceBranch cannot be expanded at compile time.

    There is no out-of-the-box method can fully meet your requirement. The If expression can not get the correct value of the Pull Request Branch.

    You can refer to the following method:

    You can split the Pipeline into two Pipelines. The first Pipeline will be used to get the System.PullRequest.TargetBranch and then use Powershell script to pass the value to the parameter value in the Second Pipeline.

    Here is an example:

    First Pipeline:

    pool:
      vmImage: windows-latest
    
    
    
    steps:
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
          $token = "$(pat)"      
          $url="https://dev.azure.com/{Orgname}/{Projectname}/_apis/pipelines/{PipelineRunID}/runs?api-version=5.1-preview"
          
          $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
          
          $JSON = "
          {
            
          
          
            `"resources`": {
              `"repositories`": {
                `"self`": {
                  `"ref`": `"refs/heads/main`"
                }
              }
            },
            `"templateParameters`": {
              `"PullRequestref`":`"$(System.PullRequest.TargetBranch)`"
             },
          
          
          
          }"
          
          
          $response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
    

    Second Pipeline:

    Main

    resources:
      repositories:
        - repository: templates
          type: git
          name: MyProj/templates
          ref: refs/heads/main
    parameters:
      - name: PullRequestref
        type: string
        default: refs/heads/test
    extends:  
      template: extends/level1.yaml@templates
      parameters:     
        MY_STAGES:
          BUILD:
            displayName: "Build"
          L1Config:
              config1: "config1"
    

    Level2:

    parameters:
      - name: L2Config
        type: object
        default: {}
            
    steps:
      - pwsh: Write-Host "Hello World!"   
      
    
      - ${{ if eq(parameters.PullRequestref, 'refs/heads/main') }}: 
        
        - template: /steps/level3@templates
          parameters:
            param1: value1
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search