Azure DevOps Server с YAML — каталог сборки меняется при каждом задании?

После перемещения всего YAML в отдельный репозиторий Git у меня возникла странная проблема: теперь с каждым заданием в конвейере каталоги агентов меняются. Первое задание использует _work\1, второе _work\2 и т. д., что означает, что все задания, кроме первого, завершаются неудачей, поскольку каталоги пусты.

Я использую конвейер для конкретного продукта, который расширяет базовый конвейер (спасибо @rui-jarimba за отличное предложение!).

Немного сокращенный код:

# FOO-pipeline.yml

name: QEC-${{ parameters.productVersion }}-$(Date:yyMMdd)$(Rev:rr)

resources:
  repositories:
    - repository: FOO
      type: git
      name: FOO
      ref: main
      trigger:
        branches:
          include:
          - main
    - repository: YAML
      type: git
      name: YAML-Automation
      ref: main
      trigger:
        - none

extends:
  template: /Base-pipeline.yml
  parameters:
    productName: FOO

Этапы Build_with_anaанализ/Build_without_anaанализ используют _work\1 на обоих агентах, все работает отлично (после того, как я объединил разные задания сборки в одно).

Затем этап Test_All использует _work\2, следующий этап использует _work\3 и т. д.

# Base-pipleine.yml

parameters:
  - name: productName
    displayName: Name of the product to build
    type: string

stages:
  - stage: Build_without_analysis
    #      ======================
    displayName: 'Build ${{ parameters.productName }}, no analysis'
    pool:
      demands: BuildServer
    jobs:
    - template: /Jobs/jobBuild-All.yml
      parameters:
        productName: ${{ parameters.productName }}
        configuration: Debug
        staticAnalysis: false


  - stage: Build_with_analysis
    #      ===================
    displayName: 'Build ${{ parameters.productName }}, with analysis'
    dependsOn: []
    pool:
      demands: AnalysisServer
    jobs:
    - template: /Jobs/jobBuild-All.yml
      parameters:
        productName: ${{ parameters.productName }}
        configuration: Release
        staticAnalysis: true


  - stage: Test_All
    #      ========
    displayName: 'All tests ${{ parameters.productName }}'
    dependsOn: Build_without_analysis    
    pool:
      demands: BuildServer    
    jobs:
    - template: /Jobs/jobTests-All.yml
      parameters:
        productName: ${{ parameters.productName }}
# jobTests-All.yml

parameters:
- name: productName
  type: string
  default: FOO

jobs:

- job: Run_all_unit_tests
  #    ==================
  displayName: 'All Unit Tests'
  steps:
    - checkout: none  
    - template: /Jobs/${{ parameters.productName }}/jobTests-${{ parameters.productName }}-UnitTests.yml
      parameters:    
        configuration: Debug

В чем может быть причина?

Не удалось найти ничего связанного ни в документации Microsoft, ни где-либо еще в Интернете.

Каждое задание (не этап) может выполняться разными агентами сборки, которые могут использовать разные рабочие папки и запускаться на разных серверах или даже в виде контейнеров Docker. Но я думаю, что ваша проблема не связана с этим. Вероятно, вы неправильно ссылаетесь на шаблоны, хранящиеся в другом репозитории. Смотрите мой ответ и читайте внимательно Справочник по использованию шаблона.

Rui Jarimba 09.07.2024 16:13

Я не вижу подробностей о ваших заданиях, то есть о том, как вы устанавливаете пути к своим файлам или папкам. По очевидным причинам (см. мой предыдущий комментарий) вы всегда должны использовать пути в сочетании с предопределенными переменными , такими как $(System.DefaultWorkingDirectory)/path/to/my/folder, вместо жестко закодированных путей, поскольку они могут меняться от агента к агенту. Никогда, никогда не используйте жестко запрограммированные пути, такие как \\\server1\DevOpsAgent\_work\1\b\ .

Rui Jarimba 09.07.2024 16:30

Вы выполняете несколько этапов и заданий, каждое задание представляет собой новый сеанс для агента. Агент автоматически назначит папку, например _work\1, _work\2, в качестве рабочего пространства для ваших различных заданий, вы не можете контролировать назначенную папку. Если вы хотите, чтобы задания использовали одно и то же рабочее пространство, вам следует объединить задачи в одно задание. Или снова оформите заказ/используйте артефакт в новом задании, чтобы получить код. Пожалуйста, проверьте ответ @jessehouwing ниже.

wade zhou - MSFT 09.07.2024 17:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
100
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

При использовании шаблонов YAML создайте другой репозиторий:

  1. Используйте спецификацию resources, чтобы указать расположение репозитория шаблонов.
  2. Обратитесь к репозиторию шаблонов, используя @ и имя, которое вы ему дали resources.

Пример:

resources:
  repositories:
    - repository: mytemplates # <------------- repository name/alias
      type: github
      name: Contoso/BuildTemplates

jobs:
  - template: common.yml@mytemplates # Reference a YAML template in repository mytemplates

Итак, в вашем случае вместо /Base-pipeline.yml попробуйте использовать /Base-pipeline.yml@YAML:

