We have a frontend monorepo build pipeline and trying to implement a dependency between build jobs.
First thing we define is the libraries to be looped over:
parameters:
- name: librariesToBePublished
default:
- my-awesome-package-1
- my-awesome-package-2
- my-awesome-package-3
type: object
Then we have the dependencies among these libraries:
- name: dependencies_my_awesome_package_2
displayName: "Library dependencies of my-awesome-package-2"
default:
- my-awesome-package-1
type: object
- name: dependencies_my_awesome_package_3
displayName: "Library dependencies of my-awesome-package-3"
default:
- my-awesome-package-1
- my-awesome-package-2
type: object
So, the my-awesome-package-2 should not be built and deployed before my-awesome-package-1 since it is depending on it. The job to build and publish that should wait until its dependency is built and published.
This is the job definition:
- stage: Publish
displayName: "Publish Libraries"
jobs:
- ${{ each package in parameters.librariesToBePublished }}:
- job: Build_${{replace(package, '-', '_')}}
displayName: "Build ${{package}}"
${{ if parameters['${{ format('dependencies_{0}', replace(package, '-', '_')) }}'] }}:
dependsOn:
- ${{ each dep in parameters['${{ format('dependencies_{0}', replace(package, '-', '_')) }}'] }}:
- Build_${{replace(dep, '-', '_')}}
condition: succeeded()
When we try to echo the expression $[parameters['${{format('libDependencies_{0}', replace(package, '-', '_') ) }}']
it works but not in if
and each
parts.
What we are missing here?
Instead of using a string array:
parameters:
- name: libraries
type: object
default:
- lib1
- lib2
- lib3
Consider using a complex object, where you specify the dependencies for each library:
parameters:
- name: libraries
type: object
default:
- name: lib1
displayName: 'Library 1'
dependsOn: []
- name: lib2
displayName: 'Library 2'
dependsOn:
- lib1
- name: lib3
displayName: 'Library 3'
dependsOn:
- lib1
- lib2
Full working example:
parameters:
- name: libraries
type: object
default:
- name: lib1
displayName: 'Library 1'
dependsOn: []
- name: lib2
displayName: 'Library 2'
dependsOn:
- lib1
- name: lib3
displayName: 'Library 3'
dependsOn:
- lib1
- lib2
trigger: none
pool: Default
jobs:
- ${{ each library in parameters.libraries }}:
- job: ${{ library.name }}
displayName: ${{ library.displayName }}
dependsOn: ${{ library.dependsOn }}
steps:
- checkout: none
- script: echo ${{ library.name }}
Advantages:
condition
property to specify conditions under which the job runs