Я построил конвейер, который использует несколько репозиториев в моем проекте.
Все они объявлены в блоке ресурсов и на них ссылаются теги, используя:ref: refs/tags/$(variableName)
и это именно то, чего я хочу достичь.
Проблема, с которой я столкнулся, связана с одним репозиторием, из которого я хочу загрузить кучу шаблонов в свой основной конвейер. По этой причине всякий раз, когда я вызываю шаблон, я использую в нем имя репозитория:- template: templateName.yml@myRepoForTemplates
Когда все выглядит так, как описано выше, я получаю следующую ошибку:
/azure-pipelines.yml: Could not get the latest source version for repository myRepoForTemplates hosted on Azure Repos using ref refs/tags/$(variableName)
.
Когда я изменил способ ссылки на переменную на «параметр шаблона», следующим образом:
ref: refs/tags/${{ variables.variableName }}
, ошибка тоже изменилась:
/azure-pipelines.yml: Could not get the latest source version for repository myRepoForTemplates hosted on Azure Repos using ref refs/tags/
.
Изменение сообщения об ошибке заставляет меня думать, что переменная воспринимается как литерал, когда репозиторий используется для вызовов шаблонов. Самое интересное, что если я не использую переменную в объявлении репо и не предоставляю тег непосредственно там, все работает правильно.
Это ошибка DevOps? Есть ли способ преодолеть это?
Я был бы более чем благодарен за вашу помощь. Ваше здоровье
Обновлено: @Bright Ran-MSFT ниже вы можете найти код yaml:
yml-config/variables.yml
variables:
serviceConnectionName: '#myConn#'
subscription-id: '#mySubId'
destroyPlan: 'false'
cicd-templates-version: '0.0.1'
tf-modules-version: '0.0.1'
tf-templates-version: '0.0.1'
tf-bin-version: '1.5.7'
azure-pipelines.yml
trigger:
- none
variables:
- template: yml-config/variables.yml
resources:
repositories:
- repository: tf-templates
type: git
name: myProject/tf-templates
ref: refs/tags/$(tf-templates-version)
- repository: tf-modules
type: git
name: myProject/tf-modules
ref: refs/tags/$(tf-modules-version)
- repository: cicd-templates
type: git
name: myProject/cicd-templates
ref: refs/tags/$(cicd-templates-version)
stages:
- template: yaml/tf-backend-setup.yml@cicd-templates
parameters:
serviceConnectionName: $(serviceConnectionName)
subId: $(subscription-id)
- ${{ if eq(variables.destroyPlan, 'false') }}:
- template: yaml/tf-execution.yml@cicd-templates
parameters:
serviceConnectionName: $(serviceConnectionName)
subId: $(subscription-id)
tfBinVersion: $(tf-bin-version)
env: 'base'
destroyPlan: $(destroyPlan)
- template: yaml/tf-execution.yml@cicd-templates
parameters:
serviceConnectionName: $(serviceConnectionName)
subId: $(subscription-id)
tfBinVersion: $(tf-bin-version)
env: 'prod'
destroyPlan: $(destroyPlan)
- template: yaml/tf-execution.yml@cicd-templates
parameters:
serviceConnectionName: $(serviceConnectionName)
subId: $(subscription-id)
tfBinVersion: $(tf-bin-version)
env: 'dev'
destroyPlan: $(destroyPlan)
- ${{ if eq(variables.destroyPlan, 'true') }}:
- template: yaml/tf-execution.yml@cicd-templates
parameters:
serviceConnectionName: $(serviceConnectionName)
subId: $(subscription-id)
tfBinVersion: $(tf-bin-version)
env: 'base'
destroyPlan: $(destroyPlan)
Два репозитория, содержащие код TF, работают правильно и проверяются на основе значений соответствующих переменных.
Пока я не вызываю шаблоны, используя синтаксис path@repo
(т. е. - template: yaml/tf-execution.yml@cicd-templates
), третий репозиторий тоже работает нормально.
Если я введу вызов path@repo
, я получу вышеупомянутые ошибки, как если бы значение ref обрабатывалось по-другому.
Заранее спасибо за вашу помощь!
Ресурс репозиториев расширяется во время компиляции, во время компиляции можно оценивать только статические переменные и параметры.
Итак, для вашего случая:
Если вы хотите установить значение ключа ref
через переменную конвейера, вам нужно установить статическую переменную, как показано ниже. Таким образом, конвейер всегда будет ссылаться на тег, указанный в статической переменной, пока вы не обновите его значение на новый тег в файле YAML.
# Define the static variable and explicitly set its value.
variables:
tagName: v1.2
resources:
repositories:
- repository: myRepoForTemplates
type: git
name: string
ref: refs/tags/$(tagName)
Если вы хотите динамически устанавливать значение tagName
при запуске конвейера, вы можете определить его как параметр, как показано ниже. Таким образом, когда вы запускаете конвейер вручную, вы можете указать значение параметра. В противном случае конвейер будет использовать значение по умолчанию.
# Define the parameter with default value.
parameters:
- name: tagName
type: string
default: v1.2
resources:
repositories:
- repository: myRepoForTemplates
type: git
name: string
ref: refs/tags/${{ parameters.tagName }}
Обновлено:
Проблема может заключаться в порядке оценки ресурсов, шаблонов и пользовательских переменных. Пользовательские переменные (как в variables.yml
, так и в azure-pipelines.yml
) можно расширить после ресурсов и шаблонов.
При раскрытии шаблонов система попытается расширить содержимое YAML-файлов шаблона из указанной ref
версии ресурса репозитория. Поскольку значения переменных не были расширены, выражение «$(tagName)
» или «${{ variables.tagName }}
» не может получить фактическое значение.
В вашем случае вы можете попробовать использовать параметры вместо переменных, чтобы установить ref
. Параметры могут быть расширены по приоритету во время компиляции. Итак, вам должно подойти следующее:
parameters:
- name: cicd-templates-version
type: string
default: '0.0.1'
resources:
repositories:
- repository: cicd-templates
type: git
name: myProject/cicd-templates
ref: refs/tags/${{ parameters.cicd-templates-version }}
stages:
- template: path/to/template.yml@cicd-templates
@BartP, пожалуйста, опубликуйте YAML вашего конвейера. И объясните, когда это работает, а когда нет?
Я добавил код и контекст в первое сообщение. Ваше здоровье!
Кажется, это работает, когда я переключаюсь со статических переменных на параметры шаблона, но проблема все еще сохраняется при использовании статических переменных.
Теперь это имеет смысл, поскольку переменные разрешаются позже в ходе цикла, но я все еще не понимаю, почему остальные репозитории проверяются правильно. В конце концов, я предоставил им эти значения таким же образом.
@BartP, "but I'm still clueless why the rest of the repos get checked out properly.
" Какие этапы или задания посмотреть в репозиториях?
tf-backend-setup.yml
и tf-execution.yml
(которые являются этапами ниже и содержат как минимум два задания) проверьте (по крайней мере, в одном из заданий): self, cicd-templates, tf-modules, tf-templates. Загадка, которую я не могу понять, заключается в том, почему ref
разрешается правильно, когда нет вызовов path@repo
и в тот момент, когда я их ввожу, ref
интерпретируется как литерал - $(variableName), похоже, больше не рассматривается как ссылка на переменную. `
@BartP, я обновил свой ответ выше, добавив дополнительную информацию (см. РЕДАКТИРОВАТЬ). Проверьте и попробуйте с ним.
Спасибо @Bright Ran-MSFT. Переход к параметрам шаблона полностью решил проблему. Большое спасибо! Поведение, которое мы здесь заметили в отношении правильного разрешения ref/tags/$(variableName)
при отсутствии вызова path@repo
и буквального понимания ref/tags/$(variableName)
при наличии вышеупомянутого вызова, остается интересным.
Я следую всем пунктам, которые вы упомянули. У меня есть только статические переменные. У меня есть три репозитория, все объявлены одинаково. Все работает, если я не вызываю шаблоны - если я это делаю (а делаю это только для одного из этих репозиториев), то начинают вылезать ошибки.