Ciągła integracja - Continuous integration

W inżynierii oprogramowania , ciągła integracja ( CI ) jest praktyka łączenia wszystkich deweloperów kopie robocze do wspólnego głównego nurtu kilka razy dziennie. Grady Booch jako pierwszy zaproponował termin CI w swojej metodzie z 1991 roku , chociaż nie zalecał integracji kilka razy dziennie. Programowanie ekstremalne (XP) przyjęło koncepcję CI i zalecało integrację więcej niż raz dziennie – być może nawet dziesiątki razy dziennie.

Racjonalne uzasadnienie

Rozpoczynając zmianę, programista pobiera kopię aktualnej bazy kodu, na której ma pracować. Ponieważ inni programiści przesyłają zmieniony kod do repozytorium kodu źródłowego , ta kopia stopniowo przestaje odzwierciedlać kod repozytorium. Można nie tylko zmienić istniejącą bazę kodu, ale można dodać nowy kod, a także nowe biblioteki i inne zasoby, które tworzą zależności i potencjalne konflikty.

Im dłużej trwa rozwój w gałęzi bez łączenia się z główną linią, tym większe jest ryzyko wielu konfliktów integracji i niepowodzeń, gdy gałąź deweloperska zostanie ostatecznie scalona z powrotem. Kiedy programiści przesyłają kod do repozytorium, muszą najpierw zaktualizować swój kod, aby odzwierciedlić zmiany w repozytorium od momentu pobrania kopii. Im więcej zmian zawiera repozytorium, tym więcej pracy muszą wykonać programiści przed przesłaniem własnych zmian.

W końcu repozytorium może stać się tak różne od linii bazowych programistów, że wejdą w to, co jest czasami określane jako „piekło scalania” lub „piekło integracji”, gdzie czas potrzebny na integrację przekracza czas potrzebny na wprowadzenie oryginalnych zmian .

Przepływy pracy

Uruchom testy lokalnie

CI ma być używany w połączeniu z automatycznymi testami jednostkowymi pisanymi przy użyciu praktyk programowania sterowanego testami . Odbywa się to poprzez uruchomienie i przekazanie wszystkich testów jednostkowych w lokalnym środowisku dewelopera przed przejściem na główną linię. Pomaga to uniknąć łamania przez jednego programistę kopii kopii innego programisty. W razie potrzeby częściowo kompletne funkcje można wyłączyć przed zatwierdzeniem, na przykład za pomocą przełączników funkcji .

Skompiluj kod w CI

Serwer kompilacji kompiluje kod okresowo lub nawet po każdym zatwierdzeniu i raportuje wyniki deweloperom. Użycie serwerów kompilacji zostało wprowadzone poza społecznością XP (programowanie ekstremalne), a wiele organizacji przyjęło CI bez przyjmowania całego XP.

Uruchom testy w CI

Oprócz zautomatyzowanych testów jednostkowych, organizacje korzystające z CI zwykle używają serwera kompilacji do wdrażania ciągłych procesów stosowania kontroli jakości w ogóle – małych prac, stosowanych często. Oprócz przeprowadzania testów jednostkowych i integracyjnych, takie procesy przeprowadzają dodatkowe analizy statyczne, mierzą i profilują wydajność, wyodrębniają i formatują dokumentację z kodu źródłowego oraz ułatwiają ręczne procesy QA . W popularnej usłudze Travis CI dla open source tylko 58,64% zadań CI wykonuje testy.

To ciągłe stosowanie kontroli jakości ma na celu poprawę jakości oprogramowania i skrócenie czasu potrzebnego na jego dostarczenie, zastępując tradycyjną praktykę stosowania kontroli jakości po zakończeniu całego rozwoju. Jest to bardzo podobne do pierwotnego pomysłu częstszej integracji w celu ułatwienia integracji, stosowanego tylko w procesach zapewniania jakości.

Wdróż artefakt z CI

Obecnie CI często przeplata się z ciągłym dostarczaniem lub ciągłym wdrażaniem w tak zwanym potoku CI/CD. „Ciągłe dostarczanie” zapewnia, że ​​oprogramowanie zaewidencjonowane na głównej linii jest zawsze w stanie, który można wdrożyć dla użytkowników, a „ciągłe wdrażanie” sprawia, że ​​proces wdrażania jest w pełni zautomatyzowany.

