我有一个包含 8 个不同 Dockerfile 的存储库,用于构建不同的镜像。它们都在同一个存储库中,因为它们共享 80% 的相同代码。每个 Dockerfile 对应一个单独的产品。我目前有一个 azure-pipeline.yaml 文件来将 8 个 Dockerfile 构建到镜像中。在制作 PR 或合并到我的主分支时,我通常只更新 8 个产品之一的功能。因此更新所有 8 张图像是没有意义的。
我想知道我可以选择哪些选项来触发我更改的产品的构建。但偶尔会触发所有 8 个构建(如果更新了共享方法)。例如,是否有一个标志功能可以用来表示当识别出该标志时,仅运行管道的这一部分?
旁注:我知道我可以将我的单一存储库拆分为许多不同的存储库,并创建一个允许共享公共(public)代码的包。然而,这需要大量的时间投入,想知道是否有更简单的方法。
最佳答案
您可以在 yaml 文件中结合使用路径过滤器和条件,根据拉取请求或提交中的更改有选择地运行构建。
1。路径过滤器
您可以使用路径过滤器来指定哪些路径应触发管道。例如,如果每个 Dockerfile 都位于单独的目录中,则可能有如下内容:
trigger:
paths:
include:
- 'productA/*'
仅当 productA
目录发生更改时才会触发构建。
2。条件步骤
您可以向步骤或作业添加条件来决定它们是否应该运行。例如,您可以定义变量并使用它们有条件地运行步骤:
variables:
isFullBuild: $[eq(variables['Build.Reason'], 'Manual')]
steps:
- script: echo Building ProductA...
condition: or(eq(variables.isFullBuild, true), changesContain('productA/*'))
您可以将两者结合起来添加触发器并调节您的管道,如下所示。
trigger:
branches:
include:
- main
paths:
include:
- 'productA/*'
- 'productB/*'
- 'common/*'
- job: BuildProductA
condition: or(eq(variables.isFullBuild, true), changesContain('productA/*', 'common/*'))
steps:
- script: echo Building ProductA...
- job: BuildProductB
condition: or(eq(variables.isFullBuild, true), changesContain('productB/*', 'common/*'))
steps:
- script: echo Building ProductB...
更多信息:changeContains 不是 Azure Pipelines 中的表达式(它只是添加类似条件的占位符)。在使用作业条件之前,您应该添加一个运行脚本并生成将保存更改的文件夹的输出的作业。用于比较工作条件是否存在变化。下面的例子:
CheckChanges.ps1
$folders = @("productA", "productB", "productC") # specify your folder names
$changedFolders = @()
foreach ($folder in $folders) {
$changes = git diff --name-only HEAD HEAD~1 -- $folder
if ($changes) {
$changedFolders += $folder
}
}
# Join the changed folders into a comma-separated string
$changedFoldersString = $changedFolders -join ','
# Set the pipeline variable
Write-Output "##vso[task.setvariable variable=changedFolders;isOutput=true]$changedFoldersString"
您更新后的管道可能如下所示:
trigger:
branches:
include:
- main
paths:
include:
- 'productA/*'
- 'productB/*'
- 'common/*'
- job: CheckChanges
pool:
vmImage: 'windows-latest'
steps:
- powershell: |
.\CheckChanges.ps1
name: checkChangesStep
- job: BuildProductA
dependsOn: CheckChanges
variables:
changes: $[ dependencies.CheckChanges.outputs['checkChangesStep.changedFolders'] ]
condition: or(eq(variables.isFullBuild, true), contains(variables['changes'], 'productA'))
steps:
- script: echo Building ProductA...
- job: BuildProductB
dependsOn: CheckChanges
variables:
changes: $[ dependencies.CheckChanges.outputs['checkChangesStep.changedFolders'] ]
condition: or(eq(variables.isFullBuild, true), contains(variables['changes'], 'productB'))
steps:
- script: echo Building ProductB...
注意:我尚未通过运行来验证上述管道,并且可能包含一些语法/其他问题,并且仅作为通用方法提供。
关于azure - 如何在包含许多 Dockerfile 的单一存储库中构建一个特定的 Docker 镜像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77181559/