运行 Azure Pipelines 作业仅在特定文件更改时执行
Run Azure Pipelines job only when certain files are changed
我有一个包含 Docker 文件和其他代码的存储库。我们想要 运行 某些步骤而不管更改了什么,但只希望 运行 docker build
作业在 **/Dockerfile
更改时。
我已经查看了 Conditions documentation and the Expressions documentation,但我不清楚如何(如果可能的话)如何将这些结合起来或以其他方式达到预期的结果。
我知道在 bash
中是可能的(例如 git rev-list...
和 git diff --name-only <previous_commit>..HEAD | grep <pattern>
),但这有点麻烦,它仍然在 Azure Pipelines 中显示作业 运行 ,它只是短路了。理想情况下,它会(适当地)显示作业被一起跳过。
我还意识到 Docker 部分和代码部分可以位于具有单独构建触发器的单独存储库中,但如果可能的话,我希望将它们放在同一个存储库中。
您可以在每个触发器上定义 paths/include
和 paths/exclude
过滤器。我在常规文档站点上找不到这个,但是 the YAML repo clearly explains it:
示例:
trigger:
batch: true
branches:
include:
- features/*
exclude:
- features/experimental/*
paths:
include:
- **/Dockerfile
PS:不完全确定是否支持通配符以及它们使用什么语法。
抱歉,每个作业没有触发器。触发器用于管道范围。
根据您的要求,您可以将此结构作为解决方法:
jobs:
- job: OtherSteps
steps:
Your other steps in this job.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$changedfiles = git diff ... (Choose right git command depending on your needs.)
Write-Host $changedfiles
If ($changedfiles.Contains("Dockerfile")) {
echo "##vso[task.setvariable variable=IfRunDockerBuild;isOutput=true]run"
}
name: 'DetermineIfRunNextJob'
- job: DockerBuild
dependsOn: OtherSteps
condition: eq(dependencies.OtherSteps.outputs['DetermineIfRunNextJob.IfRunDockerBuild'],'run')
steps:
- script: echo Only run this job when IfRunDockerBuild=run instead of Null!
1.Assuming 你有 job1 和 job2(docker 构建),你只需要像上面那样在 job1 的末尾添加一个 PS 任务。然后它输出一个变量来确定我们是否需要 运行 job2 或跳过它。
2.The Powershell task 可以在 Linux、macOS 或 Windows.
上 运行
2.The 此解决方法的核心来自此功能:Use the output variable from a job in a condition in a subsequent job.
虽然这个问题很老了,但我遇到了同样的问题,我想我有一个很好的解决方案。挑战在于确保解决方案即使在同时推送多个提交、构建失败(因此未部署)或仅在主分支上进行部署的 PR 合并时也能正常工作。
我已经在此要点中完整描述了我的解决方案:https://gist.github.com/Myrddraal/f5a84cf3242e3b3804fa727005ed2786
它利用了管道 API,它可以提供自上次成功执行管道以来所有提交的列表。这确保即使在一次推送多个提交时,或者在基础架构更改的构建失败时,它也能正常工作。管道 API 负责确定哪些提交需要检查。
逻辑在这个 powershell 中:
[CmdletBinding()]
param (
$authorisation,
$pathFilter,
$collectionUri,
$project,
$buildId
)
$changesUrl = "$collectionUri/$project/_apis/build/builds/$buildId/changes?api-version=6.0"
$changesResponse = Invoke-RestMethod -Uri $changesUrl -Headers @{Authorization = $authorisation } -Method Get
$commits = @($changesResponse.value | ForEach-Object { $_.id })
Write-Host "##vso[task.setvariable variable=filesUpdated;isOutput=true]False"
Write-Host "Checking $($commits.Length) commits for changes matching path $pathFilter"
for ($j = 0; $j -lt $commits.Length; $j++) {
Write-Host "Checking commit: $($commits[$j]) with its parent"
$files = $(git diff "$($commits[$j])~" $commits[$j] --name-only)
Write-Host $files
if ($files -like "*$pathFilter/*") {
Write-Host "Found file matching path filter in commit $($commits[$j])"
Write-Host "##vso[task.setvariable variable=filesUpdated;isOutput=true]True"
break
}
}
使用以下 YAML 调用它(在拉取存储库后的构建作业中):
- task: PowerShell@2
inputs:
filePath: "azure-pipelines/Test-ChangesMadeInPath.ps1"
arguments: >-
-authorisation "Bearer $(system.accesstoken)"
-pathFilter "azure-pipelines/deployment"
-buildId $(Build.BuildId)'
-collectionUri $(System.CollectionUri)
-project $(System.TeamProject)
name: DetermineChangesMadeInDeploymentFolder
env:
SYSTEM_ACCESSTOKEN: $(system.accesstoken)
然后将以下条件添加到您的部署作业中:
- deployment: DeployInfrastructure
condition: eq(stageDependencies.Build.BuildJob.outputs['DetermineChangesMadeInDeploymentFolder.filesUpdated'], 'True')
displayName: Deploy infrastructure
environment: "prod"
strategy:
runOnce:
deploy:
steps:
- template: deployment/YAML/deploy-infrastructure.yml
parameters:
environment: $(Environment.Name)
我有一个包含 Docker 文件和其他代码的存储库。我们想要 运行 某些步骤而不管更改了什么,但只希望 运行 docker build
作业在 **/Dockerfile
更改时。
我已经查看了 Conditions documentation and the Expressions documentation,但我不清楚如何(如果可能的话)如何将这些结合起来或以其他方式达到预期的结果。
我知道在 bash
中是可能的(例如 git rev-list...
和 git diff --name-only <previous_commit>..HEAD | grep <pattern>
),但这有点麻烦,它仍然在 Azure Pipelines 中显示作业 运行 ,它只是短路了。理想情况下,它会(适当地)显示作业被一起跳过。
我还意识到 Docker 部分和代码部分可以位于具有单独构建触发器的单独存储库中,但如果可能的话,我希望将它们放在同一个存储库中。
您可以在每个触发器上定义 paths/include
和 paths/exclude
过滤器。我在常规文档站点上找不到这个,但是 the YAML repo clearly explains it:
示例:
trigger:
batch: true
branches:
include:
- features/*
exclude:
- features/experimental/*
paths:
include:
- **/Dockerfile
PS:不完全确定是否支持通配符以及它们使用什么语法。
抱歉,每个作业没有触发器。触发器用于管道范围。
根据您的要求,您可以将此结构作为解决方法:
jobs:
- job: OtherSteps
steps:
Your other steps in this job.
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$changedfiles = git diff ... (Choose right git command depending on your needs.)
Write-Host $changedfiles
If ($changedfiles.Contains("Dockerfile")) {
echo "##vso[task.setvariable variable=IfRunDockerBuild;isOutput=true]run"
}
name: 'DetermineIfRunNextJob'
- job: DockerBuild
dependsOn: OtherSteps
condition: eq(dependencies.OtherSteps.outputs['DetermineIfRunNextJob.IfRunDockerBuild'],'run')
steps:
- script: echo Only run this job when IfRunDockerBuild=run instead of Null!
1.Assuming 你有 job1 和 job2(docker 构建),你只需要像上面那样在 job1 的末尾添加一个 PS 任务。然后它输出一个变量来确定我们是否需要 运行 job2 或跳过它。
2.The Powershell task 可以在 Linux、macOS 或 Windows.
上 运行2.The 此解决方法的核心来自此功能:Use the output variable from a job in a condition in a subsequent job.
虽然这个问题很老了,但我遇到了同样的问题,我想我有一个很好的解决方案。挑战在于确保解决方案即使在同时推送多个提交、构建失败(因此未部署)或仅在主分支上进行部署的 PR 合并时也能正常工作。
我已经在此要点中完整描述了我的解决方案:https://gist.github.com/Myrddraal/f5a84cf3242e3b3804fa727005ed2786
它利用了管道 API,它可以提供自上次成功执行管道以来所有提交的列表。这确保即使在一次推送多个提交时,或者在基础架构更改的构建失败时,它也能正常工作。管道 API 负责确定哪些提交需要检查。
逻辑在这个 powershell 中:
[CmdletBinding()]
param (
$authorisation,
$pathFilter,
$collectionUri,
$project,
$buildId
)
$changesUrl = "$collectionUri/$project/_apis/build/builds/$buildId/changes?api-version=6.0"
$changesResponse = Invoke-RestMethod -Uri $changesUrl -Headers @{Authorization = $authorisation } -Method Get
$commits = @($changesResponse.value | ForEach-Object { $_.id })
Write-Host "##vso[task.setvariable variable=filesUpdated;isOutput=true]False"
Write-Host "Checking $($commits.Length) commits for changes matching path $pathFilter"
for ($j = 0; $j -lt $commits.Length; $j++) {
Write-Host "Checking commit: $($commits[$j]) with its parent"
$files = $(git diff "$($commits[$j])~" $commits[$j] --name-only)
Write-Host $files
if ($files -like "*$pathFilter/*") {
Write-Host "Found file matching path filter in commit $($commits[$j])"
Write-Host "##vso[task.setvariable variable=filesUpdated;isOutput=true]True"
break
}
}
使用以下 YAML 调用它(在拉取存储库后的构建作业中):
- task: PowerShell@2
inputs:
filePath: "azure-pipelines/Test-ChangesMadeInPath.ps1"
arguments: >-
-authorisation "Bearer $(system.accesstoken)"
-pathFilter "azure-pipelines/deployment"
-buildId $(Build.BuildId)'
-collectionUri $(System.CollectionUri)
-project $(System.TeamProject)
name: DetermineChangesMadeInDeploymentFolder
env:
SYSTEM_ACCESSTOKEN: $(system.accesstoken)
然后将以下条件添加到您的部署作业中:
- deployment: DeployInfrastructure
condition: eq(stageDependencies.Build.BuildJob.outputs['DetermineChangesMadeInDeploymentFolder.filesUpdated'], 'True')
displayName: Deploy infrastructure
environment: "prod"
strategy:
runOnce:
deploy:
steps:
- template: deployment/YAML/deploy-infrastructure.yml
parameters:
environment: $(Environment.Name)