czwartek, 19 grudnia 2013

CI założenia i cele


CI  ->  CD (integration - > delivery)


Continuum Integration 
CI (Continuous Integration) (przykład jak to działa znajduje się tutaj)

CI jest to technika służąca ochronie i poprawie pracy nad projektem. Pomaga usprawnić proces wytwarzania i czyni ten proces mniej ryzykownym i bardziej przejrzystym oraz większa higienę w projekcie.  Ciągłe łączenie zmian wprowadzanych przez różne osoby w projekcie to również CI.

Generalnie  trzymamy się zasad opisanych na diagramie powyżej  i
zdefiniowanych przez samego M.Fowlera czyli integrować często i wcześnie.

Nie stosowanie dobrych praktyk CI i CD skutkuje zjawiskiem zwanym piekłem integracji (integration hell) czyli co może pójść niezgodnie z przewidywaniami :
  - błędy ludzkie
  - problemy z komunikacją w zespole
  - różnice w środowiskach uruchomieniowych (np inne wersje JDK czy przeglądarek)
  - błędy i różnice w plikach konfiguracyjnych
 Pewnie coś takiego każdy z nas zauważył jeśli nie stosował wcześniej narzędzi ciągłej integracji.

Fajnie pokazane jest to na stronie : blog.octo.com







Cykl życia w CI według mnie jest następujący :
- instalacja i konfiguracja
- zdefiniowanie build'u oraz polityki pobierania i kompilacji
- testowanie (unit test , integration test  etc)
- raporty oraz metryki
- budowanie paczki
- uruchamianie paczki na serwerze testowym oraz odpalanie testów UAT
- dostarczanie paczki do klienta (zdalny deploy , sftp , etc)

Dla mnie najlepszym przykładem oraz pierwszym objawem kiedy trzeba zastosować ciągłą integracje jest zjawisko, które nazywałem : ' U mnie działa ...'.
Ale kogo to obchodzi, skoro pobierasz aktualną wersje z repozytorium. Budujesz kod, wrzucasz na serwer i ....lipa. Nic nie działa.
Teraz myślisz a co mnie kur ... obchodzi, że u Ciebie mój drogi kolego jakoś zadziałało skoro na serwerze wszystko się wypierda......, lub dostajesz deploy failed.

Jest jeszcze gorsza wersja problemu :), a właściwie to lepsza bo występuję we wcześniejszym stadium wytwarzania softu mianowicie przy kompilacji.

Teraz okazało się znów, że kumpel zapomniał zrobić commit na jeden z klas.
O tyle ten przypadek jest lepszy bo łatwość zweryfikowania problemu jest o niebo łatwiejsza. Gorzej jeśli kod się kompiluje ale integruje źle z innymi komponentami lub klasami , albo wystąpił problem z java classloader bo ktoś zmienił wersję jakiejś biblioteki.
 
Tu wysuwa się pierwszy z naszych wniosków :
- profilaktyka jest tańsza niż leczenie 
(Wczesne wykrywanie błędów i konfliktów by można je było wystarczająco szybko wyeliminować - w miarę bezboleśnie.
Sprowadza się do w sumie do częstej kompilacji kody z repozytorium i wykonywania testów jednostkowych, a następnie powiadamianie różnymi kanałami o ewentualnych problemach)

Tutaj chcemy również żeby nasze build'y były możliwie szybkie.
Możemy to osiągnąć na kilka sposobów.

1. Ograniczamy i selekcjonujemy testy np poprzez lifecycle procesów z mavena lub profile.
Testy powinny wykonywać się szybko. Nikt nie będzie czekał przez 10 min aż zbuduje mu się paczka. Testy kŧóre wymagają integracji są z reguły czasochłonne bo wymagają inicjalizacji zasobów , wczytania kontekstu, czekania na odpowiedź itd.
Z kolei testy akceptacyjne UAT z reguły wymagają uruchomienia przeglądarki i przejścia po scenariuszach testowych.
Fajnie jest jeśli mamy odpowiednią separację takich testów. Fajnie to może złe  słowo - to raczej konieczność.
2. Wyznaczymy inną ścieżkę budowy w naszym CI (rozdzielany buildy)
Np czasochłonne testy wykonują się w nocy. Testy wydajnościowe wykonują się na innych maszynach a po ich skończeniu dostajemy informacje zwrotne o ewentualnych problemach.
3. Stosujemy pipeline.
Jenkins dostarcza plugin, który pomaga podzielić proces na części. W praktyce wygląda to tak, że nie musimy czekać aż wszystkie moduły które zależą od paczki końcowej się wykonają. Zwiększamy jakby bardziej ziarnistość procesu budowy.

