如何根据文件夹中的当前文件名为策略矩阵提供一个动态对象
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
我的目标是在我添加到特定文件夹中的每个 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