Azure Pipelines:在YAML之间共享值的问题

后端开发 2026-07-10

我是Azure pipeline yaml的新手。

以下是一些背景信息:我这里有一个 azure-pipelines.yml,如下所示,它调用了另一个 dotnet-test-build-and-deploy-to-aks-template.yaml

在这个 dotnet-test-build-and-deploy-to-aks-template.yaml 中,我收集了 WorkItemIds,打算把它推送到另一个级联的 dotnet-deployment-stage.yaml@templates,但我所做的所有测试都不起作用。
dotnet-deployment-stage.yaml@templates 中得到的值始终是空白或空值。

从我目前的观察来看,WorkItemIds 已经被正确收集并在 Write-Host "Work Item IDs: $wiIds" 中显示,因此我得到了这个值。
在Debug WI的输出中,我得到的是空字符串,在级联的dotnet-deployment-stage.yaml中也同样是空字符串。

有人能帮忙把这些 $wiIds 推送到级联模板吗?

这是我的 azure-pipelines.yml

trigger:
  branches:
    include:
      - master
  paths:
    include:
       - 'src/*'
       - 'helm/*'

resources:
  repositories:
    - repository: templates
      type: git
      name: "Test/Test-Pipeline-Templates"
      ref: 'refs/heads/users/Bob/Task-1623737-report-status-back-to-US'

stages:
- template: dotnet-test-build-and-deploy-to-aks-template.yaml@templates
  parameters: 
    projectPath: 'src/Wrs.RuleService'
    helmFilesPath: 'helm'
    dockerfilePath: './Dockerfile'
    dockerfileContext: '.'
    appName: 'businessrule-service'
    dotnetVersion: '8.x'
    sonar: true
    sonarProjectKey: 'Wrs-teams_AKS_RuleService'

这是 dotnet-test-build-and-deploy-to-aks-template.yaml

parameters:
- name: projectPath
  type: string
- name: helmFilesPath
  type: string
- name: dockerfilePath
  type: string
- name: dockerfileContext
  type: string
- name: appName
  type: string
- name: dockerRegistry
  default: 'ACR Service Connection - Staging'
  type: string
- name: dockerRegistriesToPushImages
  default: ['ACR Service Connection - Staging', 'ACR Service Connection - Prod']
  type: object
- name: dotnetVersion
  default: '8.x'
  type: string
- name: sonar
  type: boolean
  default: false
- name: sonarProjectKey
  type: string
  default: ''
- name: skipDeploymentEnvironments
  default: ['test']
  type: object

stages:

# ===============================================================
# 1) BUILD STAGE
# ===============================================================
- stage: Build
  displayName: Build
  pool:
    vmImage: 'ubuntu-latest'

  jobs:

  # ------------------------------------------------------------
  # 1. Build template
  # ------------------------------------------------------------
  - template: dotnetcore-docker-test-build.yaml@templates
    parameters:
      projectPath: '${{ parameters.projectPath }}'
      helmFilesPath: '${{ parameters.helmFilesPath }}'
      dockerfilePath: '${{ parameters.dockerfilePath }}'
      dockerfileContext: '${{ parameters.dockerfileContext }}'
      appName: '${{ parameters.appName }}'
      dockerRegistry: '${{ parameters.dockerRegistry }}'
      dockerRegistriesToPushImages: ${{ parameters.dockerRegistriesToPushImages }}
      dotnetVersion: '${{ parameters.dotnetVersion }}'

  # ------------------------------------------------------------
  # 2. Collect WI IDs
  # ------------------------------------------------------------
  - job: collect_workitems
    displayName: "Collect Work Item IDs"

    pool:
      vmImage: ubuntu-latest

    steps:
    - task: PowerShell@2
      name: extract_pr_and_wi
      displayName: "Extract PR ID and Work Item IDs"
      env:
        SYSTEM_ACCESSTOKEN: $(System.AccessToken)
      inputs:
        targetType: 'inline'
        script: |
          $ErrorActionPreference = "Stop"

          $msg = "$(Build.SourceVersionMessage)"
          Write-Host "Commit message: $msg"

          $patterns = @(
            'Merged PR (\d+):',
            'Merge pull request #(\d+)',
            'Merge PR (\d+)'
          )

          $prId = $null
          foreach ($p in $patterns) {
            if ($msg -match $p) {
              $prId = $matches[1]
              break
            }
          }

          if (-not $prId) {
            Write-Host "No PR ID found."
            Write-Host "##vso[task.setvariable variable=PR_ID;isOutput=true]0"
            Write-Host "##vso[task.setvariable variable=WI_IDS;isOutput=true]''"
            exit 0
          }

          Write-Host "Extracted PR ID: $prId"
          Write-Host "##vso[task.setvariable variable=PR_ID;isOutput=true]$prId"

          $org     = "$(System.CollectionUri)"
          $project = "$(System.TeamProject)"
          $repoId  = "$(Build.Repository.ID)"
          $token   = "$(System.AccessToken)"
          $headers = @{ Authorization = "Bearer $token" }

          $uri = "$org$project/_apis/git/repositories/$repoId/pullRequests/$prId/workitems?api-version=7.1"
          Write-Host "Fetching WI IDs from PR: $uri"

          try {
            $result = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
          }
          catch {
            Write-Host "Failed to fetch WI IDs from PR"
            throw
          }

          $wiIds = ($result.value.id | Sort-Object -Unique) -join ','
          Write-Host "Work Item IDs: $wiIds"
          Write-Host "##vso[task.setvariable variable=WI_IDS;isOutput=true]$wiIds"

  # ------------------------------------------------------------
  # 3. Debug WI output
  # ------------------------------------------------------------
  - job: debug_stageDeps
    displayName: "DEBUG - stageDependencies"
    dependsOn: collect_workitems

    variables:
      WI_TEST: $[ stageDependencies.Build.collect_workitems.outputs['extract_pr_and_wi.WI_IDS'] ]

    steps:
    - script: |
        echo "DEBUG: WI_TEST = '$(WI_TEST)'"
      displayName: "Print WI_TEST output"


