Ciągła integracja

Koziołek

1 Wstęp
2 Motywacja
3 Co w chodzi w skład CI
     3.1 Repozytorium kodu
     3.2 Repozytorium wyników
     3.3 Serwer komunikacyjny
4 Ogólne zasady działania CI
5 Jaki powinien być kod by CI miało sens
     5.4 Kod z repozytorium powinien się kompilować
     5.5 Kod powinien wykorzystywać narzędzia do automatycznej kompilacji
     5.6 Kod powinien być samotestujacy
     5.7 Wszystkie zmiany wprowadzamy do określonej godziny
     5.8 Zadania powinny być małe
     5.9 Każdy widzi rezultaty ostatniego zadania
     5.10 Powinna być możliwość automatycznego zdrożenia
6 Wady

Wstęp

W raz z rozwojem metodyk programowania zwinnego zaistniała potrzeba stworzenia narzędzi wspomagających automatyzację niektórych procedur związanych z budowaniem, testowaniem i dokumentowaniem kodu. Choć istniały narzędzia takie jak Maven, a znakomita większość IDE wspierała m.n. zarządzanie projektem to brakowało narzędzia pozwalającego na jeszcze lepszą automatyzację procesów.
Takim narzędziem są systemy ciągłej integracji.

Motywacja

W każdym projekcie informatycznym możemy wyróżnić kilka powtarzalnych kroków wykonywanych przez wszystkich programistów uczestniczących w projekcie. Te kroki to:

  • stworzenie interfejsu dla danego elementu (klasy, modułu).
  • stworzenie zestawu testów jednostkowych dla tego interfejsu.
  • kodowanie interfejsu i uruchamianie testów jednostkowych.
  • uzupełnienie dokumentacji.
  • wysłanie kodu do wspólnego repozytorium.

Każdy z tych kroków dotyczy zazwyczaj kodu nad którym pracuje dany programista. Bardziej rozbudowane zadania takie jak uruchamianie wszystkich testów jednostkowych w celu weryfikacji poprawności kodu, uruchamianie testów integracyjnych czy też generowanie dokumentacji są zazwyczaj przerzucane na jednego z uczestników projektu lub też zaniedbywane i wykonywane w trakcie wdrażania do testów akceptacyjnych.
Wynika to z faktu, że zadania te są czasochłonne, monotonne, powtarzalne i mało ciekawe. Jednym słowem nudne. Można je zatem wykonywać automatycznie stosując odpowiednie narzędzia.
Automatyzacja pozwala też na zaoszczędzenie czasu osób biorących udział w projekcie. Jeżeli narzędzie będzie potrafiło cyklicznie wykonywać zadania związane z weryfikacją kodu to rola odpowiedzialnego za to programisty będzie ograniczać się tylko do sprawdzenia rezultatów zadania. W przypadku niepowodzenia narzędzie będzie też wstanie wysłać informację do osób związanych z projektem o problemie. Samo niepowodzenie może zostać zdefiniowane na wiele sposobów. Począwszy od błędów kompilacji, poprzez niepoprawne rezultaty testów, a skończywszy na zbyt niskim pokryciu kodu testami czy brakach w dokumentacji. Narzędzie takie, czyli właśnie serwer ciągłej integracji (CI), pozwala ponad to na skupieniu w jednym miejscu informacji dotyczących wielu projektów. Oznacza to kolejne oszczędności i ujednolicenie sposobu zarządzania projektami w ramach firmy.
Podsumowując możemy powiedzieć, że chcąc:

  • oszczędzić czas programistów
  • zautomatyzować zadania związane z weryfikacją kodu
  • ułatwić zarządzanie kodem

należy użyć narzędzi CI.

Co w chodzi w skład CI

Serwer CI choć jest najważniejszym elementem nie jest jedynym, który wchodzi w skład systemu CI. Inne elementy to:

  • repozytorium kodu
  • serwer (zazwyczaj web) przechowujący m.n. wygenerowaną dokumentację, rezultaty testów czy skompilowany kod.
  • opcjonalny serwer poczty albo komunikatora służący do rozsyłania informacji.

Omówmy teraz każdy z tych elementów

Repozytorium kodu

