Czujny Pan Jenkins, czyli trochę o Continuous Integration.

Michał
Michał
DevOps Engineer

Ten, kto nie robi błędów, zwykle nie robi nic. Błędy  się więc zdarzają — rzecz jednak w tym, aby szybko i skutecznie je eliminować i wyciągać wnioski. Skuteczną formą weryfikowania błędów jest doskonale programistom znana ciągła integracja (ang. Continuous integration). Jednym z popularniejszych narzędzi CI/CD jest Jenkins, który pozwala na zautomatyzowanie procesu budowania, np. uruchomia test, buduje projekt albo zbiera informacje o przeprowadzonych operacjach poprzez skonfigurowanie zadań (w programie nazywane “jobs”).

Czym jest ciągła integracja (CI)?

Jest to proces, który rozpoczyna się poprzez zamieszczenie zmian fragmentów kodu w repozytorium. Następnie taki kod jest budowany, a dalej uruchamiane są automatyczne kompilacje i testy. W przypadku błędu programista szybko dostaje informację zwrotną. Gdy integracja odbywa się często, najlepiej kilka razy dziennie, ogranicza to ilość błędów i koszt związany z ich odnalezieniem. Wpływa również na poprawę jakości oprogramowania oraz skrócenie czasu potrzebnego na weryfikację i wydanie nowych aktualizacji oprogramowania.

Do procesu CI wykorzystywany jest Jenkins, który np. automatycznie pobiera kod z repozytorium (poprzez ustawiony np. w Bitbucket’cie webhook, który go o tym informuje) i przystępuje do zadanego zestawu czynności. Może to być np. kompilacja, odpalenie testów jednostkowych, wrzucenie zmian na środowisko testowe. Zadania można ustawić w różny, odpowiedni dla nas sposób.

W przypadku aplikacji opartych o nowoczesne frameworki PHP, biblioteki frontendowe jak React, pierwszym zadaniem będzie odpalenie Composer’a w celu zaktualizowania paczek, uruchomienie webpacka w celu kompilacji plików JS i CSS. Następnie Jenkins uruchomi niezbędne testy jednostkowe, które pozwalają przetestować poszczególne atomowe cześci aplikacji i wykryć błędy we wczesnej fazie. Dodatkowo Jenkins może uruchomić statyczną analizę kodu i odpalić testy automatyczne (np. w Selenium), które pozwolą zminimalizować konieczność każdorazowych manualnych testów, czy zajmujących sporo czasu testów regresyjnych i zwyczajnie zautomatyzować cały proces testowania webowej aplikacji. Jeśli używasz Docker’a, możesz również użyć Jenkinsa do automatycznego uploadu obrazów kontenerów — warto w tym celu skorzystać np. z Amazon ECR.

Informuj  i wypuszczaj zmiany tak szybko jak to możliwe!

Najistotniejszą, fundamentalną cechą ciągłej integracji jest przekazywanie informacji tak szybko, jak to możliwe. Na to możemy liczyć. Każde odchylenie od normy wykryte w testach jest odpowiednio komunikowane poprzez wysłanie wiadomości na zintegrowaną skrzynkę mailową zespołu lub poprzez komunikator tekstowy (np. Slack). Jenkins może też rozmawiać z programistami na Twitterze, Skypie lub odzywać się przez aplikację na smartfonach 🙂

Mechanizm powiadomień niezwykle ułatwia pracę, bo dzięki niemu niemal natychmiast wiemy, który kod jest w porządku, a który nie funkcjonuje prawidłowo i wymaga korekty. CI dokładnie sprawdza poprawność kodu dostarczonego przez programistę w każdej nowej wersji wrzuconej do repozytorium. Jenkins powie też, w której linijce pliku znajduje się błąd i kto z naszego teamu jest za niego odpowiedzialny. [nasz post na blogu o systemie „kar” i „nagród” dla członków teamu niedługo się pojawi].

Jenkins - przykładowy widok
Główny widok listy zadań w Jenkinsie – widzimy status ostatniego builda i dodatkowe informacje (czas trwania, itp.)

Jenkins powiadomi nas również w sytuacji gdy problem zostanie rozwiązany. Odpowiednia informacja dotrze do każdego programisty zainteresowanego projektem, a dzięki temu cały zespół zna aktualny stan prac i łatwiej jest rozplanować zadania. Po udanym procesie build’a możemy wreszcie wrzucić nasze zmiany na odpowiednie środowisko – podczas codziennej pracy zmiany lądują na środowisku „dev”, gdzie programiści i testerzy mogą przetestować daną funkcjonalność. Jenkins odpowiada później również za wypuszczanie tych zmian na środowisko „stage”, jak również na produkcję. Zaoszczędzisz w ten sposób sporo czasu, a releasy staną się łatwiejsze, bardziej pewne, dzięki czemu będą robione częściej.