Historia

Najwcześniejsze znane prace nad ciągłą integracją to środowisko Infuse opracowane przez GE Kaiser, DE Perry i WM Schell.

W 1994 roku Grady Booch użył wyrażenia ciągła integracja w analizie zorientowanej obiektowo i projektowaniu z aplikacjami (wydanie drugie), aby wyjaśnić, w jaki sposób podczas opracowywania przy użyciu mikroprocesów „wewnętrzne wydania reprezentują rodzaj ciągłej integracji systemu i istnieją, aby wymusić zamknięcie mikroprocesu”.

W 1997 roku Kent Beck i Ron Jeffries opracowali Extreme Programming (XP) podczas realizacji projektu Chrysler Comprehensive Compensation System , obejmującego ciągłą integrację. Beck opublikował w 1998 r. temat ciągłej integracji, podkreślając znaczenie komunikacji twarzą w twarz nad wsparciem technologicznym. W 1999 roku Beck rozwinął więcej w swojej pierwszej pełnej książce poświęconej programowaniu ekstremalnemu. CruiseControl , jedno z pierwszych narzędzi CI typu open source, zostało wydane w 2001 roku.

W 2010 roku Timothy Fitz opublikował artykuł szczegółowo opisujący, w jaki sposób zespół inżynierów IMVU zbudował i używał pierwszego praktycznego systemu CI. Chociaż jego post początkowo spotkał się ze sceptycyzmem, szybko przyjął się i znalazł szerokie zastosowanie jako część metodologii tworzenia oprogramowania Lean , również opartej na IMVU.

Wspólne praktyki

W tej sekcji wymieniono najlepsze praktyki sugerowane przez różnych autorów dotyczące osiągania ciągłej integracji i automatyzacji tej praktyki. Automatyzacja kompilacji sama w sobie jest najlepszą praktyką.

Ciągła integracja — praktyka częstego integrowania nowego lub zmienionego kodu z istniejącym repozytorium kodu — powinna występować na tyle często, aby między zatwierdzeniem a kompilacją nie pozostało żadne okienko interweniujące , a także aby nie pojawiły się żadne błędy bez zauważenia ich przez programistów i natychmiastowego ich poprawienia. Normalną praktyką jest wyzwalanie tych kompilacji przy każdym zatwierdzeniu w repozytorium, a nie okresowo zaplanowanej kompilacji. Praktyczne możliwości robienia tego w środowisku szybkich zatwierdzeń dla wielu programistów są takie, że zwykle wyzwalanie następuje po krótkim czasie po każdym zatwierdzeniu, a następnie rozpoczęcie kompilacji po wygaśnięciu tego licznika lub po dłuższej przerwie od ostatniej kompilacji . Zauważ, że ponieważ każde nowe zatwierdzenie resetuje licznik czasu używanego do wyzwalacza krótkiego czasu, jest to ta sama technika używana w wielu algorytmach odrzucania przycisków. W ten sposób zdarzenia commit są "odbijane", aby zapobiec niepotrzebnym kompilacjom między seriami szybkich commitów. Wiele zautomatyzowanych narzędzi oferuje to planowanie automatycznie.

Innym czynnikiem jest potrzeba systemu kontroli wersji, który obsługuje atomowe zatwierdzenia ; tzn. wszystkie zmiany dewelopera mogą być postrzegane jako pojedyncza operacja zatwierdzenia. Nie ma sensu próbować budować tylko z połowy zmienionych plików.

Aby osiągnąć te cele, ciągła integracja opiera się na następujących zasadach.

Utrzymuj repozytorium kodu

Ta praktyka zaleca stosowanie systemu kontroli wersji dla kodu źródłowego projektu. Wszystkie artefakty wymagane do zbudowania projektu należy umieścić w repozytorium. W tej praktyce i w społeczności kontroli wersji konwencja jest taka, że ​​system powinien być budowany od nowa i nie wymaga dodatkowych zależności. Zwolennik Extreme Programming Martin Fowler wspomina również, że tam, gdzie rozgałęzienie jest wspierane przez narzędzia, należy zminimalizować jego użycie. Zamiast tego preferowane jest integrowanie zmian, a nie jednoczesne utrzymywanie wielu wersji oprogramowania. Linia główna (lub trunk ) powinna być miejscem na działającą wersję oprogramowania.

