Использование двух автономных агентов конвейера 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

Надеюсь на помощь!

Вы не можете и не должны делать то, что пытаетесь сделать. Агенты намеренно запускают задания в изолированных, независимых рабочих папках. Попытка запустить несколько агентов в одной и той же рабочей папке вызовет условия гонки и ошибки, точно такие же, как вы видите.

Другие вопросы по тегам