Search code examples
azure-devopsazure-pipelines-yaml

Azure Devops - Conditions issues in azure pipelines


I have 3 stages in my pipeline, and now i would like to had conditions for stages:

  • Step #1 is triggered by default except if a PROD or SWINT variable were added during a manual build
  • Step #2 is triggered by default except if a PROD or UNIT variable were added during a manual build
  • Step #3 is always triggered

I tried a lot of different solutions but the best I can do is having a working solution without the possibility of canceling manually the run...

Any ideas ?

stages:
 - stage: Step1
   condition: and(succeeded(), eq(variables['PROD'], ''), eq(variables['SWINT'], ''))
   jobs:
     - template: ...     
     - job: Step1
       ...

 - stage: Step2
   condition: and(succeeded(), eq(variables['PROD'], ''), eq(variables['UNIT'], ''))
   jobs:
   ...

 - stage: Step3
condition: and(succeeded(), in(dependencies.Swints.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), not(canceled()))   
   jobs:
   - job: Step3
     pool: ...
     ....

Here is the issues:

  • Adding condition overwrite the implicit default value 'succeeded()' so I have to add it, otherwise i cannot 'cancel' manually the build.
  • When step2 is 'skipped' due to a PROD variable set, I would like to run step3 but it fails. To resolve this i have to replace condition by always() but in this case, the manual cancel is not taken into account.
  • I would like to have step2 running on manual build when SWINT is added, step1 should be ignored/skipped then step2 should run and also step3. But during the run i would also allow manual 'cancel' to work....

Addentum 1: Updated to the following solution, i think that is would be the correct strategy, it works when i set isProd value to false. So now, i need to have a correct evaluation on this PROD. It's a variable passed at queue time by the user, adding variable named PROD and set a value (i.e: 1). Doesn't look like to work. I would need a runtime evaluation but it seems that is should not be coded in this way.

When i set value: false, it works as i expect, and the evaluation expression

eq(variables['PROD'], '')

returns false or true when i use it into as a condition depending if i set PROD or not at queue time. I don't understand why the expression doesn't work when i use it in variables section.

variables:
- name: isProd
  value: $[eq(variables['PROD'], '')]

stages:
  - ${{ if eq(variables['isProd'], false)}}:
    - stage: Units

Addentum 2: Trying a new strategy:

 - ${{ if eq(variables['PROD'], '' )}}:
   - stage: Step1 

 - ${{ if eq(variables['PROD'], '' )}}:
   - stage: Step2 

 - stage: Step3

But it still doesn't work, i cannot trig step1/step2 by adding variable PROD when i run it manually.

Here is my old condition

condition: and(succeeded(), eq(variables['PROD'], ''), eq(variables['SWINT'], '')) When i set PROD with the value 1 from web interface queue build feature, it makes a false and the stage is skipped. The same test from IF statement above stages doesn't react in the same way apparently. The evaluation doesn't work, i don't know why.


Solution

  • Here are the requirements I summarize so far:

    Step #1 is triggered by default except if a PROD or SWINT variable were added during a manual build

    Step #2 is triggered by default except if a PROD or UNIT variable were added during a manual build

    Step #3 is always triggered

    When step2 is 'skipped' due to a PROD variable set, I would like to run step3 but it fails. To resolve this i have to replace condition by always() but in this case, the manual cancel is not taken into account.

    I would like to have step2 running on manual build when SWINT is added, step1 should be ignored/skipped then step2 should run and also step3. But during the run i would also allow manual 'cancel' to work....

    What i'm trying to do is allow user to launch a manuel build using the queue build feature, adding a variable named PROD or SWINT and set value to 1.

    Here are some tips that we can take into consideration to generate the sample YAML.

    • Instead of using Step 1,2,3 to define each stage, I prefer using Stage 1,2,3 because a step are usually referred as a task in a job.

    • By default, each stage in a pipeline depends on the one just before it in the YAML file. If you need to refer to a stage that isn't immediately prior to the current one, you can override this automatic default by adding a dependsOn section to the stage. We can use dependOn: [] for Stage2 and Stage3, so that there is no dependency between stages.

    • We can define variables for a YAML pipeline via the web UI and let users override the value when running this pipeline. In the sample, I have defined variables of PROD SWINT and UNIT with empty values.

      enter image description here

    Here is the sample YAML.

    trigger:
    - main
    
    stages:
    - stage: Stage1
    
      condition: and( ne(variables['PROD'], ''), ne(variables['SWINT'], ''))
      jobs:
      - job: Job1
        steps:
        - script: |
            echo $(PROD)
            echo $(SWINT)
          name: step1
    
    - stage: Stage2
      dependsOn: []
      condition: and( ne(variables['PROD'], ''), ne(variables['UNIT'], ''))
      jobs:
      - job: Job2
        steps:
        - script: |
            echo $(PROD)
            echo $(SWINT)
          name: step2
    
    - stage: Stage3
      dependsOn: []
      jobs:
      - job: Job3
        steps:
        - script: |
            echo $(PROD)
            echo $(SWINT)
          name: step3
    

    When the pipeline is automatically triggered by any commit pushed to main branch, Stage1 and Stage2 are skipped because the conditions are evaluated and not met, as the values of variables PROD SWINT and UNIT are not defined; Stage3 will continue to run even Stage2 is skipped, because Stage3 dependsOn no stages.

    enter image description here

    When I run the pipeline manually, I can replace the values of the variables PROD, SWINT and UNIT with 1; hence, all the stages will be running. enter image description here