Czym jest ciągła integracja (CI) i jak może Ci pomóc

Czym jest ciągła integracja (CI) i jak może Ci pomóc

Ciągła integracja (CI) to proces weryfikacji projektu po każdorazowym wprowadzeniu zmiany w bazie kodu. Czym dokładnie jest integracja? To zależy od tego, jak skonfigurujesz ten proces: może być to coś tak prostego jak instalacja zależności i kompilacja projektu albo skomplikowana operacja polegająca na uruchamianiu wielu różnych skryptów celem stwierdzenia, czy Twój kod znajduje się w odpowiednim stanie.

Pilny współpracownik

Proces CI możesz traktować, jak pilnego współpracownika, który zawsze jest gotowy do pracy, tylko czekając na Twoje zmiany, aby móc je sprawdzić przed scaleniem ich do gałęzi głównej. W przypadku korzystania z CI warto mieć w workflow pull request, nawet jeśli pracujesz nad projektem sam. Twoje zmiany zostaną zweryfikowane przez maszynę, a umieszczenie ich na osobnej gałęzi pozwoli Ci na naprawę wszelkich wykrytych błędów, zanim zostaną scalone do gałęzi głównej.

Bez CI każdy programista odpowiada za weryfikację wszystkich wprowadzanych przez siebie zmian. Prędzej czy później któryś z członków zespołu zapomni o takiej weryfikacji – może oryginalne zmiany są w porządku, ale co będzie, jeśli po przeprowadzeniu rebase’a lub scalenia pojawi się problem? Jeśli nie korzystasz z procesu CI, pozwalasz mniej uważnym kolegom z zespołu na wrzucanie zmian z błędami i zapominanie o nich, a cały bałagan będą musieli po nich sprzątać inni.

Jak jest zorganizowane CI

Ciągła integracja sprawdza Twoje rewizje. Każda zmiana kodu pociąga za sobą wykonanie kilku różnych zadań w określonym porządku. Możesz wykorzystać dane wyjściowe z jednego zadania jako dane wejściowe w drugim zadaniu; możesz na przykład zbudować aplikację, a potem wykorzystać powstały dzięki temu pakiet do przeprowadzenia testów aplikacji. CI zarządza się zwykle z poziomu pliku konfiguracyjnego, który znajduje się w repozytorium – dzięki temu CI ewoluuje razem z Twoją bazą kodu.

Jeśli wszystkie zadania zostaną wykonane prawidłowo, commit przejdzie weryfikację pomyślnie; jeśli któreś z nich nie zostanie wykonane, commit nie przejdzie weryfikacji. W idealnej sytuacji sama zawartość commitu decyduje o wyniku CI: nie będą miały znaczenia usługi zewnętrzne ani nie będzie żadnego losowego elementu, który mógłby namieszać.

CI pokazuje wynik dla najnowszej rewizji. Gałąź główna powinna dawać wynik pozytywny w zdecydowanej większości przypadków; jakiekolwiek problemy wykryte w tym miejscu będą wpływać na cały zespół, jeśli więc dojdzie do regresji, naprawianie ich powinno być priorytetem. Gałęzie funkcjonalności należy scalać dopiero, gdy przejdą przez CI z wynikiem pozytywnym.

Image description

Zadania, którymi może zająć się CI

W procesie CI możesz umieścić wszelkie skrypty, które wykonujesz w swoim środowisku lokalnym. W przypadku większych projektów takich skryptów może być bardzo dużo. Przyjrzyjmy się jednak zadaniom tego procesu, które pojawią się najpewniej w każdym projekcie, niezależnie od jego wielkości.

Budowanie

Najprostszym testem, który możesz przeprowadzić na swoim kodzie, jest sprawdzenie, czy się kompiluje. Dzięki temu wyłapiesz wszystkie zależności, które zostały zainstalowane, ale nie zapisane, wszelkie rozbieżności typu TypeScript, które przedostały się do rewizji. Błędy te można łatwo usunąć, kiedy programista pracuje nad zadaniem, ale kiedy zostaną one udostępnione pozostałym członkom zespołu, mogą dezorientować i denerwować.

Analiza statyczna

Analiza statyczna zakłada sprawdzenie kodu bez jego uruchamiania. W projektach frontendowych często można spotkać się z narzędziami takimi jak:

  • ESLint,
  • HTMLHint,
  • Stylelint.