Chcemy poprawić testowalość (testablility) naszej aplikacji, a CI nam w tym pomaga:
- automatyczne testy (regresja - daje nam pewność, że wcześniej dostarczona funkcjonalność nadal działa pomimo wprowadzenia nowych zmian)
- separacja testów (czytaj wyżej)
- monitoring czasu wykonywania testów
- monitoring pokrycia testami (test coverage)

 Drugi z naszych wniosków:
 - skracanie procesu wytwarzania i czasu wydania release'a
 CI sprawia , że prawie przez cały czas dysponujemy działającą wersją aplikacji, którą możemy pokazać testerom , a potem po ich akceptacji zmienić wersję z snapshot na release po czym otagować ją w repozytorium ponownie.
Ewentualne defekty poprawia osoba, które je wprowadziła ponieważ ma największą wiedzę z dziedziny problemu oraz kontekstu.
Dostajemy również łatwy dostęp do najnowszego artefaktu, a także każdego artefaktu historycznego.

Trzeci z naszych wniosków:
 - automatyzacja jest zajebista bo jest odporna na ludzkie błędy
Często spotkałeś się pewnie z następującym problemem czy zjawiskiem :
Szef projektu każe szybko przygotować wersji dla klienta z jakimś nowym CR czy poprawką w stosunku do powszedniej wersji. Twoim zadaniem jest tylko zbudować wersji odpowiadającą środowisku produkcyjnemu klienta. Tylko...
Pośpiech jest złym doradcą ....
Zapomniałeś zmienić profil z -Pdevelop na -Pprod , lub jeśli masz to zorganizowane w inny sposób w pliku .properties nie zmieniłeś parametrów bazy , adresu jakiegoś WS czy serwisu LDAP , lub obojętnie czego w zależności od specyfiki projektu.

Taka wersja trafia do klienta i z reguły nie działa. Traci na tym wizerunek firmy.
Jeśli są to odosobnione przypadki to jest jeszcze ok, każdy robi błędy i klient to zrozumie.
Gorzej jeśli to zjawisko występuje nagminnie. To kolejny powód by pomyśleć o CI w firmie.

Czwarty z naszych wniosków:
 - wspomaga zwinne metodyki wytwarzania
Continuous Delivery (CD) sprawia, że proces wytwarzania staje się faktycznie i praktycznie procesem zwinnym (agile). Cały cykl iteracyjny wytwarzania ma odzwierciedlenie CD.
Kompilacja - Testy - Budowanie - (Testy) - Dostarczanie.
Użytkownik końcowy jak i tester są bliżej wprowadzanych zmian i poprawek niż kiedykolwiek przedtem.
Przez to mają lepszy obraz funkcjonalności i  faktycznego postępu co z kolei definiuje szybki feedback z ich strony.
Klient faktycznie widzi jak z każdą iteracją aplikacji rozwija się co przekłada się na polepszenie obustronnego zaufania i zaciśnięcie obustronnej współpracy.

 Piąty z naszych wniosków:
 - każdy członek zespołu umie wyprodukować produkt końcowy łącznie z zainstalowaniem go na dedykowanym do tego serwerze. (Poprawa komunikacji (team collaboration)) oraz Collective Ownership (własność wspólna)
Częste commit'y oraz wspólny kod sprzyja manifestowi Agile oraz poprawia komunikacje w zespole. Nie istnieją "bogowie build'ow" czyli takie osoby, które jako jedyne są w stanie zbudować i dostarczyć paczkę dla klienta.
Taka wiedza powinna należeć do całego zespołu. Dzięki CI ten proces obywa się automatycznie (scheduled process) lub na żądanie wystarczy wcisnąć (play-> tzn  build) w jenkinsie.
Wszyscy widzą co się dzieje - (M.Fowler), każdy jest w stanie określić w jakim stadium znajduje się projekt oraz określić jakie zmiany do niego wprowadzono.

Szósty z naszych wniosków :
- zdecydowana poprawa jakości wytwarzanego oprogramowanie.
Podpięcie testów wspomaga przyszły refaktoring. Podpięcie narzędzi do statycznej analizy kody zwiększa higienę kodu, oraz eliminuje część złych praktyk oraz potencjalnych bug'ów.
Dzięki temu  przechodzimy do pojęcia (Continuous inspection) ciągła inspekcja, dzięki której możemy wytwarzać oprogramowanie lepszej jakości (sonar - timeline)

