如何在Azure Pipeline每个语句中使用动态更新的变量?

问题描述 投票:0回答:1

这是一个简单的 Azure Pipeline,它说明了我的问题:-

jobs:
- job: BuildAndTest
  steps:
  - script: |
     echo "##vso[task.setvariable variable=nuGetPackagesToBuild;isoutput=true]Configuration,Logging,UnitTests.Core"
    name: GetChangedProjects

- job: CreateChangedNuGetPackages
  dependsOn: BuildAndTest
  variables:
    nuGetPackagesToBuildFromBuildAndTestJob: $[ dependencies.BuildAndTest.outputs['GetChangedProjects.nuGetPackagesToBuild'] ]  
  steps:
    - ${{ each nuGetPackageToBuild in split(variables.nuGetPackagesToBuildFromBuildAndTestJob, ',') }} :
      - script: echo $(nuGetPackagesToBuildFromBuildAndTestJob)         # Configuration,Logging,UnitTests.Core
      - script: echo 'NuGet Packages to Build $(nuGetPackagesToBuild)'  # $(nuGetPackagesToBuild)
      - script: echo 'Creating NuGet Package1 ${{nuGetPackageToBuild}}' # $[ dependencies.BuildAndTest.outputs['GetChangedProjects.nuGetPackagesToBuild'] ]'
      - script: echo 'Creating NuGet Package2 $(nuGetPackageToBuild)'   # $(nuGetPackageToBuild)

我有一项工作(BuildAndTest),它创建需要重建的 NuGet 包数组(字符串)。在上面的示例中,列表是硬编码的,但在我的真实脚本中,列表是通过查看 Git 提交中的文件列表动态生成的。

第二个作业 (CreateChangedNuGetPackages) 从 BuildAndTest 作业中读取包列表。它有一个“each”语句,尝试迭代数组中的项目(使用 split() 将字符串转换为数组)。

您可以从 4 个 echo 语句中看到,无论我使用什么语法,nuGetPackageToBuild 变量都不会保留有用的值(例如“Configuration”)。相反,它保存文字字符串“$[ dependency.BuildAndTest.outputs['GetChangedProjects.nuGetPackagesToBuild'] ]”。它不应该这样做,因为我们可以从第一个 echo 语句中看到该变量已正确计算为“Configuration,Logging,UnitTests.Core”。

看起来好像“each”语句是在编译时而不是运行时评估的,因此不可能将“each”与动态生成的数组一起使用。

如果我在 CreateChangedNuGetPackages 作业中对列表进行硬编码,如下所示:-

nuGetPackagesToBuildFromBuildAndTestJob: 'Configuration,Logging,UnitTests.Core'

然后“each”语句似乎正确执行,并且 nuGetPackagesToBuild 变量包含正确的值,并且循环执行 3 次而不是一次(因为数组中有 3 个元素)。

我期望“每个”变量在运行时被分配正确的值。

如何为动态生成的数组中的每个元素执行管道步骤?

azure-devops yaml azure-pipelines each
1个回答
0
投票

YAML 示例中的每个表达式都需要在编译时读取变量值。但跨作业变量:strong textnuGetPackagesToBuild 将在Runtime展开。

这种情况下,Each 表达式在编译时无法获取跨作业变量。所以它无法成功拆分变量。

恐怕没有现成的方法可以直接满足您的要求。

作为解决方法,我建议您可以将管道拆分为两个管道(作业 BuildAndTest -> 管道一和作业 CreateChangedNuGetPackages -> 管道二)。第一个管道将使用 PowerShell/Bash 脚本将变量值传递给第二个管道中的参数值。

这是一个例子:

管道一:

jobs:
- job: BuildAndTest
  steps:
    - task: PowerShell@2
      inputs:
        targetType: 'inline'
        script: |
          $token = "$(pat)"      
          $url="https://dev.azure.com/{Orgname}/{Projectname}/_apis/pipelines/{PipelineRunID}/runs?api-version=5.1-preview"
          
          $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
          
          $JSON = "
          {
            
          
          
            `"resources`": {
              `"repositories`": {
                `"self`": {
                  `"ref`": `"refs/heads/main`"
                }
              }
            },
            `"templateParameters`": {
              `"nuGetPackagesToBuild`":`"Configuration,Logging,UnitTests.Core`"
            },
          
          
          
          }"
          
          
          $response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json

管道二

parameters:
- name: nuGetPackagesToBuild
  type: string

jobs:
- job: CreateChangedNuGetPackages

  steps:
    - ${{ each nuGetPackageToBuild in split(parameters.nuGetPackagesToBuild, ',') }} :
      - script: echo 'Creating NuGet Package1 ${{nuGetPackageToBuild}}' 

结果:

这里是关于 运行时参数 和 Rest API 的文档:运行 - 运行管道

© www.soinside.com 2019 - 2024. All rights reserved.