accessing resources.repositories in Azure Devops yaml pipeline template

71 Views Asked by At

In our codebase there are two commonly used resource repository aliases used for the template repository.

Short version: Is it possible to somehow access the alias in use via the resources.repositories object within the template?

I want to be able to do a conditional checkout and call another template using the already declared resource alias, without having to change a bunch of the calling pipelines to set in parameters.

Details: The first if in the yaml template below refers to the resources.repository object and results in this error when I trigger the pipeline manually:/debug.yml@commonTemplates (Line: 11, Col: 3): Unrecognized value: 'resources'. Located at position 24 within expression: contains(convertToJson(resources.repositories),'commonTemplates').

This is the template:

parameters:

- name: templateResourceAlias
  type: string
  default: "commonTemplates"

steps:
- checkout: self

- ${{ if contains(convertToJson(resources.repositories),'commonTemplates') }}:
  - checkout: commonTemplates
- ${{ if eq(parameters.templateResourceAlias,'commonTemplates') }}:
  - checkout: commonTemplates

- pwsh: |
    echo '$[ resources.repositories['self'].name ]'
    echo '$(repos)'

ConvertToJson does give a valid value in the calling pipeline, below, when setting a variable but references to resources.repositories or specific properties like resources.repositories['self'].name in the template has just given errors. (Name doesn't actually help, that gives the repo name not the alias. I can't see a property to get the alias, hence the attempt to find it in a json string.)

I did try sending the json from the calling pipeline and do the contains in the template but the checkout never happened. I wondered if that was because of the newlines so I did try replacing them with something else using split and join consecutively, but that didn't seem to make a difference. resources.repositories.keys didn't get me anywhere either.

This is the results of the convertToJson.

{
  "self": {
    "id": "2b3f919f-dad0-4db6-8ea5-1b3dad1170b7",
    "name": "experiments",
    "ref": "refs/heads/main",
    "type": "Git",
    "url": "https://project.visualstudio.com/experiments/_git/experiments",
    "version": "0bc22a6c6bf1fe394caea5d837cd6b2f95789f4a"
  },
  "commonTemplates": {
    "id": "ac1749c6-f8e0-4188-a7de-3a1ae5928cfe",
    "name": "Templates",
    "ref": "refs/heads/main",
    "type": "git",
    "url": "https://project.visualstudio.com/Templates/_git/Templates",
    "version": "b0011c9e6cd6013c0dc4d4731f10720ca4834094"
  }
}

I could imagine that this might possibly work if the template could be at a stage or jobs level so we could add local variables but our existing structure limits me to having steps and not extended templates.

For the sake of completeness, and by request, here is the calling pipeline I have been labbing with.

trigger: none

name: $(Build.DefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)

pool:
  vmImage: ubuntu-latest

resources:  
  repositories:  
  - repository: commonTemplates  
    type: git  
    name: Templates/Templates 

jobs:
  - job: BuildAndValidate
    displayName: Build and Validate
    variables:
      tools.ref: $[ resources.repositories['commonTemplates'].ref ]
      repos: $[ convertToJson(resources.repositories) ]
      ct:  $[ convertToJson( resources.repositories.commonTemplates) ]
      tt:  $[ convertToJson( resources.repositories.teamTemplates) ]
      exists: $[ contains( convertToJson( resources.repositories), 'commonTemplates') ]

    pool:
      vmImage: 'ubuntu-latest'

    steps:
      - template: debug.yml@commonTemplates


There are a lot of variables that I was experimenting with, and one can see in the logs that these get filled in as one would expect, but I want to avoid having to update all the calling pipelines. Then we might as well change all the repository resource declarations to a consistent alias.

I know that in this case, I could refer to the checked out repository to get the other template blocks I want to call, but I have another pipeline that also calls the template blocks that doesn't checkout the repository and will need the alias.

1

There are 1 best solutions below

1
Bright Ran-MSFT On

You can update like as below in the template YAML file debug.yml.

# debug.yml

. . .

steps:
- checkout: self
- checkout: commonTemplates
  condition: contains(variables.resRepos,'commonTemplates')

. . .
# azure-pipelines.yml

. . .

resources:  
  repositories:  
  - repository: commonTemplates  
    type: git  
    name: Templates/Templates

variables:
  resRepos: $[ convertToJson(resources.repositories) ]
  . . .

jobs:
  - job: BuildAndValidate
    . . .
    steps:
      - template: debug.yml@commonTemplates