Ciągła Integracja: anioł stróż dobrego programisty

Gdybym miała wskazać jedną ważną umiejętność, której brakuje większości absolwentów informatyki (i pokrewnych kierunków) aplikujących do pracy u nas w biurze, z pewnością byłaby to Ciągła Integracja. Wygląda na to, że programy studiów nie obejmują tego tematu, a prowadzący zajęcia nie przykładają do niego specjalnej wagi. Tymczasem w moim doświadczeniu niewiele rozwiązań skutkuje tak zauważalnym wzrostem produktywności pracy, a także codziennego zadowolenia programistów, jak ta właśnie praktyka. Na szczęście, luki w wiedzy nie tak trudno uzupełnić, choć diabeł, jak zwykle, tkwi w szczegółach.

Ciągła Integracja (CI) – co to?

Definicją służy, jak zawsze niezawodny, Martin Fowler:

Ciągła Integracja (ang. Continuous Integration) to praktyka programistyczna, w której członkowie zespołu często scalają wyniki swojej pracy – z reguły każdy robi to przynajmniej raz dziennie. W tej sposób każdego dnia powstaje kilka zintegrowanych wersji kodu, które są sprawdzane przez automatyczny proces budowania (i testowania).

Jest to również jedna z 12 praktyk Programowania Ekstremalnego.

Zasadę dobrze przedstawia poniższa ilustracja, pochodząca ze strony firmy Atlassian.

Ciągła Integracja: architektura na przykładzie narzędzia Atlassian Bamboo

W wielkim skrócie: programiści pracują nad bazą kodu, na bieżąco aktualizując zawartość wspólnego repozytorium. Niezależnie od niego działa serwer Ciągłej Integracji, który co jakiś czas (np. po każdym wysłaniu porcji kodu do repozytorium, albo zawsze o 2 w nocy) pobiera kod z repozytorium, który następnie testuje, kompiluje i, jeśli wszystko poszło jak trzeba, przygotowuje do wdrożenia. W przypadku wykrycia błędów niezwłocznie informuje osoby zaangażowane w projekt o problemie.

Po co to?

  1. Ciągła Integracja zmniejsza ryzyko związane z integracją na samym końcu projektu – błędy, niekompatybilność interfejsów, trudny do oszacowania czas na poskładanie całości. Z własnego doświadczenia znam przypadek, w którym sprzeczka o to, po której stronie interfejsu jest problem i kto ma przyjść do pracy w sobotę, żeby naprawić go przed poniedziałkową prezentacją, doprowadziła do odejścia „pokrzywdzonej” osoby z pracy.
  2. CI ułatwia naprawę błędów: ich szybkie wykrywanie sprawia, że łatwiej zlokalizować przyczynę  – wiadomo, co było ostatnio modyfikowane i jaka wersja działała poprawnie.
  3. CI chroni przed niespodziankami wynikającymi z różnic pomiędzy środowiskiem deweloperskim a produkcyjnym (np. inne środowisko uruchomieniowe danego języka, niestandardowe biblioteki).beavis
  4. CI umożliwia demonstrowanie aplikacji i konsultację z klientem w dowolnym momencie dzięki stałej dostępności ostatniej działającej wersji.
  5. CI ułatwia refaktoryzację (po każdej „kosmetycznej”  zmianie możemy szybko sprawdzić, czy wszystko gra).
  6. Ciągła integracja zdejmuje z programistów obowiązek wykonywania wielu powtarzalnych, nierozwijających (a jednak trudnych!) czynności.

(Niezgrabne) terminy

Terminy związane z Ciągłą Integracją trudno zwięźle przełożyć na języki polski. Najwięcej kłopotów sprawia najważniejszy z terminów, czyli build.

Proces budowania (build) to dużo więcej niż sama kompilacja. Często obejmuje:

  • kompilację
  • testy
  • inspekcję kodu
  • wdrożenie

Jeśli wykorzystujesz serwer CI tylko do kompilacji, nie powinieneś nazywać swojego procesu Ciągłą Integracją.

Narzędzie do budowania (build script lub build automation tool) pozwala na zdefiniowanie procesu budowania uruchamianego „jednym kliknięciem”. Nie musi wiązać się z serwerem Ciągłej Integracji: może działać w ramach IDE lub konsolowo. Przykłady: Maven, Rake, make.

Integracyjny proces budowania (integration build) to proces budowania uruchomiony na osobnym, specjalnie do tego przeznaczonym serwerze.

Prywatny proces budowania (private build) to proces budowania uruchomiony przez programistę lokalnie, przed wysłaniem kodu do repozytorium (lub w prywatnej, należącej do danego programisty gałęzi kodu w repozytorium).

Serwer Ciągłej Integracji (schematycznie przedstawiony na pierwszej ilustracji w tym wpisie) usprawnia definiowanie integracyjnych procesów budowania i  odpowiada za ich uruchamianie w określonych okolicznościach (zwróć uwagę na akapit o wyzwalaczach).

