Использование двух автономных агентов конвейера Azure для публикации артефактов в параллельном режиме
У меня есть конвейер сборки в Azure Pipelines, содержащий несколько этапов. Язык - C#, .Net Core 3.1/.Net Framework 4.7. На первом этапе конвейера создается все решение и выполняются модульные и интеграционные тесты. На следующих этапах разные микросервисы и отдельные части API публикуются и загружаются в Azure как отдельные артефакты. Все это запускается на собственном агенте сборки.
После тестирования я пытался распараллелить этапы. Логика заключалась в том, что на этих этапах сборка не производится, выполняется только простое копирование и архивирование файлов. Для этого я запустил два разных агента сборки из одного пула на одном компьютере. Агенты использовали ту же локальную папку, что и их рабочие папки. Но когда я попытался запустить конвейер сборки, агенты начали конкурировать за ресурсы. Проблема с папкой для артефактов сборки решена, но не единственная. Например, оба агента пытались создать / удалить одинаковые временные файлы в папке _temp. В этом случае одна задача завершилась сбоем со следующей ошибкой:
[error]Unhandled: ENOENT: no such file or directory, open 'e:\_build\_temp\.taskkey'
Также стали возникать странные ошибки другого типа. Текст ошибок был примерно как на скриншоте ниже: Странный текст ошибки
Я предполагаю, что причиной этих ошибок были конфликты между двумя агентами.
Использование двух разных рабочих папок для агентов кажется не лучшим решением, потому что в этом случае один агент не будет иметь доступа к файлам, созданным на первом этапе.
Есть ли у кого-нибудь успешный опыт запуска двух агентов Azure Pipelines на одном компьютере для обработки одного конвейера?
2 ответа
Как упоминал Дэниел выше, вы не должны использовать ту же локальную папку, что и рабочие папки для ваших локальных агентов.
Существуют обходные пути для обмена файлами между различными этапами на локальных машинах агентов.
Например, вы можете использовать задачу публикации артефактов сборки на этапе A для публикации файлов, которые необходимы на других этапах, на сервере azure DevOps. Затем вы можете использовать задачу загрузки артефактов сборки на этапе B, чтобы загрузить файлы в его рабочий каталог.
Обновить:
Другой обходной путь - добавить задачу сценария для определения переменной и установки ее значения в рабочий каталог этапа A. И добавить зависимость для этапа A на этапе B.
Тогда вы можете использовать выражение dependencies.<Previous stage name>.outputs['<name of the job which execute the task.setvariable >.TaskName.VariableName']
чтобы получить значение переменной, определенной на этапе A, который является рабочим каталогом этапа A.
Пожалуйста, проверьте пример ниже: Этап B может получить доступ к рабочему каталогу этапа A и скопировать свои файлы в c:\test\copyfromoriginalfolder
stages:
- stage: A
jobs:
- job: a
pool: Default
steps:
- task: PowerShell@2
inputs:
targetType: inline
script: |
echo "##vso[task.setvariable variable=PathA]$(system.defaultworkingdirectory)"
name: power1
- stage: B
dependsOn: A
variables:
PathInA: $[dependencies.A.outputs['a.power1.PathA']]
jobs:
- job: b
pool: Default
steps:
- powershell: |
cd $(PathInA)
ls
- task: CopyFiles@2
inputs:
SourceFolder: $(PathInA)
contents: '**'
TargetFolder: 'c:\test\copyfromoriginalfolder'
CleanTargetFolder: true
Надеюсь на помощь!
Вы не можете и не должны делать то, что пытаетесь сделать. Агенты намеренно запускают задания в изолированных, независимых рабочих папках. Попытка запустить несколько агентов в одной и той же рабочей папке вызовет условия гонки и ошибки, точно такие же, как вы видите.