Niektórzy twierdzą, że lenistwo to paradoksalnie potęga cywilizacji, bo gdyby nie ludzie leniwi, nie byłoby tylu wynalazków. Czy faktycznie tak jest? Może to nie lenistwo jest źródłem rozwoju, a odwieczna chęć człowieka do podbicia i podporządkowania sobie całego świata? Może lenistwo jest tylko nagrodą, efektem ubocznym takiego podporządkowania? Jakkolwiek by nie było, zostawmy te rozważania i weźmy się lepiej za coś konkretnego! W naszym świecie takie podporządkowanie niewątpliwie możemy nazwać automatyzacją i o niej warto pomyśleć w pracy programisty.
Autorzy tekstu: SoftwareHut – diamentowy sponsor konkursu „Daj Się Poznać”, białostocka firma o dużych aspiracjach. Dla swoich Klientów są solidnym partnerem w dziedzinie szeroko rozumianych usług IT oraz outsourcingu specjalistów. Starają się łamać stereotypy związane ze sposobem postrzegania programistów, działać niestandardowo, jak tylko się da wspierać społeczności i ciekawe inicjatywy rodzące się w głowach prawdziwych pasjonatów! Swoją codzienną pracą „od kuchni” i „bez makijażu” dzielą się na Facebooku oraz Snapchacie. Są firmą budowaną wokół ludzi i dla ludzi.
Aktualnie starają się wystartować z projektem nowego firmowego bloga i, jak twierdzą, ten post jest pierwszym konkretnym krokiem zrobionym w tym kierunku ;)
Ten krótki tekst ma za zadanie pokazać jak szybko, minimalistycznie i skutecznie za pomocą Visual Studio Online oraz Azure zrealizować proces Continuous Deployment, który może stać się bardzo dobrą bazą do dalszego rozwoju CD. Zaczynamy!
VSO, Azure + Continuous Deployment
W największym skrócie działa to tak: gdy pojawia się Git pull request, kod jest automatycznie wystawiany na Azure Website pod adresem url zawierającym nazwę gałęzi/brancha. Aplikację można uruchomić, zobaczyć, przetestować… Po zamknięciu pull requesta wszystko zostaje posprzątane i usunięte. Voila! Szybko, minimalistycznie i skutecznie. Prześledźmy zatem co, gdzie i kiedy się dzieje.
Ale ale, co dokładnie chcemy osiągnąć? Załóżmy, że nasz workflow wygląda następująco:
- Programista dostaje Work Item np. “Task nr 4 – zarządzanie użytkownikami”.
- Ponieważ pracujemy z podejściem feature branching, tworzona jest gałąź o nazwie np. 4-users i programista zaczyna implementację.
- Implementacja zostaje zakończona i programista zgłasza pull request o merge gałęzi 4-users do gałęzi master.
- Po zgłoszeniu tego pull requesta, aplikacja web zostaje wystawiona jako Azure Website pod adresem np. nazwaprojektu-4-users.azurewbsites.net
- Pull request przechodzi code review innego programisty i zostaje oznaczony jako Approved.
- Dział QA testuje aplikację pod wystawionym adresem i oznacza pull request jako Rejected.
- Programista poprawia błędy, commituje zmiany, pushuje.
- Aplikacja ponownie zostaje automatycznie wystawiona.
- Dział QA testuje aplikację i oznacza pull request jako Approved.
- Pull request zostaje zmergowany do gałęzi master.
- Aplikacja spod adresu nazwaprojektu-4-users.azurewebsites.net oraz wszystko z nią związane (np. baza danych) zostaje usunięte.
Magia
Skupmy się zatem na dwóch punktach dotyczących automagicznego wystawiania i usuwania aplikacji. Potrzebna będzie do tego subskrypcja Azure, a pierwszym krokiem jest połączenie VSO z Azure.
W wybranym projekcie przechodzimy do ustawień (ikona w prawym górnym rogu).
Następnie wybieramy “New Service Endpoint” i kolejno “Azure Classic“.
Wybieramy uwierzytelnianie przez certyfikat. Aby pobrać plik z certyfikatem i resztą danych do wypełnienia klikamy link “publish settings file”
Teraz stwórzmy build aplikacji o nazwie PublishToAzure. W zakładce build klikamy znak plusa i wybieramy Visual Studio. Wybieramy gdzie są źródła naszego projektu i widzimy kroki naszego builda.
- Wyrzucamy wszystkie kroki oprócz “build solution”
- W kroku “build solution” w “msbuild arguments” dodajemy /v:q /m
- /v:q – to skrót od /verbosity:quiet , minimalizuje informacje, które wypisuje msbuild; potrafi to skrócić czas builda
- /m – jeżeli będzie to możliwe, msbuild będzie kompilować nasz projekt na kilku rdzeniach
- Dodajemy następny krok “AzurePowershell” i jako skrypt dodajemy poniższy kod.
#aby zaimportować odpowiednie moduły (VSO robi to za nas, ale potrzebne jest to żeby odpalić i przetestować skrypt w ISE ) Import-Module "C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Azure.psd1" Import-Module 'C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ResourceManager\AzureResourceManager\AzureResourceManager.psd1' #wczytanie zmiennych środowiskowych $branch = $Env:BUILD_SOURCEBRANCH write-host "building branch $branch" $project = $Env:SYSTEM_TEAMPROJECT $urlprefix = "$project-" $sources = $Env:BUILD_SOURCESDIRECTORY $dir = "$sources\src\" # wyciągniecie ze zmiennej branch właściwej nazwy gałęzi, bo jest tu ona podawana jako refs/costam/nazwabrancha if( $branch.LastIndexOf('/') -gt 0) { $branch = $branch.Substring($branch.LastIndexOf('/')+1) } # url ma postać nazwaprojektu-nazwabrancha $url = $urlprefix + $branch $dbName = $url # w nazwach baz danych niedozwolone jest korzystanie ze znaku myślnika $dbName = $dbName.Replace('-','_') # jeżeli strona już istnieje to usuń ją $website = Get-AzureWebsite -name $url if($website -ne $null) { Write-Host "Deleting website with url $url" Remove-AzureWebsite $url -Force } # stwórz nowy website o podanym urlu $website = New-AzureWebsite $url Write-Host "Creating website with url $url" try { #usuń bazę danych Write-Host "Attempt to remove database $dbName" Invoke-Sqlcmd -ServerInstance "$sqlServerName" "DROP DATABASE $dbName" -Username $login -Password $password -QueryTimeout 2000 } catch{} #przywróć backup try { $sql = " RESTORE DATABASE $dbName FROM DISK = 'c:\db\backups\backup.bak' WITH MOVE 'naszprojekt' TO 'c:\db$dbName.mdf', MOVE 'naszprojekt_log' TO 'c:\db$dbName.ldf', MOVE 'naszprojekt_dev_filestream' TO 'c:\db$dbName', NOUNLOAD, REPLACE, STATS = 10 GO "; Write-Host "Attempt to create database $dbName" Invoke-Sqlcmd -ServerInstance "$sqlServerName" $sql -Username $login -Password $password -QueryTimeout 2000 } catch{} #zbuduj paczkę do deploymentu #ważny parametr BuildingProject - przed publishem builduje projekt, bez tego następuje tylko skopiowanie plików &"C:\Program Files (x86)\MSBuild.0\Bin\msbuild.exe" "$dir\Project.Web\Web.csproj" /p:DeployOnBuild=true /p:VisualStudioVersion=14.0 /v:q /p:Configuration=Release /t:Package /p:BuildingProject=true # publish paczki z podmianą connection stringów Publish-AzureWebsiteProject -package "$dir\Project.Web\obj\Release\Package\Web.zip" -name $url -ConnectionString @{ "DBConnection" = "Data Source=$sqlServerName;Initial Catalog=$dbName;User Id=$login;Password=$password"; }
Nazewnictwo website w konwencji {nazwa_projektu}-{nazwa_brancha} ma taką zaletę, że podczas ręcznego zarządzania website’ami przez manage.windowsazure.com mamy je posortowane według projektów.
Następnym krokiem jest stworzenie kolejnego builda, tym razem takiego, który usunie aplikację z Azure. Nazwijmy go RemoveFromAzure. W tym buildzie obchodzi nas tylko krok “AzurePowershell“, a ważne są tu dwie linijki:
Remove-AzureWebsite $url -Force Invoke-Sqlcmd -ServerInstance "$sqlServerName" "DROP DATABASE $dbName" -Username $login -Password $password -QueryTimeout 2000
Ostatnim krokiem jest napisanie małej aplikacji web. VSO posiada mechanizm Web Hook, który przy wystąpieniu wybranego zdarzenia potrafi wysłać POST na podany przez nas url. W taki sposób możemy zintegrować VSO z naszym firmowym Slackiem, ale my wykorzystamy to w inny sposób.
Schemat działania naszej aplikacji.
- Programista tworzy pull request.
- Web Hook powiadamia naszą aplikację
- Nasza aplikacja w zależności od tego jaki jest status pull requesta (updated, closed czy abandoned)
- triggeruje build PublishToAzure
- triggeruje build RemoveFromAzure
Podsumowanie
Plusy takiego rozwiązania:
- nowe funkcje są gotowe do testowania najszybciej jak to możliwe
- zerowy czas poświęcony na wystawianie wersji aplikacji dla działu QA
- po skończonej pracy nad zadaniem wystawiona aplikacja zostaje usunięta
Minusy:
- wystawiane website są domyślnie tworzone w darmowym planie, który przewiduje ograniczone zasoby np. pamięci RAM
- można dodać krok builda “AzureResourceManager” i tam zmienić plan na np. “Basic”, wtedy miejmy już na uwadze, że wiąże się to z dodatkowymi kosztami
Powyższy tekst to tylko propozycja w jaki sposób można najprościej podejść do tematu Continuous Deployment. Pamiętajcie, że nieważne jest w jaki sposób to zrealizujecie, ważne jest, że spróbujecie to wdrożyć u siebie i dalej dostosowywać do swoich potrzeb. Wszystko po to, aby jak najwięcej czasu zostało nam na kodowanie, czyli to, co wszyscy lubimy najbardziej.
[…] okazji na blogu Maćka Aniserowicza ukazał się też nasz artykuł System. Web.HokusPokus czyli Continuous Deployment dla leniwych napisany przez Janka […]