Definicja polityki pokrycia testami , tu możemy zakończyć proces budowy jeśli okaże się, że pokrycie testów (test coverage) nie pokrywa np 60% całości. Tak samo działa polityka wykrywania wszelkiego rodzaju nieprawidłowości w kodzie np : build kończy się niepowodzeniem jeśli system wykrył ponad 20 nowych problemów (issue)
Można zdefiniować repozytorium tzn staging dzięki któremu możemy wprowadzić funkcjonalność typu code review (np gerrit) co zwiększa kontrolę  oraz jeszcze bardziej poprawia jakoś finalnego kodu. Ponieważ kod, który znajdzie się docelowo we właściwym repozytorium musi być sprawdzony i zatwierdzony przez członka zespołu o największych umiejętnościach i wiedzy w danej dziedzinie.
Gramy w leader board - czyli stosujemy licznik i wprowadzamy zasady punktacji np : za każdy dobry deploy +1 punkt, za każde issue +3 punkty , za każdy TODO + 3punkt, za każdy nieudany build -1punkt, za wygenerowanie nowego issue -3 punkty itd.
CI wspomaga tworzenie soft TDD (Test Driven Development) - piszesz najpierw testy które z początku nie działają, a podczas budowania cała funkcjonalność musi przejść te testy. (JUnit , TestNG)   ->  mvn test
BDD (Behavior Driven Development) - zespół opisuje poprzez testy scenariusze i ustala warunki i wynik  ich wykonania. (jbehave, Cucumber) -> mvn verify

Jenkins posiada wtyczki pozwalające na odpalanie testów wydajnościowych stworzonych np przez JMeter dzięki czemu jesteśmy w stanie dotrzymać warunki zawarte w SLA projektu.

Siódmy z naszych wniosków :
- mniejszy poziom stresu dla całego zespołu, większa kontrola, dostarczanie produktu na czas. 
Jako podsumowanie naszym poprzednich 6 punktów przychodzi następująca konkluzja:
- wiedzę , że mam większą kontrolę na całością cyklu wytwarzania.
- odpowiednie osoby dostają odpowiednie raporty
- widzę czy wytwarzanie projektu idzie w dobrym kierunku
- dbam o higienę kodu - bardziej to CI to na mnie wymusza
- dostarczam natychmiastowo nowy produkt
- popełniam mniej błędów - wyeliminowanie do min czynnika ludzkiego.

 Kolejny ciekawy artykuł o CI  jest dostępny pod linkiem .

Inne dobre praktyki które mogę  polecić : 
- osobne konta w CI
- wprowadzenie polityki (zarządzanie i konfiguracja oraz dostęp do artefaktów)
- wszechobecne wiki
- polityka archiwizacji build'ów (harmonogram prac konserwacyjnych)
- korzystanie w różnych rodzajów systemów operacyjnych , dzięki czemu można 
testy integracyjne lub funkcjonalne na kilku różnych przeglądarkach.
-wirtualizacja CI
-polityka kopii zapasowych artefaktów.(murphy laws , backup plugin)
-monitoring zasobów : pamięć, procesor (javaMelody plugin), oraz wykorzystania dysków (disk usage plugin)
- zdefiniowanie właściwych parametrów MAVEN_OPTS
- przeglądanie logów budowy paczki (Log Parser Plugin) - pozwala nam to między innymi zagregować logi poziomem błędów.
- plugin do firefox - pozwalający na wgląd w stan aplikacji oraz pokazuje na bieżąco ich status (rss)
- integracja z groovy - pozwala na wykonywanie skryptów .groovy
- automatyczny deploy na zdalne repozytorium z udziałem ustawień znajdujących się w settings.xml mavena.
- slave axis - rozproszenie obciążenia na różne maszyny. Umożliwia stworzenie  macierzy rozwiązań tzn mogę uruchamiać i budować wersją pod różnymi systemami oraz testować na różnych przeglądarkach (Selenium, UAT test) lub wykorzystać różne instancje baz danych.
- oraz wiele innych ciekawych wtyczek które są opisane tutaj.

Szybkie i  bazowe konfigurowanie Jenkinsa w skrócie:
- konfiguracja global properties
- konfiguracja jdk
- konfiguracja jednego z wybranych narzędzi budowy np: maven
- konfiguracja systemu kontroli wersji np: git
- konfiguracja mail serwera do wysyłki wiadomości oraz potencjalnych odbiorców
- instalacja potrzebnych wtyczek
- dodanie użytkowników oraz uprawnień
- ewentualna konfiguracja proxy
- zdefiniowanie ewentualnych pre , post procesorów
- zdefiniowanie końcowych serwerów
 
dalej ->

Brak komentarzy:

Prześlij komentarz