admin管理员组

文章数量:1125047

I have a job in azure-pipelines that receives a variable number of dependencies. It could have zero dependencies, or "n" dependencies depending what previous jobs were executed before this one.

Let's see an example:

file: "dependent-job.yml"

parameters:

- name: Dependencies
  type: Array
  default:
     - Job1
     - Job2

Jobs:
  - job: Variousdependencies
    name: MyJob
    ${{ if parameters.Dependencies }} 
      dependsOn: ${{ parameters.Dependencies }}
    condition: |
      and(eq(dependencies.Job1.result, 'Succeeded'),
          eq(dependencies.Job2.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
      )

If I have 3 dependencies, I need to add another dependency in condition:

    condition: |
      and(eq(dependencies.Job1.result, 'Succeeded'),
          eq(dependencies.Job2.result, 'Succeeded'),
          eq(dependencies.Job3.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
      )

I would like to generate the lines that check if the previous jobs ended sucessfuly using the each syntax. This is what I tried:

    condition: |
      and(${{ each job in dependencies }}
             eq(dependencies.{{ job }}.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
     )

but I received the following error when trying to run it:

The directive 'each' is not allowed in this context. Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression.

I have a job in azure-pipelines that receives a variable number of dependencies. It could have zero dependencies, or "n" dependencies depending what previous jobs were executed before this one.

Let's see an example:

file: "dependent-job.yml"

parameters:

- name: Dependencies
  type: Array
  default:
     - Job1
     - Job2

Jobs:
  - job: Variousdependencies
    name: MyJob
    ${{ if parameters.Dependencies }} 
      dependsOn: ${{ parameters.Dependencies }}
    condition: |
      and(eq(dependencies.Job1.result, 'Succeeded'),
          eq(dependencies.Job2.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
      )

If I have 3 dependencies, I need to add another dependency in condition:

    condition: |
      and(eq(dependencies.Job1.result, 'Succeeded'),
          eq(dependencies.Job2.result, 'Succeeded'),
          eq(dependencies.Job3.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
      )

I would like to generate the lines that check if the previous jobs ended sucessfuly using the each syntax. This is what I tried:

    condition: |
      and(${{ each job in dependencies }}
             eq(dependencies.{{ job }}.result, 'Succeeded'),
          eq(variables[MyJobEnabled,'True'),
          eq('${{ parameters.ForceJob }}','True')
     )

but I received the following error when trying to run it:

The directive 'each' is not allowed in this context. Directives are not supported for expressions that are embedded within a string. Directives are only supported when the entire value is an expression.
Share Improve this question edited 2 days ago Jane Teichmann asked 2 days ago Jane TeichmannJane Teichmann 133 bronze badges New contributor Jane Teichmann is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
Add a comment  | 

2 Answers 2

Reset to default 0

Consider adding a condition property to the Dependencies parameter and use filtered arrays to dynamically set the dependencies and conditions of the job.

Sample pipeline:

pool:
  vmImage: ubuntu-latest

trigger: none

parameters:
  - name: ForceJob
    type: boolean
    default: true

  - name: Dependencies
    type: object
    default: 
      - jobName: Job1
        condition: eq(dependencies.Job1.result, 'Succeeded')
        exitCode: 0 # Change to 1 to simulate a failed job
      - jobName: Job2
        condition: eq(dependencies.Job2.result, 'Succeeded')
        exitCode: 0 # Change to 1 to simulate a failed job

variables:
  - name: MyJobEnabled
    value: True

jobs:
  - ${{ each dependency in parameters.Dependencies }}:
    - job: ${{ dependency.jobName }}
      displayName: ${{ dependency.jobName }}
      steps:
        - checkout: none
        - script: |
            echo "Job: ${{ dependency.jobName }}"
            exit ${{ dependency.exitCode }}
          displayName: 'Display job name'

  - job: AnotherJob
    dependsOn: ${{ parameters.Dependencies.*.jobName }}
    condition: |
      and(
        ${{ coalesce(join(', ', parameters.Dependencies.*.condition), 'True') }},
        eq(variables['MyJobEnabled'], 'True'),
        eq('${{ parameters.ForceJob }}', 'True')
      )
    steps:
      - checkout: none
      - script: |
          echo "conditions: ${{ join(', ', parameters.Dependencies.*.condition) }}"
        displayName: 'Display conditions'

Notes:

  • coalesce(..., 'True') will generate a dummy condition in case Dependencies parameter is an empty array
  • join(', ', parameters.Dependencies.*.condition) will generate eq(dependencies.Job1.result, 'Succeeded'), eq(dependencies.Job2.result, 'Succeeded') for the conditions set in the sample pipeline

Azure DevOps compile-time expressions do not support nested expressions in a single scalar value.

There is a way to accomplish what you want:

  1. Create a template for your job that accepts the conditions as an array of strings (object). In that template, you concatenate the strings together to assemble a single scalar value.

    # template - job with dynamic conditions
    parameters:
    - name: name
      type: string
    
    - name: displayName
      type: string
      default: ''
    
    - name: dependsOn
      type: object
      default: []
    
    - name: condition
      type: object
      default: []
    
    - name: steps
      type: stepList
    
    jobs:
    - job: ${{ parameters.name }}
      displayName: ${{ coalesce( parameters.displayName, parameters.name ) }}
      ${{ if ne(length(parameters.condition), 0) }}:
        condition: ${{ join( '', parameters.condition) }}
      ${{ if ne(length(parameters.dependsOn), 0) }}:
        dependsOn: ${{ parameters.dependsOn }}
      steps: 
      - ${{ parameters.steps }}
    
  2. In the calling template, dynamically construct the array of condition statements. It looks really weird, and you need to include the , statements as they would normally appear in the condition.

    # pipeline
    parameters:
    - name: dependencies
      type: object
      default:
      - job1
      - job2
    
    - name: forceJob
      type: boolean
      default: false
    
    jobs:
    - job: job1
      steps:
      - script: echo 'job1'
    
    - job: job2
      steps:
      - script: echo 'job2'   
    
    - template: job-with-dynamic-conditions.yml
      parameters:
        name: variousDependences
        dependsOn: ${{ parameters.dependencies }}
        condition: 
        - and(
        - ${{ each job in parameters.dependencies }}:
          - eq(dependencies.${{ job }}.result, 'Succeeded'),
        - eq(variables['jobEnabled'], 'true'),
        - eq( '${{ parameters.forceJob }}', 'true')
        - )
       steps:
       - script: echo 'steps go here'
    

本文标签: conditional statementsAzure pipelines conditions with each loop inside the conditionStack Overflow