【问题标题】:How to use output of a powershell command as parameters in Azure pipeline?如何在 Azure 管道中使用 powershell 命令的输出作为参数?
【发布时间】:2020-04-12 23:15:10
【问题描述】:

我有一个 PowerShell 脚本任务,它从我的 git 存储库中的一个文件夹中获取一些文件的名称并将它们放入一个变量中。我想在参数中使用这些文件名并在另一个任务(任务:HelmDeploy@0)中使用“每个”条件,以便每次使用其中一个文件名作为 valueFile 变量来运行该任务。

这是我尝试过的,但是它给出了一个错误 Template-Yaml/deploy-jobs.yaml@pipelinetemplates Expected a sequence or mapping。 ${{parameters.files 中的每个文件}}

行中的实际值 '$[dependencies.A.outputs['fileoutput.valuefiles']]'

部署-jobs.yaml

   parameters:
     files: []

   jobs:
     - job: Deploy
       pool:
         vmImage: 'ubuntu-latest'
       variables:
         filenames: ${{ parameters.files }}
       steps:
       - task: HelmInstaller@1
         displayName: 'Installing Helm'
         inputs:
           helmVersionToInstall: '2.15.1'

       - task: HelmDeploy@0
         displayName: 'Initializing Helm'
         inputs:
           connectionType: 'Azure Resource Manager'
           azureSubscription: $(azureSubscription)
           azureResourceGroup: $(azureResourceGroup)
           kubernetesCluster: $(kubernetesCluster)
           command: 'init'

       - task: AzureCLI@2
         inputs:
           azureSubscription: $(azureSubscription)
           scriptType: 'bash'
           scriptLocation: 'inlineScript'
           inlineScript: 
             echo "##vso[task.setvariable variable=imgtag]$(az acr repository show-tags --name myacr --repository myrepo --orderby time_desc --top 1 | awk ' /[[:digit:]]/ { print $0 } ' | tr -d '[:space:]')"

       - task: Bash@3
         displayName: 'Fetching repo-tag'
         inputs:
           targetType: 'inline'
           script: |
             echo tag=$(imgtag)
             echo filenames=$(filenames) ### output is: **/myfolder/dev/file1.yaml,**/myfolder/dev/file2.yaml

      - ${{each file in parameters.files}}: ##Error 
       - task: HelmDeploy@0
         displayName: 'Upgrading helmchart'
         inputs:
           connectionType: 'Azure Resource Manager'
           azureSubscription: $(azureSubscription)
           azureResourceGroup: $(azureResourceGroup)
           kubernetesCluster: $(kubernetesCluster)
           command: 'upgrade'
           chartType: 'FilePath'
           chartPath: $(chartPath)
           install: true
           releaseName: $(releaseName)
           ##valueFile: $(valuefiles)
           valueFile: ${{ file }}
           arguments: '--set image.tag=$(imgtag) --set domain=$(domain)'

azure-pipeline.yaml 文件如下:

  trigger:
    branches:
      include:
        - master
        - refs/tags/v*
    paths:
      exclude:
        - readme.md

  variables:
    azureSubscription: 'myazuresubscription'
    chartPath: '**/mychart'
    containerRegistry: 'mysc'
    repository: 'myrepo'

  resources:
    repositories:
    - repository: pipelinetemplates
      type: github
      name: 'mygitorg/myrepo'
      endpoint: 'mygitorg'

  stages:
    - stage: Deploy_Cluster
      variables:
        azureResourceGroup: 'myresourcegroup'
        kubernetesCluster: 'mycluster'
        releaseName: 'mychartreleasename'
        #valueFile: '**/mychart/values.yaml'
        domain: 'mydomain'
      jobs:

 - job: A
   pool:
    vmImage: 'ubuntu-latest'
   steps:
   - task: PowerShell@2
     displayName: 'Fetching ValueFiles'
     inputs:
      targetType: 'inline'
      script: |
       Write-Host "Fetching value files"
       cd myfolder
       $a=git ls-files
       $List = $a | foreach {'**/myfolder/dev/' + $_}
       Write-Host $List
       $d = '"{0}"' -f ($List -join '","')
       Write-Host $d   ### output is: "**/myfolder/dev/file1.yaml","**/myfolder/dev/file2.yaml"
       Write-Host "##vso[task.setvariable variable=valuefiles;isOutput=true]$d"
     name: fileoutput

      - template: Template-Yaml/deploy-jobs.yaml@pipelinetemplates  ##Error expected a sequence or mapping
        parameters: 
          files : $[dependencies.Deploy.outputs['fileoutput.valuefiles']]

我从这个页面得到了一些想法:https://www.aaron-powell.com/posts/2019-05-24-azure-pipeline-templates-and-parameters/ 关于使用依赖项。

我用谷歌搜索了很多,但到目前为止我找不到解决此问题的方法,我们将不胜感激。

测试 Levi建议的回复:

parameters:
  files: []

