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



我的目标是在我添加到特定文件夹中的每个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"one_answers"nginxalpine"的两个文件。

然后,我将通过stageDependencies命令将该变量加载到矩阵中。

有没有办法从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'

你也可以在这里查看我对类似问题的回答

最后我发现我的解决方案不起作用,因为我试图生成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

最新更新