Zautomatyzuj kompilację

Jedno polecenie powinno mieć możliwość zbudowania systemu. Wiele narzędzi do budowania, takich jak make , istnieje od wielu lat. Inne, nowsze narzędzia są często używane w środowiskach ciągłej integracji. Automatyzacja produkcji powinna obejmować automatyzację integracji, która często obejmuje wdrożenie do produkcji podobnego środowiska . W wielu przypadkach skrypt budujący nie tylko kompiluje pliki binarne, ale także generuje dokumentację, strony internetowe, statystyki i nośniki dystrybucyjne (takie jak Debian DEB , Red Hat RPM czy pliki Windows MSI ).

Dokonaj autotestu kompilacji

Po skompilowaniu kodu należy uruchomić wszystkie testy, aby potwierdzić, że zachowuje się on zgodnie z oczekiwaniami programistów.

Każdy każdego dnia zobowiązuje się do linii bazowej

Dzięki regularnemu zatwierdzaniu każdy zatwierdzający może zmniejszyć liczbę sprzecznych zmian. Sprawdzanie tygodniowej wartości pracy wiąże się z ryzykiem konfliktu z innymi funkcjami i może być bardzo trudne do rozwiązania. Wczesne, małe konflikty w obszarze systemu powodują, że członkowie zespołu komunikują się o wprowadzanych zmianach. Zatwierdzanie wszystkich zmian co najmniej raz dziennie (raz na zbudowaną funkcję) jest ogólnie uważane za część definicji ciągłej integracji. Ponadto generalnie zaleca się wykonywanie nocnych kompilacji . To są dolne granice; oczekuje się, że typowa częstotliwość będzie znacznie wyższa.

Każde zatwierdzenie (do linii bazowej) powinno zostać zbudowane

System powinien zbudować zatwierdzenia do bieżącej wersji roboczej, aby sprawdzić, czy integrują się poprawnie. Powszechną praktyką jest używanie automatycznej ciągłej integracji, chociaż można to zrobić ręcznie. Automatyczna ciągła integracja wykorzystuje serwer lub demon ciągłej integracji do monitorowania systemu kontroli wersji pod kątem zmian, a następnie automatycznie uruchamia proces kompilacji.

Każde zatwierdzenie poprawki błędu powinno zawierać przypadek testowy

Podczas naprawiania błędu dobrą praktyką jest wypchnięcie przypadku testowego, który odtwarza błąd. Pozwala to uniknąć cofnięcia poprawki i ponownego pojawienia się błędu, co jest znane jako regresja . Badacze zaproponowali zautomatyzowanie tego zadania: jeśli zatwierdzenie naprawiające błąd nie zawiera przypadku testowego, można go wygenerować z już istniejących testów.

Utrzymuj kompilację szybko

Kompilacja musi zostać szybko ukończona, aby w przypadku problemów z integracją został szybko zidentyfikowany.

Przetestuj na klonie środowiska produkcyjnego

Posiadanie środowiska testowego może prowadzić do awarii testowanych systemów podczas ich wdrażania w środowisku produkcyjnym, ponieważ środowisko produkcyjne może znacząco różnić się od środowiska testowego. Jednak zbudowanie repliki środowiska produkcyjnego jest zbyt kosztowne. Zamiast tego należy zbudować środowisko testowe lub oddzielne środowisko przedprodukcyjne („staging”), aby było skalowalną wersją środowiska produkcyjnego w celu zmniejszenia kosztów przy jednoczesnym zachowaniu składu i niuansów stosu technologicznego . W tych środowiskach testowych wirtualizacja usług jest powszechnie stosowana w celu uzyskania dostępu na żądanie do zależności (np. interfejsów API, aplikacji innych firm, usług, komputerów mainframe itp.), które są poza kontrolą zespołu, wciąż ewoluują lub są zbyt skomplikowane do skonfigurowania w wirtualnym laboratorium testowym.

Ułatw uzyskiwanie najnowszych materiałów

Udostępnienie kompilacji dla interesariuszy i testerów może zmniejszyć ilość przeróbek koniecznych podczas przebudowy funkcji, która nie spełnia wymagań. Ponadto wczesne testowanie zmniejsza szanse, że defekty przetrwają do momentu wdrożenia. Wcześniejsze znajdowanie błędów może zmniejszyć ilość pracy niezbędnej do ich rozwiązania.

