Запускать задание Azure Pipelines только при изменении определенных файлов
У меня есть репозиторий, содержащий как Dockerfile, так и другой код. Мы хотим выполнить определенные шаги независимо от того, что изменилось, но хотим запустить толькоdocker build
работа, когда **/Dockerfile
изменено.
Я рассмотрел документацию Условия и документацию Expressions, но неясно мне, как (если это вообще возможно), как объединить эти или иным образом достичь желаемого результата.
Я понимаю, что это возможно в bash
(например git rev-list...
а также git diff --name-only <previous_commit>..HEAD | grep <pattern>
), но это немного громоздко, и в Azure Pipelines все еще отображается, что задание было выполнено, просто произошло короткое замыкание. В идеале это должно было показать (соответственно), что задание было пропущено полностью.
Я также понимаю, что часть Docker и часть кода могут находиться в отдельных репозиториях с отдельными триггерами сборки, но хотел бы, чтобы они были вместе в одном репо, если это возможно.
4 ответа
Извините, но для каждого задания нет триггера. Триггер для области трубопровода.
В соответствии с вашими требованиями вы можете использовать эту структуру как обходной путь:
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. Предполагая, что у вас есть job1 и job2(сборка докеров), вам просто нужно добавить одну задачу PS, как указано выше, в конце job1. Затем он выводит одну переменную, которая определяет, нужно ли нам запускать job2 или пропускать его.
2. Задача Powershell может выполняться в Linux, macOS или Windows.
2. Суть этого обходного пути заключается в следующем: использование выходной переменной задания в условии в следующем задании.
Хотя вопрос старый, у меня была такая же проблема, и я думаю, что у меня есть хорошее решение. Задача состоит в том, чтобы гарантировать, что решение работает, даже если несколько коммитов отправляются одновременно, или если сборка завершается сбоем (и, следовательно, не развертывается) или при слиянии 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)
Примечание. Ответ DaveF работает хорошо, но теперь вам нужно добавить указание предыдущего шага оформления заказа как:
steps:
- checkout: self
fetchDepth: 0
Дополнительную информацию см. в неоднозначном аргументе HEAD^ в конвейере Azure DevOps.
Вы можете определить paths/include
так же как paths/exclude
фильтр по каждому триггеру. Я не смог найти это на обычном сайте документации, но репозиторий YAML четко объясняет это:
Пример:
trigger:
batch: true
branches:
include:
- features/*
exclude:
- features/experimental/*
paths:
include:
- **/Dockerfile
PS: Не совсем уверен, поддерживаются ли подстановочные знаки и какой синтаксис для них использовать.