Kontynuujemy przegląd wspaniałego narzędzia do programowania w systemie Windows i nie tylko, Azure DevOps. Tym razem, zmagając się z zmiennymi środowiskowymi, postanowiłem podzielić się całym doświadczeniem w jednym artykule.
Zaczynając od tego, że dla każdego środowiska wykonawczego mają inny składnik, kończąc na braku standardowej możliwości przenoszenia zmiennych z jednego etapu pipeline'u do drugiego.
Powołam się na to, że główne przykłady będą dotyczące Release Pipelines, ponieważ YAML tam jeszcze nie dotarł, a ja potrzebuję funkcjonalności wielu etapów i wielu artefaktów. Jak się okazuje, to stało się dostępne w normalnych Pipeline'ach, co praktycznie wyrównało ich funkcjonalność. W Pipeline'ach YAML dopracowano i dodano do tekstowego przedstawienia, małą graficzną wskazówkę z parametrami, które można ustawić. Bardzo wygodne, nie trzeba zaglądać do dokumentacji dla każdego modułu. Ale to opiszę w następnym artykule, a póki co, oto obrazek z najnowszym udoskonaleniem.

Przechowywanie i użycie
Zacznijmy od tego, że w systemie mamy zmienne domyślne. Zaczynają się, w zależności od pochodzenia, od słów Release, System itd. Pełna lista ( jak się okazało, nie ma) dostępna jest w . Całą szaloną różnorodność składni ilustruje przykład z dokumentacji poniżej. Ta sama zmienna ma trzy przedstawienia, w zależności od tego, gdzie ją wywołujemy.
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)Jeżeli ustawisz zmienną na agencie, na którym wykonywane jest zadanie, to jest to $(System.AccessToken). Jeśli chcesz jej użyć wewnątrz skryptu PowerShell na tym samym agencie, będzie to już $env:SYSTEM_ACCESSTOKEN. Jeśli, nie daj Boże, chcesz użyć tej zmiennej na jakimś zdalnym hoście, korzystając z zadania PowerShell na maszynach docelowych, musisz przekazać to przez argument do skryptu, używając . W przypadku basha jest prościej, można po prostu przekazać wewnątrz, używając argumentu i składni $SYSTEM_ACCESSTOKEN.
Te same zasady nie rozciągają się na twoje własne zmienne, to już Ty odpowiadasz za składnię. Zmienne można ustawiać lokalnie w każdym zadaniu.

Lub globalnie w magazynie zmiennych, a następnie łączyć je z magazynu. Bardzo wygodne.

Dodatkowo, jeśli zmienne są wyjątkowo poufne, można je przechowywać w chmurze Azure w magazynie o nazwie Azure Vault, a Vault można połączyć z projektem w bibliotece.

Ogólnie rzecz biorąc, zmienne są zrozumiałe, w pipeline'ach można je również ustawiać ręcznie na każde uruchomienie, taka funkcjonalność nie jest dostępna w release. Można sprawdzić, co przekazujesz do pipeline'u w dziennikach inicjalizacji agenta, ale pamiętaj, że są już tam w przetworzonej postaci.

Zmienne dynamiczne
Najciekawsze zaczyna się, gdy chcemy uzyskać pewną wartość na jednym etapie i przekazać ją do następnego.

Takiej funkcjonalności nam nie dostarczono. Ale nasze ręce nie są do niczego innego i dzięki Google znaleźliśmy rozwiązanie. Na szczęście Azure DevOps ma API, które pozwala nam zrobić trochę więcej, niż to, co zostało nam przedstawione w interfejsie.
A więc będziemy potrzebować wywołania do aktualizacji globalnych zmiennych, które wykonamy bezpośrednio w pipeline. Adres pochodzi z zmiennych środowiskowych, tych samych, o których nie ma ani słowa w dokumentacji, jak wspomniano wcześniej. Możesz je ustawić samodzielnie lub, co tam, zakodować na stałe, jeśli to zostanie zamknięte.
$releaseurl = ('{0}{1}\/apis\/release\/releases\/{$2}?api-version=5.0' -f $($env:SYSTEM_TEAMFOUNDATIONSERVERURI), $($env:SYSTEM_TEAMPROJECTID), $($env:RELEASE_RELEASEID))Ustawiamy pustą wartość zmiennej, którą chcemy przekazać, ustawiamy Scope — Release

Na przykład tworzymy pewien losowy generator wartości. Zwróć uwagę na składnię deklaracji zmiennej w tym etapie, taka funkcjonalność została wprowadzona.

W następnym etapie przekazujemy zmienną do skryptu, tak, tak, bezpośrednio nie można, trzeba przez argument.

Skrypt w spoilerze
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))
#endregionLub
Bash
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_URLW dwóch słowach, nasz skrypt przyjmuje zmienną myVar i za pomocą API umieszcza wartość tej zmiennej w stageVar. W następnym etapie, używając składni zmiennych systemowych, możemy ją zobaczyć.

Przykład jest dość prosty, ale funkcjonalność otwiera przed nami dobre możliwości, w połączeniu z moją wcześniejszą , kiedy możemy stworzyć maszynę wirtualną na pierwszym etapie testów, wykonać z nią różne operacje, w tym równolegle kilka. A na końcu ją zniszczyć. Teraz nasze automatyczne testy uruchamiają się na nowych maszynach wirtualnych za każdym razem. Biorąc pod uwagę, że żyją one przez około 10 minut, koszt jest minimalny.
W następnym artykule, jeśli zajdzie taka potrzeba, opowiem o potokach YAML, w ostatnim czasie pojawiło się wiele interesujących nowości.
Źródło: habr.com
