3

I asked the following question at the beginning of the year:

Multiple separate triggers in azure-pipelines.yml

Basically, my setup is my "microservices" are subdirectories in a monorepo. I wanted separate triggers for each of those subdirectories based on if there were changes in them. I was trying to avoid a polyrepo and it sounded like this answer was the solution. Otherwise, anytime there was a change anywhere in the project, everything would be triggered to rebuild and redeploy.

I started running into issues with it so I disabled it. The two primary issues where:

  • It seemed like when the pipeline would fail, either at the CI or CD stage, and I'd go to manually trigger it, it wouldn't find changes for some reason and wouldn't run. I'd have to modify the azure-pipeline.yaml by commenting out the task checking for changes and then run. Or I'd have to make some small change, recommit, retrigger, etc.
  • Sometimes I did just want to manually trigger the subdirectory and its associated pipeline, and I'd have to do the preceding.

So I disabled it and have just been stopping the pipeline from rebuilding and redeploying everything when it is triggered, and manually running on the subdirectories I wanted.

How can I implement this functionality in my azure-pipeline.yaml?

  1. Only run on a subdirectory if there is a change.
  2. Run when there is a manual trigger even if no changes.
trigger:
  branches:
    include:
    - staging
    - master
  paths:
    include:
    - admin/*
    - client/*
    - api/*
    - azure-pipelines.yml
cjones
  • 8,384
  • 17
  • 81
  • 175
  • _How can I implement this functionality?_ To exactly which functionality are you refering? – Wolfgang Kuehn Oct 11 '20 at 20:47
  • Hi @eox.dev, Is there any update about this ticket? Feel free to let me know if you have any questions. If the answer could help, you may consider accepting it. – Vito Liu Oct 14 '20 at 09:49

1 Answers1

2

You need to combine two things:

  • one which is detect changes in your subfolder like here for instance (code is in powershell)
$editedFiles = git diff HEAD HEAD~ --name-only
$editedFiles | ForEach-Object {
   Switch -Wildcard ($_ ) {
       'SubFolderA/*' { Write-Output "##vso[task.setvariable variable=MicroserviceA]true" }
       # The rest of your path filters
   }
}

(you can also leave your way with detecting changes)

  • and detect reason change by using variable Build.Reason

So you would end up with condition similar to this one

or(eq(variables['MicroserviceA'], true), eq(variables['Build.Reason'], 'Manual'))

If you use stages for separation you need to create a new stage put there a logic of detecting subfolder changes, make other stages dependent of this stage and use in other stages condition. However you need to remember about [stage dependencies and their naming]

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - powershell: |
            $editedFiles = git diff HEAD HEAD~ --name-only
            $editedFiles | ForEach-Object {
               Switch -Wildcard ($_ ) {
                   'SubFolderA/*' { Write-Output "##vso[task.setvariable variable=MicroserviceA;isOutput=true]true" }
                   # The rest of your path filters
               }
            }
       name: detectChange
- stage: B
  condition: or(and(succeeded(), eq(dependencies.A.outputs['A1.detectChange.MicroserviceA'], true)), eq(variables['Build.Reason'], 'Manual'))
  dependsOn: A
  jobs:
  - job: B1
    steps:
    - script: echo hello from Stage B

Above way trigger all parts for Manual trigger and if you want to be able to pick a one you may use runtime parameters

parameters:
- name: configs
  type: string
  default: 'all'

trigger: none

jobs:
- ${{ if or(contains(parameters.configs, 'MicroserviceA'),contains(parameters.configs, 'all')) }}:
  - job: MicroserviceA
    steps:
    - script: echo Building MicroserviceA...
- ${{ if or(contains(parameters.configs, 'MicroserviceB'),contains(parameters.configs, 'all')) }}:
  - job: MicroserviceB
    steps:
    - script: echo Building MicroserviceB...
- ${{ if or(contains(parameters.configs, 'MicroserviceC'),contains(parameters.configs, 'all')) }}:
  - job: MicroserviceC
    steps:
    - script: echo Building MicroserviceC...
Krzysztof Madej
  • 32,704
  • 10
  • 78
  • 107