Jest to serwer, na którym znajduje się kod źródłowy projektów. Kod do repozytorium wysyłają programiści w miarę postępu prac. Dobra praktyka zalecana przez m.n. Martina Fowlera[#]_ mówi, że każdy programista powinien przynajmniej raz dziennie wysłać kod do repozytorium. W systemie CI repozytorium jest zazwyczaj najważniejszym elementem, na którym opiera się proces budowy kodu.

Repozytorium wyników

Zazwyczaj jest ono zintegrowane z serwerem CI. Warto jednak pamiętać, że może istnieć konieczność udostępnienia wyników na innym serwerze. Specyficzną odmianą repozytorium wyników są repozytoria zależności, z których korzysta np. Maven. Należy zatem pamiętać, że zarówno skompilowany kod jak i wygenerowana dokumentacja mogą zostać umieszczone poza serwerem CI.

Serwer komunikacyjny

W praktyce wszystkie systemy CI udostępniają informacje o wynikach za pomocą agregatorów treści takich jak RSS czy Atom. Warto jednak zadbać o to by serwer CI był wstanie jak najszybciej poinformować programistów o wynikach. Jest to szczególnie ważne w przypadku gdy dane zadanie zakończy się niepowodzeniem. Idealnie w tej roli sprawdza się komunikator sieciowy np. Jabber albo serwer pocztowy ze skonfigurowanym oprogramowaniem grup dyskusyjnych. Serwer CI wysyła wtedy informację do zainteresowanych.

Ogólne zasady działania CI

Każdy z serwerów CI działa w trochę inny sposób, ale ogólna zasada działania jest taka sama dla wszystkich rozwiązań. Mówiąc o projekcie w systemie CI mamy na myśli pojedyncze zadania. Zadaniem może być proste przeprowadzenie kompilacji, uruchomienie testów, wygenerowanie dokumentacji. Może też być bardziej złożone na przykład kompilacja, uruchomienie testów i wdrożenie na serwerze testowym. Zadania mogą od siebie zależeć tworząc całe łańcuchy, które odzwierciedlają kolejne kroki bardziej skomplikowanych procedur.
Zadania mogą być uruchamianie ręcznie przez programistę, ale zazwyczaj istnieje możliwość skonfigurowania cyklicznego uruchamiania z uwzględnieniem różnych warunków. Przykładowo zadanie kompilacji i przetestowania kodu może być uruchamiane tylko wtedy gdy w repozytorium pojawią się zmiany. Samo odpytywanie repozytorium będzie już realizowane cykliczne w zadanych odstępach czasu. Dopiero gdy zmiany pojawią się w repozytorium zostanie uruchomiony proces kompilacji.
Wynika z tego, że co do zasady zadania rozpoczynają się od sprawdzenia stanu repozytorium. Oczywiście nie jest to konieczne przy niektórych rodzajach zadań, ale te są zazwyczaj rzadko spotykane. Po pobraniu kodu z repozytorium serwer CI przystępuje do głównego zestawu czynności czyli kompilacji, testowania bądź np. generowania dokumentacji. Po zakończeniu tych zadań wyniki są agregowane do zainteresowanych osób lub też są uruchamiane kolejne zadania owiązane z tym zadaniem.

Jaki powinien być kod by CI miało sens

Istnieje kilka zasad dotyczących kodu oraz pracy, które ułatwiają wdrożenie CI w projekcie.

Kod z repozytorium powinien się kompilować

Nie jest to oczywiste. Wielu programistów traktuje repozytorium jak miejsce, w którym wygodnie składuje się kopię zapasową kodu. Bez względu na to czy dany kod się kompiluje czy też nie. Jest to zła praktyka. Kod, który nie kompiluje się powinien zostać wydzielony do osobnej gałęzi w repozytorium i dopiero po wprowadzeniu wszystkich zmian powinien zostać z powrotem dołączony do głównego repozytorium.
Jeżeli kod nie będzie się kompilował serwer CI zgłosi błąd i będzie powtarzał zgłoszenie do czasu poprawienia kodu. Może to powodować np. wstrzymanie publikacji działającej wersji na serwerach. W dodatku będzie blokowało prace innych programistów.

Kod powinien wykorzystywać narzędzia do automatycznej kompilacji

Głównym założeniem CI jest automatyzacja zadań. Jeżeli kod wymaga dodatkowych prac przed kompilacją, które nie mogą zostać zautomatyzowane, to wdrożenie go w ramach CI nie ma sensu.

Kod powinien być samotestujacy

Podobnie jak w przypadku kompilacji testy powinny być integralną częścią kodu. Po kompilacji powinna być możliwość ich uruchomienia w ramach tego samego zadania. Pozwala to na weryfikację kodu pod kątem poprawności działania.

Wszystkie zmiany wprowadzamy do określonej godziny

Skoro każdy programista powinien codziennie wysyłać swój działający kod do repozytorium to ważne jest by zmiany były dokonywane do pewnej ustalonej godziny. Pozwala to na zaplanowanie kolejki zadań na serwerze CI co przekłada się na niższe koszty jego eksploatacji.

Zadania powinny być małe

Oczywiście w miarę możliwości. Chodzi tu generalnie o tworzenie prostych zadań, które nie zawierają wielu skomplikowanych kroków. Pozwoli to na szybsze wyłapywanie błędów oraz ułatwi zarządzanie zadaniami.

Każdy widzi rezultaty ostatniego zadania

Jest to o tyle ważne, że dzięki tej zasadzie każdy z programistów zainteresowanych danym projektem wie jaki jest aktualny stan prac. Pozwala to na lepsze zaplanowanie innych zadań z uwzględnieniem stanu danego projektu.

Powinna być możliwość automatycznego zdrożenia

Jeżeli kompilacja i testy zakończą się powodzeniem powinna być możliwość automatycznego wdrożenia nowej wersji oprogramowania na serwerach lub w repozytorium. Pozwala to na oszczędzenie czasu programistów.

Wady

Systemy CI mają kilka istotnych wad:

  • wymagają konfiguracji i utrzymania.
  • wymagają kodu dobrej jakości. Szczególnie kodu z odpowiednią ilością testów by móc korzystać z zalet automatyzacji testów.
  • mogą wymagać znacznych nakładów sprzętowych.

Szczególnie wymieniona w ostatnim punkcie cecha może okazać się dużym zagrożeniem. Wraz z rozwojem systemu CI w firmie pojawia się zapotrzebowanie na coraz to mocniejsze serwery zdolne prowadzić wiele zadań związanych z kompilacją na raz oraz na coraz większe dyski w celu przechowywania wyników. Pomimo to warto jednak zainwestować w serwer CI ponieważ ułatwia on pracę oraz obniża koszty związane z testami i wdrożeniem oprogramowania.

.. [#] http://martinfowler.com/articles/continuousIntegration.html#PracticesOfContinuousIntegration

2 komentarzy

@kadoel, dostawców CI jest od cholery i ciut ciut. Przykłady raczej w tekstach o konkretnych rozwiązaniach.

Spodziewałem się dłuższego artykuł z przykładami.