У меня есть репозиторий Azure DevOps
, который я хочу заполнить несколькими (конвейерными) шаблонами.
Каждый файл шаблона представляет собой Azure Container App Job
.
При слиянии с производством я хотел бы, чтобы конвейер идентифицировал измененные шаблоны и запускал эти шаблоны. Затем шаблоны будут обновлены/добавлены Container App Jobs
в моем Container Environment
.
Если это невозможно сделать таким способом, какой способ будет лучше?
Для пояснения: у меня есть готовый контейнер, который я хочу запустить как несколько заданий приложений-контейнеров Azure с разными параметрами. Я не спрашиваю, как создать контейнер в реестре контейнеров.
Обновлять:
Обновление 2: Определение первого конвейера:
variables:
ubuntuversion: 'ubuntu-22.04'
trigger:
branches:
include:
- main
stages:
- stage: FindNewTemplates
jobs:
- job: FindNewTemplates
pool:
vmImage: $(ubuntuversion)
steps:
- checkout: self
fetchDepth: 0
- powershell: |
$token = "$(system.accesstoken)"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$prefix_url = "$(System.CollectionUri)"
$project = "$(System.TeamProject)"
$buildId = $(Build.BuildId)
$url = "${prefix_url}${project}/_apis/build/builds/${buildId}/changes?includeSourceChange=true&api-version=7.0"
$response=Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"}
$changesCount = $response.count
Write-Host "The count of commits associated with this build is $changesCount."
$modifiedFiles= git diff HEAD HEAD~$changesCount --name-only
echo $modifiedFiles
$modifiedFiles1 = @()
foreach ($file in $modifiedFiles)
{
if ($file -like 'acaj-definitions/*tes*.yaml')
{
echo $file
$modifiedFiles1= -join("$modifiedFiles1", ",", "$file")
}
}
$modifiedFiles1 = $modifiedFiles1.TrimStart(",")
echo $modifiedFiles1
$url = "${prefix_url}${project}/_apis/pipelines/14/runs?api-version=5.1-preview"
echo $url
$JSON = "
{
`"resources`": {
`"repositories`": {
`"self`": {
`"ref`": `"refs/heads/main`"
}
}
},
`"templateParameters`": {
`"files`":`"[$modifiedFiles1]`"
},
}"
$response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
echo $response
Определение второго конвейера:
parameters:
- name: files
type: object
variables:
ubuntuversion: 'ubuntu-22.04'
acaj_memory: 4
trigger: none
jobs:
- ${{ each file in parameters.files }}:
#- template: ${{file}}
# parameters:
# acaj_memory: $(acaj_memory)
- script: echo ${{file}}
Обновление 3: вывод ADO
Description : Run a PowerShell script on Linux, macOS, or Windows
Version : 2.239.1
Author : Microsoft Corporation
Help : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/powershell
==============================================================================
Generating script.
========================== Starting Command Output ===========================
/usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command . '/home/vsts/work/_temp/b5f286c2-1c7d-41b0-b89a-c064e9581e64.ps1'
The count of commits associated with this build is 19.
.azure-pipelines/01_identify_new_templates.yaml
.azure-pipelines/01_identify_new_templatesmine.yaml
.azure-pipelines/02_run_new_templates.yaml
acaj-definitions/intralinks/testtemplate.yaml
acaj-definitions/intralinks/testtemplate.yaml
acaj-definitions/intralinks/testtemplate.yaml
https://dev.azure.com/companyname/projectname/_apis/pipelines/14/runs?api-version=5.1-preview
{
"resources": {
"repositories": {
"self": {
"ref": "refs/heads/main"
}
}
},
"templateParameters": {
"files":"[acaj-definitions/intralinks/testtemplate.yaml]"
}
}
Invoke-RestMethod: /home/vsts/work/_temp/b5f286c2-1c7d-41b0-b89a-c064e9581e64.ps1:49
Line |
49 | $response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "B …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| { "$id": "1", "innerException": null, "message": "TF400898: An
| Internal Error Occurred. Activity Id:
| 647e4983-f3df-41eb-84e0-5d3b0f8bafaf.", "typeName":
| "System.NullReferenceException, mscorlib", "typeKey":
| "NullReferenceException", "errorCode": 0, "eventId": 0 }
##[error]PowerShell exited with code '1'.
Finishing: PowerShell
Боюсь, что не существует встроенной переменной, которая могла бы содержать информацию об измененных файлах.
хотелось бы, чтобы конвейер идентифицировал измененные шаблоны и запускал эти шаблоны
Судя по вашему описанию, вы используете шаблон в Pipeline для запуска заданий.
Нам нужно запустить скрипт, чтобы собрать измененные файлы и отправить их в конвейер, чтобы подтвердить, какие шаблоны запускать.
Поскольку шаблоны YAML будут расширяться во время компиляции, а запуск скрипта будет выполняться во время выполнения, нам необходимо создать два конвейера для достижения этого требования.
Вот пример:
Первый конвейер: используется Rest API и команда Git для сбора измененных файлов и отправки результата во второй конвейер.
Второй конвейер: используйте параметры типа объекта и каждое выражение для зацикливания измененных файлов для запуска шаблона.
parameters:
- name: files
type: object
jobs:
- ${{ each file in parameters.files }}:
- template: ${{file}}
Результат:
Трубопровод первый:
Трубопровод второй:
Обновлять:
Чтобы API-интерфейс Rest успешно запускал конвейер, необходимо предоставить разрешения на построение очередей двум учетным записям служб: учетной записи службы сборки коллекции проектов (имя организации) и службе сборки имени проекта (организация).
Нажмите «Управление параметрами безопасности» и установите разрешения.
Например:
Затем вы можете использовать следующий обновленный образец Pipeline One:
steps:
- checkout: self
fetchDepth: 0
- powershell: |
$token = "$(system.accesstoken)"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$prefix_url = "$(System.CollectionUri)"
$project = "$(System.TeamProject)"
$buildId = $(Build.BuildId)
$url = "${prefix_url}${project}/_apis/build/builds/${buildId}/changes?includeSourceChange=true&api-version=7.0"
$response=Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"}
$changesCount = $response.count
Write-Host "The count of commits associated with this build is $changesCount."
$modifiedFiles= git diff HEAD HEAD~$changesCount --name-only
echo $modifiedFiles
$modifiedFiles1 = @()
foreach ($file in $modifiedFiles)
{
if ($file -like 'tes*.yml')
{
echo $file
$modifiedFiles1= -join("$modifiedFiles1", ",", "$file")
}
}
$modifiedFiles1 = $modifiedFiles1.TrimStart(",")
echo $modifiedFiles1
$url = "${prefix_url}${project}/_apis/pipelines/{Pipeline Two ID}/runs?api-version=5.1-preview"
echo $url
$JSON = "
{
`"resources`": {
`"repositories`": {
`"self`": {
`"ref`": `"refs/heads/main`"
}
}
},
`"templateParameters`": {
`"files`":`"[$modifiedFiles1]`"
},
}"
$response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json
echo $response
Или вы можете создать полноценный PAT и использовать его в поле $token
.
Когда Rest Api заработает успешно, он вернет значение объекта json.
Например:
Обновление2:
Я проверил код YAML. Причиной проблемы является проблема с форматом YAML второго конвейера.
Вы можете использовать следующий формат:
parameters:
- name: files
type: object
jobs:
- ${{ each file in parameters.files }}:
- job:
steps:
- script: echo ${{file}}
@kiesel Можете ли вы проверить правильность путей к файлам в выводе PowerShell первого конвейера?
И вы можете проверить, правильно ли вы ввели идентификатор второго конвейера.
Файлы абсолютны, от корня папки до файлов. Идентификатор — это параметр ?definitionId=14
, который я вижу в браузере, верно? Итак, в моем случае я использовал 14 в первом конвейере.
Я только что повторил $response
и заметил, что он содержит javascript и тело. Я полагаю, это неправильно?
@kiesel Если вы используете конвейер YAML, вы должны увидеть pipelineId=1302
в браузере. Если возможно, можете поделиться скриншотами текущих настроек и результата?
Вот документация по Rest API: Learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/…
@kiesel Я могу воспроизвести твою проблему сейчас. Пожалуйста, подождите несколько минут. Я найду решение.
@kiesel Пожалуйста, проверьте обновление в ответе. Вам необходимо предоставить разрешения учетным записям служб или изменить использование PAT для аутентификации. Тогда он может работать так, как ожидалось. И вы можете попробовать использовать обновленный образец в обновленном ответе. Не стесняйтесь, дайте мне знать, если это сработает.
Я добавил запрошенные права, но вижу то же самое, что и раньше (может быть, правам нужно время для синхронизации?). В понедельник попробую использовать PAT. Я добавил фотографии в свой пост, чтобы показать, какие права были предоставлены.
@kiesel Права должны быть правильными. Пожалуйста, используйте обновленный код в моем ответе. Я думаю, что это внесет некоторые изменения
@kiesel Есть ли какая-нибудь информация об этом билете? Не могли бы вы попробовать использовать код YAML в обновленном ответе, чтобы обновить свой конвейер? Не стесняйтесь, дайте мне знать, если это сработает для вас.
На самом деле я просто тестирую это. С правами разобрался, но теперь выдает вот такую ошибку: { "$id": "1", "innerException": null, "message": "TF400898: An | Internal Error Occurred. Activity Id: | 0f5b2a0b-9ac8-4219-a775-480d8871df26.", "typeName": | "System.NullReferenceException, mscorlib", "typeKey": | "NullReferenceException", "errorCode": 0, "eventId": 0 }
при звонке второму Invoke-RestMethod
@kiesel Если возможно, не могли бы вы обновить вопрос и поделиться определением двух конвейеров? Вы можете скрыть информацию об организации и PAT.
Обновлено. Спасибо!
@kiesel Позвольте мне проверить это. Я обновлю как можно скорее.
@kiesel Пожалуйста, проверьте обновление2 в ответе. Вы можете изменить второй конвейер с помощью примера YAML.
Спасибо! К сожалению, я все еще наблюдаю ту же проблему с исправленным кодом. Я убедился (в ADO), что конвейер был обновлен перед повторной попыткой.
@kiesel, можешь ли ты поделиться результатами выполнения задачи powershell в журнале конвейера?
Или вы можете попытаться создать новый конвейер с существующим кодом YAML и протестировать его еще раз.
Я добавил вывод в первый пост (добавил несколько эхо). Попробую воссоздать конвейеры.
@kiesel Спасибо, что поделились. Я проверил журнал конвейера и могу подтвердить, что URL-адрес и тело запроса верны. Это должно успешно запустить конвейер. Попробуйте запустить его в новом конвейере, а также попробуйте использовать агент Windows для запуска сценария Powershell.
Оказывается, службе сборки проекта также требуется разрешение Edit queue build configuration
, в противном случае (я предполагаю) параметр files
остается пустым, что объясняет нулевое исключение. Большое спасибо за Вашу помощь!!!
@kiesel Хорошая мысль! Рад узнать, что теперь это может работать.
Спасибо за помощь! При реализации я получил ошибку:
parameter -Headers@ doesn't exist.
Предполагая, что это опечатка, я добавил пробел между-Headers
и@
, в результате чего первый конвейер завершается правильно, но второй конвейер не вызывается.