Ostatnio pisałam o podstawach Cake. Dzisiaj czas na nowy projekt wykorzystujący Cake do uruchamiania skryptów np. az-cli. Stworzyłam na GitHubie specjalne repozytorium, z którego możecie korzystać.
Jeszcze zanim zaczniemy, upewnijcie się, że macie zainstalowane Azure CLI oraz npm. Dodatkowo polecam też wtyczkę markdownlint do VSCode – przydaje się podczas pisania dokumentacji z użyciem składni markdown.
Struktura
Na początek opiszę strukturę repozytorium.

Starałam się odpowiednio pogrupować pliki dotyczące command-runners i commands (dla naszego przykładu commands-az.cake do uruchamiania skryptów az-cli).
Podstawowy plik, który będziemy uruchamiać, to deploy.ps1. Jest to powershellowy plik uruchamiający Cake. W jego logice jest zawarte pobieranie Cake i innych narzędzi z Nuget i uruchomienie skryptu deploy.cake z przekazaniem odpowiednich parametrów. Taki plik można wziąć z oficjalnego repozytorium Cake – należy tylko uważać na wersje. Aktualna wersja do uruchamiania Cake używa Invoke-Expression (końcówka pliku):
# Start Cake
Write-Host „Running build script…”
Invoke-Expression „& $CAKE_EXE_INVOCATION $($cakeArguments -join ” „)”
exit $LASTEXITCODE
Niestety ta wersja nie działała podczas przekazywania w parametrach zmiennych zawierających znaki specjalne. Żeby to naprawić można używać wcześniejszej wersji skryptu:
# Start Cake
Write-Host „Running build script…”
&$CAKE_EXE $cakeArguments
exit $LASTEXITCODE
Główny plik, w którym będziemy pisać logikę, to deploy.cake. To w nim tworzymy na starcie (w metodzie Setup()) nowe instancje CommandRunner dla az-cli oraz PowershellCommanRunner dla powershella. W tym pliku definiujemy też główne zadania (Task()), które będziemy uruchamiać. Domyślnie będzie zawsze brany Task(„Default-Az-Show-Version”), ale używając odpowiednich parametrów, można zmienić wywoływany task.
Popatrzmy na powershell-command-runner.cake, po którym dziedziczą wszystkie inne pliku runner.
public class PowershellCommandRunner
{
protected ICakeContext context;
protected bool globalExceptionOnError;
public PowershellCommandRunner(ICakeContext context,
bool globalExceptionOnError = true)
{
this.context = context;
this.globalExceptionOnError = globalExceptionOnError;
}
//...
}
W konstruktorze przekazujemy context, a także ustawiamy globalExceptionOnError (domyślnie na true). W skrócie – jest potrzebna taka „furtka”, żeby pozwolić skryptowi działać dalej pomimo warningu. Niestety az-cli czasami wyświetla warning pomimo sukcesu operacji. W domyślnym ustawieniu nasz skrypt się przerwie z powodu błędu. Dlatego dla konkretnych operacji można ustawić powyższą flagę na false, wtedy „połykamy błąd” i skrypt leci dalej. Oczywiście są również mankamenty takiego rozwiązania – gdy operacja się naprawdę wysypie, nasz skrypt będzie dalej wykonywał kolejne kroki.
Widzimy, że mamy 3 metody:
- Run<T>() pozwala na wywołanie skryptu i zdeserializowanie outputu jako konkretnego obiektu o typie T.
- Run() pozwala wywołać skrypt, bez zwracania outputu.
- RunCommand() zawiera już bezpośrednio logikę związaną z uruchomieniem skryptu Powershell z naszą komendą. W powyższym przykładzie mogłaby być prywatna.
Przypatrzmy się Command-Runner.cake.
public class CommandRunner : PowershellCommandRunner
{
private string toolName;
public CommandRunner(ICakeContext context,
string toolName,
bool globalExceptionOnError = true)
: base(context, globalExceptionOnError)
{
this.toolName = toolName;
}
//...
}
Dziedziczy on po PowershellCommandRunner. W konstruktorze przyjmuje 3 parametry: context, toolName i globalExceptionOnError ustawiony na true. Najważniejszy parametr to toolName – jest to odpowiednik nazwy narzędzia, którą chcemy wywołać. Dla az-cli jest to po prostu „az” (bo używamy go jako „az login”, gdzie „login” jest już konkretną komendą).
Dodatkowo utworzyłam również npm-command-runner.cake. Pozwala on na uruchamianie skryptów zainstalowanych przez npm.
public class NpmCommandRunner: CommandRunner
{
public NpmCommandRunner(ICakeContext context,
string commandName,
bool globalExceptionOnError = false)
: base(context,
context.MakeAbsolute(new FilePath($"./node_modules/.bin/{commandName}.cmd")).FullPath,
globalExceptionOnError)
{
}
}
Potrzebujemy przekazać mu w kontruktorze commandName, który będzie szukał odpowiedniego pliku {commandName}.cmd w folderze node_modules/.bin/.
W folderze commands możemy dodawać pliki command dla różnych narzędzi. W naszym przykładzie mamy tylko jeden plik commands-az.cake. Mamy w nim 3 taski:
Task("Az-Show-Version")
.Does(() => {
az.Run(a => {
a.Append("version");
});
});
Task("Login")
.Does(() => {
//exceptionOnError: false because of default warning
//"WARNING: You have logged in. Now let us find all
//the subscriptions to which you have access..."
az.Run(a => {
a.Append("login");
}, exceptionOnError: false);
});
Task("Set-Subscription")
.Does(() => {
az.Run(a => {
a.Append("account");
a.Append("set");
a.AppendSwitchQuoted("--subscription",
ReleaseVariable("subscription"));
});
});
- „Az-Show-Version” – do wyświetlania wersji az
- „Login” – do logowania się
- „Set-Subscription” – do ustawiania subskrypcji (po zalogowaniu)
Jak widać w ostatnim tasku, potrzebujemy pobrać zmienną subscription korzystając z ReleaseVariable.
ReleaseVariable
W celu definiowania zmiennych korzystam z paczki Cake.Deploy.Variables. Dzięki niej definiuję odrębne pliki ze zmiennymi dla różnych środowisk. W projekcie mamy domyślny plik variables-default.cake:
// example of basic variable file
ReleaseEnvironment("default")
.AddVariable("subscription",
x => Argument<string>("subscription"));
oraz dodatkowy plik dla środowiska dev variables-dev.cake:
// example of new variable file for other environment
ReleaseEnvironment("dev")
.IsBasedOn("default")
.AddVariable("env", "dev");
Uruchamianie
Jak uruchomić skrypty? Wystarczy uruchomiść skrypt powershell
./deploy.ps1
Wywoła on domyślny task Az-Show-Version. Jeśli chcemy wybrać inny task, wystarczy go podać w parametrze:
./deploy.ps1 -Target Az-Login
A jeśli chcemy wywołać task z przekazaniem dodatkowych zmiennych, możemy to zapisać tak:
./deploy.ps1 --env="dev" --subscription= '*****' -Target Az-Login-With-Set-Subscription
PS
Niedługo po napisaniu tego posta dowiedziałam się, że powstało coś takiego jak Cake.AzureCLI (z tego posta). Rozszerzenie do Cake, pozwalające bezpośrednio używać azure-cli w Cake. Ma swoje plusy i minusy, ale jeśli chcecie korzystać tylko z azure-cli i nie przeszkadza Wam uzależnienie od konkretnej jego wersji, to może warto rozważyć 🙂
Post powstał pod patronatem firmy, w której aktualnie pracuję: Objectivity.
Grafikę tytułową zaprojektował niezastąpiony zespół designu!
Podoba Ci się to, co tworzę? Chcesz dostawać informacje o:
– wydarzeniach, które organizuję lub wspieram (np. konferencje, meetupy, webinary)
– inicjatywach, które organizuję lub wspieram (np. GeekWeekWro, DevAdventCalendar)
– moich prelekcjach, kursach i szkoleniach
– wyróżnionych artykułach z mojego bloga
0% SPAMu, 100% informacji! Krótko i na temat.
Ciekawy artykuł 🙂
Pozdrawiam,
Dariusz Gruca
http://www.DariuszGruca.pl
PolubieniePolubione przez 1 osoba
Dziękuję!
PolubieniePolubienie