Wszyscy programiści powinni rozpocząć dzień od aktualizacji projektu z repozytorium. W ten sposób wszystkie będą na bieżąco.

Każdy może zobaczyć wyniki najnowszej wersji

Powinno być łatwe ustalenie, czy kompilacja uległa awarii, a jeśli tak, to kto dokonał odpowiedniej zmiany i co to była za zmiana.

Zautomatyzuj wdrażanie

Większość systemów CI umożliwia uruchamianie skryptów po zakończeniu kompilacji. W większości sytuacji możliwe jest napisanie skryptu wdrażającego aplikację na aktywnym serwerze testowym, na który każdy może się przyjrzeć. Dalszym postępem w tym sposobie myślenia jest ciągłe wdrażanie , które wymaga wdrożenia oprogramowania bezpośrednio do produkcji, często z dodatkową automatyzacją, aby zapobiec defektom lub regresjom.

Koszty i korzyści

Ciągła integracja ma przynosić korzyści, takie jak:

  • Błędy integracji są wykrywane wcześnie i można je łatwo wyśledzić dzięki małym zestawom zmian. Oszczędza to zarówno czas, jak i pieniądze przez cały czas trwania projektu.
  • Unika chaosu w ostatniej chwili w dniu premiery, kiedy wszyscy próbują sprawdzić swoje nieco niekompatybilne wersje
  • Gdy testy jednostkowe nie powiodą się lub pojawi się błąd , jeśli programiści muszą przywrócić kod do stanu wolnego od błędów bez debugowania , tylko niewielka liczba zmian zostanie utracona (ponieważ integracja zdarza się często)
  • Stała dostępność „aktualnej” kompilacji do celów testowych, demonstracyjnych lub wydawniczych
  • Częste ewidencjonowanie kodu zmusza programistów do tworzenia modułowego, mniej złożonego kodu

Dzięki ciągłym testom automatycznym korzyści mogą obejmować:

  • Wymusza dyscyplinę częstych testów automatycznych
  • Natychmiastowa informacja zwrotna na temat ogólnosystemowych skutków zmian lokalnych
  • Metryki oprogramowania generowane z automatycznego testowania i CI (takich jak metryki dla pokrycia kodu , kodu złożoności i funkcji kompletności ) deweloperów koncentruje się na rozwoju funkcjonalnego, kodu jakości oraz pomoc w rozwoju pędu w zespole

Niektóre wady ciągłej integracji mogą obejmować:

  • Stworzenie zautomatyzowanego zestawu testów wymaga znacznego nakładu pracy, w tym ciągłego wysiłku w celu objęcia nowych funkcji i podążania za celowymi modyfikacjami kodu.
  • Skonfigurowanie systemu kompilacji wymaga pewnego nakładu pracy , który może stać się skomplikowany, co utrudnia elastyczną modyfikację.
  • Ciągła integracja niekoniecznie jest wartościowa, jeśli zakres projektu jest mały lub zawiera nietestowalny starszy kod.
  • Wartość dodana zależy od jakości testów i tego, jak naprawdę testowalny jest kod.
  • Większe zespoły oznaczają, że nowy kod jest stale dodawany do kolejki integracji, więc śledzenie dostaw (przy zachowaniu jakości) jest trudne, a kolejkowanie kompilacji może spowolnić wszystkich.
  • Przy wielu zatwierdzeniach i scaleniach dziennie, częściowy kod funkcji może być łatwo wypchnięty, a zatem testy integracji zakończą się niepowodzeniem, dopóki funkcja nie zostanie ukończona.
  • Bezpieczeństwo i zapewnienie rozwoju o znaczeniu krytycznym (np. DO-178C , ISO 26262 ) wymagają rygorystycznej dokumentacji i przeglądu w trakcie procesu, co jest trudne do osiągnięcia przy użyciu ciągłej integracji. Ten rodzaj cyklu życia często wymaga wykonania dodatkowych kroków przed wydaniem produktu, gdy wymagane jest zatwierdzenie produktu przez organy regulacyjne.

Zobacz też

Bibliografia

Zewnętrzne linki