How would i make this yaml template reusable?

I currently have a template for a build step that I want to use in multiple templates.

tag.yaml:

jobs:
- job: Tag
  displayName: 'Tag'
  dependsOn:
    - UnitTests
    - BuildMyContainers
    - HelmPackage
    - Prebuild
  condition: |
    and
    (
      eq(dependencies.UnitTests.result, 'Succeeded'),
      eq(dependencies.BuildMyContainers.result, 'Succeeded'),
      eq(dependencies.HelmPackage.result, 'Succeeded')
    )

  - task: Bash@3
    displayName: tag
    inputs:
      targetType: 'inline'
      script: |
        tag="$(RELEASE-NUMBER)"

I use this in my main template file

main.yaml

jobs:
- template: prebuild.yaml
- template: docker-publish.yaml
- template: dotnet-test.yaml
- template: helm.yaml
- template: tag.yaml

I now want to try and use this tag.yaml in another template

main2.yaml

jobs:
- template: prebuild.yaml
- template: docker-publish.yaml
- template: dotnet-test.yaml
- template: fortify.yaml
- template: sonar.yaml
- template: tag.yaml

As you can see in main2 I have different build steps so I need to update the dependsOn and conditions for tag.yaml based on the template it is being used in. I know I can pass in the dependsOn parameters via the main templates, but I am not able to pass in the conditions. How would I approach this? Do I just need to create a version of tag.yaml and maintain two?

Compare your main.yaml and main2.yaml, you have removed helm.yaml but add other two yamls. But in your tag.yaml, it has hardcode - HelmPackage depends, which looks like from the deleted helm.yaml.

For your scenario, it’s recommended to create a new tag2.yaml, it could be more simple and maintained easily.

If you still would like to reuse the tag.yml, you can consider below option. The limitation is you cannot add/remove dependencies jobs number.

  1. in main2.yaml, define the jobs as parameter for tag.yaml :
pool:
  vmImage: ubuntu-latest

jobs:
- template: prebuild.yaml
- template: docker-publish.yaml
- template: dotnet-test.yaml
- template: fortify.yaml
- template: sonar.yaml
- template: tag.yaml
  parameters:
    job1: UnitTests
    job2: BuildMyContainers
    job3: Prebuild
    job4: newjob
  1. In tag.yaml, you can change the dependson and conditions with parameters.
jobs:
- job: Tag
  displayName: 'Tag'
  dependsOn: 
  - ${{ parameters.job1 }}
  - ${{ parameters.job2 }}
  - ${{ parameters.job3 }}
  - ${{ parameters.job4 }}

  condition: |
    and
    (
      eq(dependencies.${{ parameters.job1 }}.result, 'Succeeded'),
      eq(dependencies.${{ parameters.job2 }}.result, 'Succeeded'),
      eq(dependencies.${{ parameters.job3 }}.result, 'Succeeded'),
      eq(dependencies.${{ parameters.job4 }}.result, 'Succeeded')
    )

If you define dependson parameter to contain all job names in main2.yaml as below:

...
- template: tag.yaml
  parameters:
    DependsOn:
    - UnitTests
    - BuildMyContainers
    - Prebuild
    - newjob

and use dependsOn: '${{ parameters.DependsOn }}' in tag.yaml,you cannot check all job result on the condition.

This example shows how you can extend your pipeline to provide dependsOn value more dynamically. Based on condition in your example (run if all jobs succeeded), condition is not required because it is default behavior

By default, steps, jobs, and stages run if all direct and indirect dependencies have succeeded.

#example-template.yml
parameters:
  - name: jobName
    type: string
    default: ''
  - name: dependencies
    type: object
    default: []

jobs:
- job: ${{ parameters.jobName }}
  dependsOn: ${{ parameters.dependencies }}
  steps:
  - script: echo "Hello from ${{ parameters.jobName }}"

#azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

jobs:
- job: Build
  steps:
  - bash: echo "Hello world"

- job: Test
  steps:
  - bash: non-existing command

- template: example-template.yml
  parameters:
    jobName: 'templateJobName'
    dependencies:
      - Build
      - Test

Leave a Comment