resources:
  repositories:
    # ...

    - repository: YAML # <------------- repository name/alias
      type: git
      name: YAML-Automation
      ref: main
      trigger:
        - none

extends:
  template: /Base-pipeline.yml@YAML # Reference a YAML template in repository YAML
  parameters:
    productName: FOO

Дополнительную информацию см. в Справочнике по использованию шаблонов.

Спасибо! Сделано — заменил каждый .yml на .yml@YAML. К сожалению, проблема все та же.

HaraldJ 09.07.2024 16:20

@HaraldJ подожди, что ты имеешь в виду под каждым .yml файлом? Это следует делать только в FOO-pipeline.yml, чтобы ссылаться на шаблоны из других репозиториев. Репозиторий YAML-Automation — это тот, который содержит общие шаблоны, верно? Или вы также используете шаблоны из других репозиториев?

Rui Jarimba 09.07.2024 16:24

Только что заметил, что на обоих агентах проверка создает пустой YAML-Automation файл (name: репозитория и каталог YAML (- repository: YAML) со всеми YML-файлами. Если я правильно понимаю документацию, команда проверки использует имя репо, а не имя репо: поле. Может ли это быть связано с проблемой?

HaraldJ 09.07.2024 16:45
the checkout command uses the repo name — правильный синтаксис будет checkout: YAML. Но вам не нужно явно использовать задачу оформления заказа для использования шаблонов YAML, ЕСЛИ вы не используете другие файлы, такие как json, xml и т. д. Попробуйте сначала удалить задачу checkout.
Rui Jarimba 09.07.2024 16:50

Рабочие места назначаются агентам без каких-либо предположений. Ваша задача — обеспечить наличие всего необходимого для начала работы. Агентом может быть другая машина, каждый раз это может быть совершенно новая виртуальная машина (как в случае с размещенными агентами), и каждый раз это может быть другая рабочая папка на агенте.

Таким образом, либо ваш рабочий процесс должен загружать и скачивать артефакты конвейера между заданиями, либо проверять репозиторий в начале каждого задания. Если вы хотите убедиться, что все ваши файлы находятся на месте, не разбивайте рабочий процесс на несколько заданий, а просто запустите все, начиная с первого.

В своем конвейере всегда ссылайтесь на предварительно заполненные известные переменные: $(Build.SourcesDirectory) или $(Pipeline.Workspace), они всегда должны указывать на правильный каталог.

Используйте опубликовать: и загрузить:, чтобы опубликовать результаты предыдущего задания и загрузить их снова из более позднего.

Спасибо, @jessehouwing. Весь рабочий процесс со многими заданиями, использующими один и тот же каталог агента, работал отлично, пока я не поместил что-нибудь YAML в отдельный репозиторий Git. Сейчас и $(Build.SourcesDirectory), и $(Pipeline.Workspace) меняются от работы к работе, и я не понимаю почему. Возможно, придется вернуться к использованию YAML в репозиториях кода.

HaraldJ 10.07.2024 09:13
Ответ принят как подходящий

Как упоминал @jessehouwing, Джобса назначают агентам без каких-либо предположений.

Поскольку вы используете On-Prem DevOps server и имеете разные ресурсы репозитория (FOO, YAML). Проверено на моей стороне: если у вас есть разные проверки репозиториев в разных заданиях в одном агенте, он может использовать другую папку (_work\1, _work\2) в качестве Рабочее пространство.

Если вы хотите получить рабочий каталог с предыдущих работ, one possible workaround — это set variable на предыдущем этапе и перейти на следующий этап. Обратите внимание, что это не меняет default working directory на новом этапе, а переходит в каталог на предыдущем этапе для таких задач, как powershell, задачи bash..

Например, в jobs на этапе Build_without_analysis установите переменную:

    - powershell: echo "##vso[task.setvariable variable=directory;isOutput=true]$(Build.SourcesDirectory)"
      name: setvarStep

На зависимом этапе Test_All получите переменную:

    variables:
       myVarfromStageA: $[ stageDependencies.Build_without_analysis.jobBuildAll.outputs['setvarStep.directory'] ]

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

Вы можете проверить документ об использовании переменной.

Вот это интересная идея, попробую!!! Но я до сих пор не понимаю, почему все задания используют один и тот же каталог, если весь YAML является частью репозитория продукта.

HaraldJ 10.07.2024 10:36

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

wade zhou - MSFT 10.07.2024 10:50

Это полезная опция, спасибо! Это работает, но, похоже, между этапами требуется dependsOn:. Прямо сейчас я подумываю об изменении своего рабочего процесса, сделав модульные тесты и статический анализ кода частью реальных заданий сборки. Тогда у меня будут только артефакты для публикации/загрузки для следующего этапа, и не имеет значения, изменится ли рабочий каталог.

HaraldJ 15.07.2024 17:39

Спасибо @HaraldJ. Рад знать, что это помогает! Да, для передачи переменных требуется зависимость. Если у вас есть какие-либо вопросы, не стесняйтесь поднимать новый билет и всегда рады помочь. Счастливый день! :)

wade zhou - MSFT 16.07.2024 08:00

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