# ===============================================================
# 2) DEPLOYMENT STAGE (must NOT be nested under Build.jobs)
# ===============================================================
- template: dotnet-deployment-stage.yaml@templates
  parameters:
    appName: '${{ parameters.appName }}'
    skipDeploymentEnvironments: ${{ parameters.skipDeploymentEnvironments }}
    workItemIds: $[ stageDependencies.Build.collect_workitems.outputs['extract_pr_and_wi.WI_IDS'] ]
    appEnvironments:
      - name: Dev
        serviceConnection: 'staging-sc'
      - name: Staging2
        serviceConnection: 'staging-sc'
      - name: Staging
        serviceConnection: 'staging-sc'
      - name: Prod
        serviceConnection: 'prod-sc'

以及这里的最后一个阶段模板:

# dotnet-deployment-stage.yaml
parameters:
- name: appEnvironments
  type: object
- name: appName
  type: string
- name: helmArtifactName
  type: string
  default: 'helm-values'
- name: skipDeploymentEnvironments
  default: ['test']
  type: object
- name: workItemIds
  type: string

stages:
- ${{ each appEnvironment in parameters.appEnvironments }}:
  - stage: Release_${{ replace(parameters.appName, '-','_') }}_to_${{ appEnvironment.name }}
    displayName: 'Deploy to ${{ appEnvironment.name }}'
    condition: ${{ not(in(parameters.skipDeploymentEnvironments, appEnvironment.name)) }}
    pool: Cloud-Stag2-DeploymentAgentPool
    variables:
    - template: envs/${{ lower(appEnvironment.name) }}.yaml

    jobs:
    - job: Trace_Stage_Inputs
      displayName: "TRACE: dotnet-deployment-stage.yaml — inputs for ${{ appEnvironment.name }}"
      steps:
      - script: |
          echo "=== TRACE: Entering dotnet-deployment-stage.yaml ==="
          echo "Template: dotnet-deployment-stage.yaml"
          echo "AppName: ${{ parameters.appName }}"
          echo "Environment: ${{ appEnvironment.name }}"
          echo "workItemIds param: '${{ parameters.workItemIds }}'"
        displayName: "TRACE — Show template params"

    - template: dotnet-deployment-job.yaml
      parameters:
        appName: '${{ parameters.appName }}'
        helmArtifactName: '${{ parameters.helmArtifactName }}'
        appEnvironment: ${{ appEnvironment }}
        workItemIds: '${{ parameters.workItemIds }}'

解决方案

根据 Azure Doc's,你必须添加一个 dependsOn: collect_workitems,并在变量映射中传递输出的值,就像你在调试阶段所做的那样。

因此,正确的设置应该是:

- template: dotnet-deployment-job.yaml
  dependsOn: collect_workitems
  variables:
      workItemIds: $[ stageDependencies.Build.collect_workitems.outputs['extract_pr_and_wi.WI_IDS'] ]
  parameters:
     appName: '${{ parameters.appName }}'
     helmArtifactName: '${{ parameters.helmArtifactName }}'
     appEnvironment: ${{ appEnvironment }}
     workItemIds: $(workItemIds)

如果你想在同一个作业中使用该变量,你只需使用 $(workItemIds),但要跨越 jobs or stages 传递变量,你需要这个设置。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章