Dobre praktyki

Cechy, którymi powinno charakteryzować się środowisko Ciągłej Integracji:

  1. Jedno wspólne repozytorium kodu, zawierające wszystko, co potrzebne do zbudowania i uruchomienia systemu na czystej maszynie. Oczywiście zdarza się, że nad projektem pracuje kilka rozproszonych zespołów odpowiadających za oddzielne komponenty i preferujących różne systemy kontroli wersji. Ciągła Integracja jest wtedy jeszcze bardziej potrzebna!
  2. Automatyczne budowanie – żadnych wyskakujących okienek i ręcznego kopiowania plików!
  3. Automatyczne testy podczas budowania – to, że program się skompilował i da się go uruchomić, nie znaczy jeszcze, że wszystko z nim w porządku. Warto sprawdzać nie tylko wyniki testu, ale także procent pokrycia kodu testami.
  4. Codzienne wysyłanie i scalanie (działającego!) kodu przez programistów. Integracja to komunikacja – programiści widzą, nad czym pracują inni i jak im idzie.
  5. Inspekcje kodu. Przeglądy kodu, przeprowadzane przez innych programistów, mogą nawet doprowadzić do niewpuszczenia kodu na serwer. Ich podstawową wartością jest jednak wymiana wiedzy.
  6. Uruchomienie procesu budowania po każdej zmianie kodu w repozytorium i natychmiastowa reakcja na awarie
  7. Szybkość procesu budowania – natychmiastowa informacja zwrotna. Automatyczne testy nie powinny ciągnąć się przez godzinę. Jeżeli nie ma możliwości optymalizacji działania systemu ani dołożenia większej liczby maszyn, można stosować techniki takie jak randomizacja testów lub staged tests, w których najistotniejsze, szybkie testy przesuwa się na początek, żeby autor kodu wiedział, czy może (wstępnie) kontynuować pracę.
  8. Testy w środowisku jak najlepiej udającym produkcję. Drobiazgi, takie jak inne numery portów, potrafią doprowadzić do prawdziwej katastrofy.
  9. Ciągła dostępność wyników testów oraz najnowszej zbudowanej wersji aplikacji. Wszyscy programiści powinni wiedzieć, co dzieje się w głównej gałęzi repozytorium. Informację tę można dystrybuować na różne sposoby: powiadomienia (np. mailowe), ekrany wyświetlające status (zielony = wszystko gra, czerwony = awaria), lava lamps… Wyobraźnia nie zna granic 🙂

220px-Series_of_build_lights

Ciągłe Wdrażanie, czyli jeden krok dalej

Oprócz terminu Continuous Integration możesz natknąć się jeszcze na Continuous Deployment, Continuous Release, Continuous Delivery (dosłownie to: ciągłe wdrażanie, wydawanie, dostarczanie).

Ciągłe Wdrażanie to to Ciągła Integracja rozszerzona o wdrażanie z częstotliwością odpowiadającą integrowaniu – udostępniamy klientom każdą wersję, która przeszła testy automatyczne.

Omawianie szczegółowych różnic pomiędzy przytoczonymi tu terminami zdecydowanie wykracza poza ambicje tego artykułu.

Wyzwalacze, czyli kiedy budować?

Większość serwerów Ciągłej Integracji pozwala na zdefiniowanie następujących „wyzwalaczy” procesu budowania:

  • ręczny – na żądanie programisty,
  • planowy – o określonej porze (np. tzw. „nightly build”),
  • odpytanie repozytorium – w reakcji na zmianę kodu źródłowego,
  • zdarzeniowy – np. w reakcji na zmianę kodu źródłowego (ale to repozytorium informuje) lub zakończenie innego procesu budowania.

Który serwer wybrać?

Serwerów Ciągłej Integracji jest na rynku bardzo, bardzo dużo. Najpopularniejszy jest w tej chwili otwarty serwer Jenkins (fork projektu Hudson, to historia na osobny artykuł). Inna popularna opcja to Bamboo – narzędzie komercyjne, którego siła tkwi w pełnej integracji (sic!) z innymi ułatwiającymi życie rozwiązaniami firmy Atlassian. Bardziej szczegółowe porównanie można znaleźć nawet w Wikipedii.

Co z tego zapamiętać? tl;dr

Ciągła Integracja pozwala programiście być programistą. Programista zajmuje się tworzeniem kodu, a nie powtarzalnymi operacjami niezbędnymi do scalenia kodu i przygotowania wydania.

Dzięki CI natychmiast (ewentualnie następnego ranka po beztroskiej nocy) otrzymujemy informację o tym, że coś poszło nie tak, dzięki czemu możemy reagować na bieżąco.

W następnym odcinku

W kolejnym odcinku pokażę, jak zdefiniować proces budowania na serwerze Bamboo.

Gdzie znaleźć więcej informacji?

Komentarze

7 myśli nt. „Ciągła Integracja: anioł stróż dobrego programisty”

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *