如何根据文件夹中的当前文件名为策略矩阵提供一个动态对象

How to give to the strategy matrix a dynamic object based on the current filenames in the folder

我的目标是在我添加到特定文件夹中的每个 Dockerfile 上有一些工作步骤(docker 构建和推送)到 运行。

这是我正在尝试的主要结构:

...

stages:
- stage: Get_DF_Stage
  displayName: Get_Dockerfiles
  jobs:
    - job: Get_DF_Job
      steps:
        - task: bash@3
          inputs:
            filePath: 'helpers/from_files_to_yaml_object.sh'
          displayName: Get_Dockerfiles
          name: Get_DF_Task


# --- Take the latest image on the private repo and retags it with the current date
- stage: Docker_Image_Patch
  displayName: Docker_Image_Patch
  dependsOn:
    - Get_DF_Stage
  jobs:
  - job: docker_login
    displayName: Login to COMPANY CR

    steps:
    - task: Docker@2
      displayName: Login to COMPANY Container Registry
      inputs:
        command: login
        containerRegistry: COMPANY-cr
  
  - job: docker_patch
    displayName: Build and push Docker images

    strategy:
      # $[ stageDependencies.Get_DF_Stage.Get_DF_Job.outputs['Get_DF_Task.dockerfile_list'] ]
      matrix: 
        nginx:
          dockerfile: 'nginx'
        nginx-alpine:
          dockerfile: 'nginx-alpine'  

    steps:
    - task: Docker@2
      displayName: Build Docker image
      inputs:
        command: build
        containerRegistry: COMPANY-cr
        Dockerfile: dockerfiles/$(dockerfile)
        repository: $(dockerfile)
        buildContext: .
        arguments: --no-cache --pull
        tags: latest

    - task: Docker@2
      displayName: Push Docker image
      inputs:
        command: push
        containerRegistry: COMPANY-cr
        repository: $(dockerfile)
        tags: latest

我的想法是生成执行 bash 任务的 YAML,将具有以下输出:

nginx:
  dockerfile: 'nginx'
nginx-alpine:
  dockerfile: 'nginx-alpine' 

对于文件夹中的两个文件,命名为:'nginx'和'nginx-alpine'。

然后我将通过 stageDependencies command.

将该变量加载到矩阵中

有没有办法从 bash 脚本插入 YAML 对象? 或者是否有更简单的方法来迭代文件上的作业?

是的,这可以通过以下方式实现:

jobs:
- job: JobA
  steps:
  - pwsh: |
      $json="{'nginx': {'dockerfile': 'nginx'}, 'nginx-alpine': {'dockerfile': 'nginx-alpine'}}"
      Write-Host "##vso[task.setvariable variable=targets;isOutput=true]$json"
    name: setTargets
  - script: echo $(setTargets.targets)
    name: echovar

- job: buildSrc
  dependsOn: JobA
  displayName: Build source
  strategy:
    matrix: $[ dependencies.JobA.outputs['setTargets.targets'] ]
  variables:
    targets: $[ dependencies.JobA.outputs['setTargets.targets'] ]
  steps:
  - pwsh: Write-Host "${{ convertToJson(variables) }}"
    displayName: 'Print all variables via expression'

你也可以查看我对类似问题的回答here

最后我发现我的解决方案不起作用,因为我试图生成 YAML 或 JSON 数组,而不是 JSON MAP。

所以我修改了 bash 任务以根据特定文件夹中的文件生成 JSON 地图:

#!/bin/bash
filenames_list="$(ls -1 dockerfiles/ |tr '\n' ' ' )"
filenames_list=($filenames_list) 

filenames_tmp=""
for (( i=0; i<${#filenames_list[@]}; i++ ))
do
    echo "> Found '${filenames_list[$i]}'"
    filenames_tmp="${filenames_tmp}, \"${filenames_list[$i]}\":{\"dockerfile\":\"${filenames_list[$i]}\"}"
done

# Remove first void comma
filenames_tmp="${filenames_tmp[0]:2}"
# Create JSON
filenames_list="{ ${filenames_tmp[*]} }"

## --- Output: { "nginx": { "dockerfile": "nginx" }, "nginx-alpine": { "dockerfile": "nginx-alpine" }}
echo "> Result <${filenames_list}>"
echo "##vso[task.setvariable variable=dockerfile_list;isOutput=true]`echo "${filenames_list}"`"

然后我像这样从第二阶段调用dockerfile变量

- stage: Docker_Image_Patch
  displayName: Docker_Image_Patch
  dependsOn:
    - Get_DF_Stage
  jobs:
  - job: docker_patch
  displayName: Build and push Docker images
  strategy:
    matrix: $[ stageDependencies.Get_DF_Stage.Get_DF_Job.outputs['Get_DF_Task.dockerfile_list'] ]

  steps:
    - pwsh: Write-Output "$(dockerfile)"
      displayName: Show current Dockerfile
    
    - script: echo "##vso[task.setvariable variable=CURRENT_DATE]`date +"%Y%m%d"`"

    - task: Docker@2
      displayName: Build Docker image
      inputs:
        command: build
        containerRegistry: company-cr
        Dockerfile: dockerfiles/$(dockerfile)
        repository: devops/$(dockerfile)
        buildContext: .
        arguments: --no-cache --pull
        tags: |
          $(CURRENT_DATE)
          latest

    - task: Docker@2
      displayName: Push Docker image
      inputs:
        command: push
        containerRegistry: company-cr
        repository: devops/$(dockerfile)
        tags: |
          $(CURRENT_DATE)
          latest