Продовжуємо огляд чудової тулів для розробки під Windows і не тільки, Azure DevOps. Цього разу, намучившись зі змінними оточення, я вирішив винести весь досвід в одну статтю.
Починаючи від того, що для кожного середовища виконання вони мають різний синтаксис, закінчуючи відсутністю стандартної можливості перенесення змінних з однієї стадії пайплайну в іншу.
Обмовлюся, що основні приклади будуть на Release Pipelines, тому, що YAML туди ще не доїхав, а мені потрібна функціональність безлічі етапів та безлічі артефактів. Це, начебто, стало доступно у звичайних Pipelines, що практично вирівнювало їх за функціональністю. У Pipelines YAML допилили та додали до текстового подання, невелику графічну підказку з параметрами, які можна задати. Дуже зручно, не треба лізти у документацію по кожному модулю. Але це описуватиму в наступній статті, а поки що картинка самого нововведення.
Зберігання та використання
Почнемо з того, що в системі ми маємо змінні за замовчуванням. Вони починаються, залежно від походження, за словами Release, System, etc. Повний список (як виявилося, ні), доступний у
steps:
- bash: echo This script could use $SYSTEM_ACCESSTOKEN
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- powershell: Write-Host "This is a script that could use $env:SYSTEM_ACCESSTOKEN"
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
Якщо ви задаєте змінну на агенті, який виконує таск, це $(System.AccessToken). Якщо ви хочете використовувати її всередині powershell скрипт на тому ж агенті, це вже буде $env:SYSTEM_ACCESSTOKEN. Якщо ви, боронь боже, хочете використовувати цю змінну на якомусь віддаленому хості, використовуючи таск PowerShell on target machines, вам потрібно передати це через аргумент до скрипту, використовуючи
Ті ж закони не поширюються на ваші власні змінні, тут ви несете відповідальність за синтаксис. Задати змінні можна локально у кожному завданні.
Або глобально у сховищі змінних, а потім лінкувати їх зі сховища. Дуже зручно.
Бонусом до цього, якщо змінні дуже секретні, їх можна зберігати у хмарі Azure у сховищі під назвою Azure Vault, залінкувати Vault до проекту можна в Library.
Загалом зі змінними все зрозуміло, у pipelines їх ще можна задавати вручну на кожен запуск, у release такої функціональності немає. Подивитися, що ви передаєте в пайплайн, можна ще раз в логах ініціалізації агента, але врахуйте, вони там вже в перетвореному вигляді.
Динамічні змінні
Найцікавіше починається, коли ми хочемо отримати деяке значення в одному етапі та передати його в наступний.
Такої функціональності нам не завезли. Але наші руки не для нудьги і за допомогою гугла знайшли рішення. Слава богу, Azure DevOps має API, який нам дозволяє зробити трохи більше, ніж намалювали в інтерфейсі.
Отже, нам знадобиться виклик щодо оновлення глобальних змінних, який ми робитимемо прямо зсередини пайплайну. Адреса береться зі змінних оточення, тих самих про які немає жодного слова в документації, як згадувалося раніше. Ви можете їх самостійно задати або, що там, захардкодити, якщо лавочку прикриють.
$releaseurl = ('{0}{1}/_apis/release/releases/{2}?api-version=5.0' -f $($env:SYSTEM_TEAMFOUNDATIONSERVERURI), $($env:SYSTEM_TEAMPROJECTID), $($env:RELEASE_RELEASEID) )
Задаємо порожнє значення змінної, яку хочемо передати, ставимо Scope — Release
Наприклад робимо деякий рандомний генератор значень. Зверніть увагу на синтаксис оголошення змінної усередині цього етапу, такий функціонал завезли.
На наступному етапі ми передаємо змінну скрипту, так, прямо не можна, треба через аргумент.
Скрипт під спойлером
PowerShell
#Script requires stageVar variable in release variables set to Release scope
param ( [string] $expVar )
#region variables
$ReleaseVariableName = 'StageVar'
$releaseurl = ('{0}{1}/_apis/release/releases/{2}?api-version=5.0' -f $($env:SYSTEM_TEAMFOUNDATIONSERVERURI), $($env:SYSTEM_TEAMPROJECTID), $($env:RELEASE_RELEASEID) )
#endregion
#region Get Release Definition
Write-Host "URL: $releaseurl"
$Release = Invoke-RestMethod -Uri $releaseurl -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
#endregion
#region Output current Release Pipeline
Write-Output ('Release Pipeline variables output: {0}' -f $($Release.variables | ConvertTo-Json -Depth 10))
#endregion
#region Update StageVar with new value
$release.variables.($ReleaseVariableName).value = "$expVar"
#endregion
#region update release pipeline
Write-Output ('Updating Release Definition')
$json = @($release) | ConvertTo-Json -Depth 99
Invoke-RestMethod -Uri $releaseurl -Method Put -Body $json -ContentType "application/json" -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN" }
#endregion
#region Get updated Release Definition
Write-Output ('Get updated Release Definition')
Write-Host "URL: $releaseurl"
$Release = Invoke-RestMethod -Uri $releaseurl -Headers @{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
#endregion
#region Output Updated Release Pipeline
Write-Output ('Updated Release Pipeline variables output: {0}' -f $($Release.variables | ConvertTo-Json -Depth 10))
#endregion
Або
Удар
INPUT_VAR=$1
RELEASE_VAR=$2
echo Test ID: ${INPUT_VAR}
RELEASE_URL="${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECTID}/_apis/release/releases/${RELEASE_RELEASEID}?api-version=5.0"
echo release url: $RELEASE_URL
RELEASE_JSON=$(curl -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" $RELEASE_URL)
OUTPUT=`jq ''.variables.${RELEASE_VAR}.value' = '"${INPUT_VAR}"'' <<< $RELEASE_JSON`
curl -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" -H "Content-Type: application/json" -X PUT -d "$OUTPUT" $RELEASE_URL
У двох словах, наш скрипт бере на вході змінну myVar і використовуючи API кладе значення цієї змінної в stageVar. У наступному етапі, використовуючи синтаксис системних змінних, ми можемо її переглянути.
Приклад досить простий, але функціонал відкриває нам добрі можливості, у сумі з моєю минулою
У наступній статті, якщо буде потреба, розповім про YAML пайплайни, там досить багато цікавих нововведень останнім часом.
Джерело: habr.com