Automatyczny deployment z każdego brancha

Continuous deployment (CD) is a software engineering approach in which software functionalities are delivered frequently through automated deployments.

Continuous deployment ?

Jednym z ‘ostatnich’ trendów w świecie IT (dokładniej w części związanej z DevOps) jest continuous deployment i continuous delivery. Google Trends dość dobrze nam to obrazuje:

Proces dostosowania projektu do tej metodyki wymaga zmian związanych z samym kodem, jak i z organizacją pracy. Bardzo ważnym etapem jest automatyzacja i uproszczenie etapów dostarczania oprogramowania. Chciałbym dziś pokazać jak w prosty sposób skonfigurować i uruchomić automatyczne deployowanie aplikacji napisanej za pomocą Vue CLI.

Jednym z etapów procesu wytwarzania oprogramowania jest review kodu. Podczas tego etapu osoba, która nie jest autorem kodu, przegląda go i sprawdza, czy w kodzie nie występują błędy. Podczas takiego procesu, zwłaszcza kiedy tworzymy aplikację webową, bardzo przydatne może być uruchomienie nowej wersji aplikacji by zobaczyć jak ona działa i wygląda.

Oczywiście można pobrać kod, który został dodany do pull requesta i samemu go uruchomić, ale bardzo często uruchamianie aplikacji nie należy do procesów trywialnych (może się okazać np. że potrzebujemy uruchomić jakieś inne serwisy). Dlatego najlepiej jest ten proces całkowicie zautomatyzować. Dzięki temu każdy branch będzie posiadał adres, pod którym będzie dostępna jego zbudowana i działająca wersja.

Life

Proces automatyzacji jest bardzo mocno związany z narzędziami, z których używamy do procesu testowania i budowania naszej aplikacji. Ja w poniższym przykładzie postanowiłem użyć gitlaba i amazonowego s3. Oczywiście można zastąpić te elementy innymi usługami. Jakiekolwiek narzędzie CI jak travis, jenkins może zastąpić Ci gitlaba. Zamiast S3 możesz użyć dowolnego hostingu (polecam github pages z których można korzystać za darmo)

Nasz proces będzie wyglądał następująco:

  • Developer tworzy nowy branch lokalnie i dokonuje w nim zmian w kodzie.
  • W momencie, kiedy nowy branch zostaje ‘wypchniety’ do naszego repozytorium nasz pipeline zaczyna działać. Pipeline zajmie się budową i deploymentem aktualnej wersji do s3.
  • Podczas procesu review, po każdej aktualizacji naszego brancha (albo pull requesta) nowa wersja zostanie automatycznie dodana. Stara wersje nadal będą istnieć.
  • W momencie, kiedy branch zostanie usunięty lub zmergowany do mastera nasz pipeline usunie nie potrzebną już wersje testową.

Konfiguracja AWS

Stworzenie nowego bucketa

Pierwszym krokiem, będzie utworzenie miejsca, gdzie będziemy ‘wrzucać’ nowe wersje naszej aplikacji. Ponieważ moiją aplikacją jest prosta aplikacja, która została zbudowana za pomocą VueCli możemy do tego użyć s3. Jeżeli nie wiesz, czym jest Amazon S3 (Amazon Simple Storage Service) to w tym momencie wystarczy, żebyś wiedział, że jest to prosta usługa pozwalająca trzymać pliki w chmurze. Ma ona bardzo prosty w obsłudze interfejs WWW, który umożliwia użytkownikom przechowywanie danych i zarządzanie nimi. Ilość przechowywanych danych jest teoretycznie nielimitowana. Koniecznie musisz zdawać sobie jednak sprawę z tego, że wszystkie pliki będą publicznie dostępne. Będzie można przejrzeć każdy plik, który zostanie dodany do S3. Jeżeli posiadasz w swoim kodzie jakieś ‘sekrety’ nie używaj s3 do hostowania swojej aplikacji!

Zacznijmy od stworzenia nowego ‘bucketa’. Bucket to nic innego jak miejsce, gdzie nasza aplikacja będzie trzymana. Nazwa bucketa zdecyduje o tym, jak wygląda adres, pod którym nasza aplikacja będzie dostępna. Pamiętaj, że jeżeli chcesz użyć innej domeny będziesz musiał nazwać swój bucket dokładnie tak samo, jak będzie się nazywać domena. W innym przypadku będziesz miał problem, jeżeli będziesz chciał użyć do tego Route53 (jest to inna usługa aws, która odpowiada za dns). Samo stworzenie bucketa możemy zrobić pod tym linkiem. Wystarczy kliknąć ‘Create new bucket’ i wpisać jego nazwę. Nazwa bucketa musi być dostępna globalnie (jest to związane z tym, jak działa S3)

new bucket

Finala wersja naszego bucketa powinna wyglądać następująco:

final configuration bucket

Teraz musimy zrobić jeszcze jedną rzecz - musimy włączyć opcje, dzięki której będziemy mogli hostować nasze pliki. Jest to bardzo proste i sprowadza się tylko do wskazania pliku, który ma być pokazywany domyślnie (index.html). Opcje możemy znaleźć pod zakładką ‘Properties’

static web

Teraz jest dobry moment by dodać policy dla naszego bucketa. Chcielibyśmy żeby był on read-only dla każdej osoby. Nasze policy powinno wyglądać następująco:

Dodanie nowego użytkownika

Drugim krokiem, jest stworzenie użytkownika. Będzie to użytkownik, który zostanie użyty do przeprowadzania operacji na s3. Ustawimy mu odpowiednie prawa dostępu, które pozwolą mu zarządzać naszym bucketem. Będzie on dodawał pliki i je usuwał, kiedy staną się one niepotrzebne. Nowy użytkownik musi mieć policy które wygląda następująco: Zwróć uwagę na linie 9. Należy ją zmienić by pasowała, do której nazwy użyłeś jako nazwa swojego bucketa.

Ostatnią rzeczą którą należy zrobić jest pobranie kluczy dostępowych. Są one dostępne pod zakładką ”security credentials”. Pamiętaj że możesz je zobaczyć tylko raz. Będziemy ich potrzebować podczas konfigurowania naszego gitlaba.

security credentials

Konfiguracja gitlaba

Proces przygotowania naszego pipeline jest prostszy. Jedyną rzeczą którą musimy zrobić to skopiować ten plik i zapisać go jako .gitlab-ci.yml

Musimy pamiętać by dodać nasze security credentials do ustawień CI/CD w ustawieniach gitlaba.

security credentials

Omówmy teraz najważniejsze elementy tego pliku.

Docker

Gitlab pipelines używają obrazu dockerowego, który pomaga nam skonfigurować środowisko potrzebne w procesie testowania/budowania aplikacji. Warto zwrócić uwagę, że w poszczególne stage mogą mieć własną wersję dockera (linia 31). Jest to o tyle przydatne, że podczas budowania aplikacji będziemy potrzebować elementów związanych z nodem, ale podczas deployowania będziemy potrzebowali obrazu, który posiada zainstalowanego pythona. Jest on nam potrzebny, ponieważ będziemy korzystać z awscli którego użyjemy do skopiowania naszych plików na zdalną usługę s3. Dzięki tej jednej linijce w ciągu parę minut po dodaniu naszych zmian do repozytorium możemy je przetestować w działającym środowisku.

Review deployment i Deployment

Główna magia zaczyna się dziać w sekcji deploy_review. W tym stagu nasza aplikacja (która została zbudowana w kroku build) zostanie dodana do s3. Spójrzmy na komendę która kopiuje pliki.

aws s3 cp dist s3://${BUCKET_NAME}/${CI_COMMIT_REF_SLUG}/${CI_COMMIT_SHA} –recursive

Nasze zmienne to odpowiednio

  • ${BUCKET_NAME} to nazwa bucketa

  • ${CI_COMMIT_REF_SLUG} to nazwa aktualnego brancha

  • ${CI_COMMIT_SHA} to hash aktualnego heada.

Adresem pod którym nasza aplikacja będzie coś podobnego do:

https://test5555.s3-website.us-east2.amazonaws.com/fix_123/${CI_COMMIT_SHA}

Dla brancha master mamy bardzo podobne zachowanie. Tyle że zamiast nazwy brancha pliki zostaną skopiowane pod głowny adres (np. https://test5555.s3-website.us-east2.amazonaws.com).

Po procesie review, kiedy branch zostanie zmergowany, albo odrzucony chcielibyśmy żeby nasza aplikacja została również usunięta z s3. Odpowiada za to kod pomiędzy liniami 48-59.

Konfiguracja aplikacji

Należy pamiętać też o jednej rzeczy. Ponieważ nasza aplikacja będzie dostępna pod różnym adresem, należy uwzględnić to w procesie budowania. Służy do tego zmienna VUE_APP_ROUTER_BASE. Definiuje ona adres pod którym będzie nasza aplikacja dostępna. Kiedy budujemy wersje z brancha, należy ustawić ją na nazwę brancha.

Podsumowanie

Jak mogliśmy się przekonać konfigurowanie automatycznego deploymentu naszej testowej wersji jest bardzo proste i sprowadza się tylko do poprawnego skonfigurowania naszej usługi do hostowania plików i dodania .gitlab-ci do naszego projektu. Takie testowe wersje mogą służyć do sprawdzenia aplikacji podczas review, ale równie dobrze może to być pierwszy krok do stworzenia testów integracyjnych, które będą uruchamiane na naszym kodzie.