Programy te dają najlepsze rezultaty, jeśli integruje się je z edytorem kodu. Sprawdzenie ich wyniku w ramach procesu CI stanowi dodatkową weryfikację, która może Ci pomóc w dwojaki sposób:

  • zidentyfikuje każdego programistę, który zapomniał o wykonaniu tych programów u siebie – dzięki czemu możemy go poprosić, aby naprawił swoje zmiany, zanim zepsuje większy fragment kodu,
  • zidentyfikuje wszelkie rozbieżności w wersjach i konfiguracjach, które mogą występować w różnych środowiskach programistycznych

Image description

Wykonywanie testów

Korzystanie z procesu CI i wykonywanie w jego ramach testów jest kluczowe, jeśli poważnie podchodzisz do zautomatyzowanych testów w swojej aplikacji. Testy te mają sens, jeśli wykonuje się je bardzo często – a nie ma na to chyba lepszego momentu niż zaraz przed wprowadzeniem zmian do głównej gałęzi. Zaniechanie tego prędzej czy później sprawi, że:

  • jeden z programistów doprowadzi do regresji bazy kodu,
  • pozostali członkowie zespołu naniosą na tę regresję zmiany,
  • ktoś w końcu wykona testy, które wykryją początkową regresję,
  • ten ktoś traci cenny czas na rozwiązywanie problemów, których nie spowodował, związanych ze zmianami, o których może nie mieć pojęcia.

Głównym wyzwaniem w takiej sytuacji jest to, że kiedy w końcu zaczniesz diagnozować problemy, nie będziesz nawet wiedział, kiedy one powstały: w poprzednim commicie, a może tydzień temu? Sprawę można załatwić poprzez git blame lub git bisect, ale dużo prościej jest, kiedy wiesz, w którym momencie testy przestały działać.

Podkreślę tu coś jeszcze: pisanie testów jest inwestycją w jakość. Jest to praca, którą trzeba wykonać każdego dnia. Jeśli to robisz, warto, żebyś skonfigurował CI – dzięki temu opracowywane przez Ciebie testy dadzą najlepsze rezultaty.

Wdrażanie

CI często idzie w parze z ciągłym wdrażaniem (CD), a połączenie to często skraca się do CI/CD. Jest tak dlatego, że kompilacja i weryfikacja kodu prowadzi do powstania gotowego do wdrożenia produktu – przynajmniej na serwer testowy. Proces CD z prawdziwego zdarzenia wezwałby Cię do wprowadzenia tego produktu do środowiska produkcyjnego, ale mogłoby to być jeszcze większym wyzwaniem, bo wystawiałoby użytkowników projektu na potencjalne regresje.

Minusy

Jakie są minusy CI?

Skomplikowana konfiguracja

Konfiguracja ciągłej integracji może Ci zabrać sporo czasu, zwłaszcza jeśli zajmujesz się nią po raz pierwszy. Weryfikacja nawet najprostszych zmian w konfiguracji może być czasochłonna, bo musisz ją przeprowadzić na zewnętrznym serwerze, do którego nie masz bezpośredniego dostępu.

Zależność od zewnętrznego dostawcy

Jeśli zintegrujesz CI ze swoim workflow, będziesz zależny od dostawcy tego procesu. Jeśli usługa będzie niedostępna, nie będziesz mógł scalać albo zostaniesz pozbawiony zaworu bezpieczeństwa, do którego już zdążyłeś się przyzwyczaić. Może to być frustrujące, szczególnie jeśli zdarza się dość często.

Image description

Koszt

Wielu dostawców CI oferuje opcję darmową, która powinna wystarczyć do prostych ćwiczeń lub projektów demo. Do projektów, nad którymi pracuje się na okrągło, prawie na pewno potrzebna będzie opcja płatna oraz dodatkowy czas, w którym CI będą mogły wykonać Twoje skrypty. Będzie to jednak najprawdopodobniej warte swojej ceny, nawet przy założeniu, że CI zaoszczędzi każdemu z programistów w Twoim zespole jedynie kilka minut pracy dziennie.

A co z Tobą?

Jesteś zainteresowany pogłębianiem wiedzy na temat konfiguracji CI? Myślę o napisaniu bardziej szczegółowych artykułów na temat konfigurowania narzędzi CI. Jeśli będę wiedział, jakie narzędzie interesuje Cię najbardziej, będę mógł tworzyć treści pod tym kątem. Tak więc daj mi znać w ankiecie! Twoje zdanie jest dla mnie bardzo cenne. Dzięki!

Co dalej?

Aby wycisnąć z CI jeszcze więcej, warto przeprowadzać w ramach tego procesu testy end-to-end (E2E). Konfiguracja E2E na CI to nie lada wyzwanie. Będę o tym pisał w kolejnym artykule. Tymczasem zachęcam do lektury poradnika, w którym tłumaczę, jak zacząć pracę z testami E2E.