Multiple separate triggers in azure-pipelines.yml

If i understand your request correctly. You can achieve this in a single azure-pipeline.yml. Please check below example yml.

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - client/*
    - api/*

jobs:
- job: getchangepath
  pool:
    vmImage: 'windows-latest'
  steps: 
  - powershell: |
      $url="$(System.CollectionUri)/$(System.TeamProject)/_apis/git/repositories/$(Build.Repository.ID)/commits/$(Build.SourceVersion)/changes?api-version=5.1"
      $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method GET
                       
      $changesFolder = $result.changes | Where-Object{$_.item.gitObjectType -match "tree"} | Select-Object -Property {$_.item.path}
     
      foreach($path in $changesFolder){
        if($path -match '/client'){
          echo "##vso[task.setvariable variable=Client;isOutput=true]$True"
          break
        }
      }

      foreach($path in $changesFolder){
        if($path -match '/api'){
          echo "##vso[task.setvariable variable=Api;isOutput=true]$True"
          break
        }
      }
    name: MyVariable

- job: client
  pool :
    vmImage: 'windows-latest'
  dependsOn: getchangepath
  condition: eq(dependencies.getchangepath.outputs['Myvariable.Client'], 'true')
  steps:
  - powershell: echo 'client job start'
  
- job: api
  pool :
    vmImage: 'windows-latest'
  dependsOn: getchangepath
  condition: eq(dependencies.getchangepath.outputs['Myvariable.Api'], 'true')
  steps:
  - powershell: echo 'api job start'

In above yml. I have three jobs. In the first job getchangepath I call git get changes rest api in the powershell task to get the changed path which triggers the build. And output the variables if the path contains path /client or /api.

Job client and job api are depend on job getchangepath and will be executed on the condition of the output variable in job getchangepath.

Suppose I changed a file in folder client and commit the change to azure repo. Then after job getchangepath is finished. MyVariable.Client will be set to true. Then Job client will evaluate its condition and get started. Job Api will fail its condition and get skipped.


I recently faced this problem. You don't need to hard-code and access the DevOps API and PowerShell code in the solution above.

Here is a simpler solution using out of the box YAML and the workingDirectory property per the official Azure DevOps documentation.

Setup a project structure like this, with each repository having it's own YAML file:

.
├── README.md
├── azure-pipelines.yml
├── service-a
|── azure-pipelines-a.yml
│   └── …
└── service-b
        |── azure-pipelines-b.yml
        └── …

You might not need a root pipeline, but if you do, you will want to ignore the sub-projects:

# Excerpt from /azure-pipeline.yml 

trigger:
  paths:
    exclude: # Exclude!
      - 'service-a/*'
      - 'service-b/*'

And in the sub-projects, you want them to pay attention to themselves:

# Excerpt from /service-a/azure-pipeline-a.yml

trigger:
  paths:
    include: # Include!
      - 'service-a/*' # or 'service-b/*'

Caveat - Working directories!

Your sub-project pipelines are still running with the root as your working directory. You can change this using the workingDirectory key, for example (which uses a variable to avoid repeat):

variables:
  - name: working-dir
    value: 'service-b/'

steps:
- script: npm install
  workingDirectory: $(working-dir)

- script: npm run task
  workingDirectory: $(working-dir)

If your projects share steps, you should use Pipeline Templates (in another repository) per official docs instead.