工作条件在前一阶段使用后评估为 "null"

Job condition evaluates to "null" after it is used in a previous stage

我的 PR 管道的结构如下所示:

trigger: none

resources:
- repo: self

variables:
- template: templates/variables.yaml

pool:
  vmIMage: $(vmImageName)

stages:
- template: templates/changed.yaml
  parameters:
    comparedTo: origin/production
- template: templates/unitTests.yaml
- template: templates/build.yaml
  parameters: 
    services:
    - api
    - admin
    - admin-v2
    - client
    tag: test
    tagVersion: latest
- template: templates/integrationTests.yaml
- template: templates/seleniumTests.yaml

change.yaml 基本上确定了哪些微服务发生了变化,这样就可以避免在没有变化的情况下构建、测试和部署服务。

parameters:
- name: comparedTo
  default: ''

stages:
- stage: Changed
  displayName: Checks for changes in services and configs...
  jobs:
  - job: Changes
    displayName: Checking for changes in services and configs...
    steps:
    - bash: |
        mapfile -t servicesChanged < <(git diff  HEAD ${{ parameters.comparedTo }} --name-only | awk -F'/' 'NF!=1{print }' | sort -u)
        echo "Total Changed: ${#servicesChanged[@]}"
        if [[ ${#servicesChanged[@]} > 0 ]]; then
          echo "Any services changed: True"
          echo "##vso[task.setvariable variable=anyServicesChanged;isOutput=true]true"
        fi
      name: detectChanges

如果 anyServicesChanged = true.

,则后续阶段的工作条件决定工作是否应该 运行

我目前正在测试的,这个 true 总是。

正常到达 unitTests.yaml 和 运行s(通过):

stages:
- stage: UnitTests
  displayName: Run unit tests on service...
  condition: succeeded()
  dependsOn: Changed
  jobs:
  - job: UnitTests
    condition: or(eq(stageDependencies.Changed.Changes.outputs['detectChanges.anyServicesChanged'], true), eq(variables['Build.Reason'], 'Manual'))
    displayName: Running unit tests...
    steps:
    - bash: |
        echo "Running unit tests..."

然后到达 build.yaml 并跳过它:

parameters:
- name: services
  type: object
  default: []
- name: tag
  default: ''
- name: tagVersion
  default: ''

stages:
- stage: BuildAndPush
  displayName: Build and Push Docker images of services...
  condition: succeeded()
  dependsOn: UnitTests
  jobs:
  - job: BuildAndPush
    condition: or(eq(stageDependencies.Changed.Changes.outputs['detectChanges.anyServicesChanged'], true), eq(variables['Build.Reason'], 'Manual'))
    displayName: Building and Push Docker images of services...
    steps:
    - ${{ each service in parameters.services }}:
      - task: Docker@2
        displayName: Build and Push ${{ service }} Docker image
        inputs:
          command: buildAndPush
          repository: $(imageRepository)-${{ service }}
          dockerfile: $(dockerfilePath)/${{ service }}/Dockerfile
          containerRegistry: $(dockerRegistryServiceConnection)
          tags: |
            ${{ parameters.tag }}-${{ parameters.tagVersion }}

工作condition:一模一样,只不过这次说的是NULL:

6 queue time variables used
Expanded: or(eq(Null, True), eq('PullRequest', 'Manual'))
Result: False

我不确定为什么会这样,因为我认为它会在我需要使用该变量的每个地方持续存在。

关于为什么会发生这种情况以及如何解决的建议?

build.yaml中,您需要添加依赖Changed阶段。否则在Changed阶段设置的变量无法在BuildAndPush阶段获取。

stages:
- stage: BuildAndPush
  displayName: Build and Push Docker images of services...
  condition: succeeded()
  dependsOn:
  - UnitTests
  - Changed