Statyczna analiza kodu

Kolejna przykładową rzeczą którą potrafi Jenkins jest przeprowadzenie statycznej analizy kodu – analizujemy poprawności składni, możemy znaleźć niebezpieczne i nieaktualne funkcje, wycieki pamięci, przepełnienie bufora, SQL Injections, wykryć niepotrzebne powtórzenia kodu czy nieużywane fragmenty. Pozwala to zwiększyć wydajność, wykryć wąskie gardła czy niewydajne konstrukcje. Dodatkowo możemy automatycznie sprawdzić, czy programista faktycznie zrobił w kodzie odpowiednie opisy do klas i metod (tzw. doc) – gdyby programiści o tym zapominali, nie można by było wygenerować dokumentacji dla projektu. Trzeba jednak pamiętać, że Jenkins nie jest związany z samym pisaniem dokumentacji, a tylko z jej generowaniem i zautomatyzowaniem tego procesu.

Budowanie CD z Jenkins

Ciągłe dostarczanie pozwala programistom zautomatyzować testowanie wykraczające poza testy jednostkowe, dzięki czemu mogą weryfikować aktualizacje aplikacji w wielu wymiarach przed wdrożeniem ich u klientów.

Jednym z kluczowych elementów Continuous Delivery jest potok wdrażania (pipelines). Modeluje on proces wydawania oprogramowania, definiując serwery i środowiska, na których zostaną wdrożone kompilacje, a także ręczne i automatyczne zatwierdzanie wymagane na każdym etapie procesu.

Różne aplikacje mogą używać różnych potoków lub ta sama aplikacja może używać różnych potoków dla różnych wydań. Wszystko zależy od kontekstu i potrzeb oprogramowania.

Jak Jenkins pomaga w ciągłej dostawie?

Jenkins pierwotnie został zaprojektowany, aby być serwerem do automatyzacji kompilacji (open source automation server). Z racji faktu, że skrypt kompilacji może być po prostu dowolnym skryptem, Jenkins może być używany do wielu operacji… od uruchamiania potoku CD do nawet skryptów PowerShell.

Choć Jenkins nie jest bezpośrednio odpowiedzialny za ciągłe dostarczanie, jednak za pomocą preinstalowanej wtyczki Pipelines (pierwotnie nazywanej przepływami pracy) Jenkins wraz z dedykowanymi narzędziami CD może w tym bardzo pomóc. Kiedy używasz dowolnego narzędzia do wdrażania z Jenkinsem, otrzymujesz całą wartość, jaką obecnie oferuje Jenkins jak automatyzacja kompilacji/CI, testowanie i/lub uruchamianie dowolnych skryptów oraz elastyczny proces wydawania (continous deployment). Ma to również dodatkową zaletę, że jest bardziej dostępny dla członków zespołu, którzy nie są ekspertami Jenkinsa.

Do czego mogę użyć Jenkinsa?

C#, NodeJS, PHP, Java? Bez znaczenia — Jenkins jest dla wszystkich. Aplikacja jest wieloplatformowa, więc można ją zainstalować na Windowsie, Ubuntu, MacOS. Dodatkowo, mimo iż Jenkins jest napisany w Javie, nadaje się do wszystkich projektów, nawet tych tworzonych w C#/.NET. Jenkins wspomaga automatyzację niektórych procedur związanych z budowaniem, testowaniem i dokumentowaniem kodu. No i, może najważniejsze, znacząco ułatwia wypuszczanie wszelkich zmian na środowiska (dev, stage, production). Użycie go w Waszych projektach zdecydowanie da wiele benefitów i pozwoli zaoszczędzić sporo czasu. Czy warto? Odpowiedź jest chyba jasna.

Related Posts
7 lutego 2023
Skalowanie aplikacji w chmurze — dlaczego jest ważne?
Aplikacje internetowe,  często narażone są na spore wahania ruchu. W okresie przedświątecznym, w czasie promocji…
Czytaj więcej
29 października 2017
Konkretyzuj wymagania, czyli jak działa Product Backlog Refinement.
Product Backlog Refinement jest jednym z etapów sprintu. Nie jest to formalny proces scrumowy, ale…
Czytaj więcej
22 kwietnia 2023
Środowisko AWS – o czym pamiętać przy wdrażaniu i skalowaniu?
Jeśli jesteś właścicielem startupu,  być może martwisz się skalowaniem swojej aplikacji wraz ze wzrostem jej…
Czytaj więcej