jobs:
#- ${{each file in parameters.files}}:
   - job: Deploy
     dependsOn: A
     pool:
       vmImage: 'ubuntu-latest'  
     variables:
       filenames: ${{ parameters.file }} 
     steps:
     - task: Bash@3
       displayName: 'Fetching repo-tag'
       inputs:
         targetType: 'inline'
         script: |
           ##echo files=$(filenames) #output is files=file1.yaml,file2.yaml
           for i in $(filenames)
           do
              echo "valuefiles= $i "
           done

OutPut 是 valuefiles=files=file1.yaml,file2.yaml

使用 PowerShell 进行测试:

 - task: PowerShell@2
   displayName: 'Fetching ValueFiles'
   inputs:
     targetType: 'inline'
     script: |
       foreach ($i in ${{ parameters.files }}) {
           Write-Host "filenames=$i"
       }

错误:ObjectNotFound: ($[dependencies.A.ou\u2026output.valuefiles]]:String) [], ParentContainsErrorRecordException

- task: PowerShell@2
   displayName: 'Fetching ValueFiles'
   inputs:
     targetType: 'inline'
     script: |
       foreach ($i in $(filenames)) {
           Write-Host "filenames=$i"
       }

错误:foreach ($i in ) { + ~ 表达式或语句中出现意外的标记 ')'。 + CategoryInfo : ParserError: (:) [], ParseException

【问题讨论】:

  • 我会考虑创建一个脚本并使用管道中的参数调用它。对我来说,内联 PowerShell 转义语法很繁重……
  • 我想在管道中使用脚本,这样每当我将新的 file.yaml 推送到该文件夹​​时,管道就会被触发,扫描文件夹,获取文件名,然后运行基于 HelmDeploy 任务在那个文件名上。只要我知道算法应该如何,它可以是任何脚本语言 bash 或 python。

标签: parameter-passing azure-pipelines kubernetes-helm


【解决方案1】:

发生错误是因为files只能在运行时计算,而- ${{each file in parameters.files}}是在编译时计算的。有关变量语法的更多信息,请查看here

如果动态变量已通过参数传递,- ${{each file in parameters.files}} 将不起作用。

我对 kubernetes 了解不多,如果你能设法使用 powershell/bash 脚本来执行 HelmDeploy 任务。您可以 foreach 脚本中的文件并部署每个文件。

- powershell: |
          foreach ($i in $(filenames)) {helm.exe upgrade ....}

类似的问题已提交给 Microsoft 开发团队,并确定上述问题是设计使然。但您仍然可以通过点击“Suggest a feature”并选择“azure devops

submit a feature request

更新:

azure-pipeline.yaml

trigger:
    branches:
      include:
        - master
 stages:
  - stage: Deploy_Cluster

    jobs:
    - job: A
      pool:
        vmImage: 'ubuntu-latest'
      steps:
      - task: PowerShell@2
        displayName: 'Fetching ValueFiles'
        inputs:
          targetType: 'inline'
          script: |
            Write-Host "Fetching value files"
            cd '$(system.defaultworkingdirectory)'
            $a=git ls-files
            $List = $a | foreach {'**/myfolder/dev/' + $_}
            Write-Host $List
            $d = '"{0}"' -f ($List -join '","')
            Write-Host $d  

            Write-Host "##vso[task.setvariable variable=valuefiles;isOutput=true]$d"

        name: fileoutput

    - job: B
      dependsOn: A
      pool:
        vmImage: 'ubuntu-latest'
      variables: 
        allfiles: $[dependencies.A.outputs['fileoutput.valuefiles']]
      steps:
      - template: deploy-jobs.yaml
        parameters: 
          files : $(allfiles)

部署-jobs.yaml

parameters:
  files: []

steps :
- task: PowerShell@2
  displayName: 'Fetching ValueFiles'
  inputs:
    targetType: 'inline'
    script: >

      foreach ($i in ${{parameters.files}})
      {
        Write-Host "filenames=$i"
      }

【讨论】:

  • 感谢您的回复。是的,我可以在管道中使用 bash 脚本,但您能告诉我如何执行此操作吗?“您可以在脚本中查找文件并部署每个文件。”我尝试了很多不同的东西,但它总是给我错误......
  • 为了在powershell任务中做helm升级工作,上面的一些脚本更新了powershell脚本
  • 所以在这一行:foreach ($i in $(filenames)) 文件名来自哪里?它不使用任何参数吗?这是我尝试使用的每个循环和参数的示例,但它不适用于我的情况mattvsts.github.io/2019/05/04/…
  • 它来自您在模板中定义的变量filenames: ${{ parameters.files }}。您也可以尝试使用foreach ($i in${{ parameters.files }})
  • 您应该将 foreach 脚本写在一行中,或者选中 this thread 以拆分单个命令。我更新了我的简单 yaml
猜你喜欢
  • 2021-09-11
  • 2012-03-27
  • 2019-02-16
  • 2020-04-02
  • 2012-04-08
  • 1970-01-01
  • 2020-04-04
相关资源
最近更新 更多