Jak uniknąć rozwoju opartego na CI…?

45

Pracuję nad bardzo dużym projektem open source prowadzonym przez badania, z udziałem wielu innych regularnych współpracowników. Ponieważ projekt jest obecnie dość duży, konsorcjum (złożone z dwóch pełnoetatowych pracowników i kilku członków) odpowiada za utrzymanie projektu, ciągłą integrację (CI) itp. Po prostu nie mają czasu na integrację zewnętrznych wkłady.

Projekt składa się z „podstawowego” frameworka, zawierającego około pół miliona wierszy kodu, wiązki „wtyczek” utrzymywanych przez konsorcjum oraz kilku zewnętrznych wtyczek, z których większość nie jest nawet zdaje sobie z tego sprawę.

Obecnie nasz CI buduje rdzeń i utrzymywane wtyczki.

Jednym z dużych problemów, przed którymi stoimy, jest to, że większość współpracowników (a zwłaszcza okazjonalnych) nie buduje 90% utrzymywanych wtyczek, więc kiedy proponują zmiany w rdzeniu (które obecnie zdarzają się dość regularnie), sprawdzili, czy kod kompiluje się na ich komputerze przed wysłaniem żądania ściągania w GitHub.

Kod działa, są szczęśliwi, a następnie CI kończy budowanie i zaczynają się problemy: kompilacja nie powiodła się w utrzymywanej przez konsorcjum wtyczce, której współtwórca nie zbudował na swoim komputerze.

Ta wtyczka może zależeć od bibliotek stron trzecich, takich jak na przykład CUDA , a użytkownik nie chce, nie wie, jak, lub po prostu nie może z powodów sprzętowych, skompilować tej uszkodzonej wtyczki.

Tak więc - albo pobyty PR ad aeternam w otchłań nie-do-połączyły PRS - Albo specjalista greps przemianowaną zmienną w źródle łamanego plugin zmienia Kodeksu naciska na jego / jej oddziału, czeka na CI, aby zakończyć kompilację, zwykle dostaje więcej błędów i powtarza proces, dopóki CI nie będzie zadowolony - Lub jeden z dwóch już przepełnionych stałych konsorcjów podaje rękę i próbuje naprawić PR na swoim komputerze.

Żadna z tych opcji nie jest wykonalna, ale po prostu nie wiemy, jak to zrobić inaczej. Czy kiedykolwiek spotkałeś się z podobną sytuacją swoich projektów? A jeśli tak, jak poradziłeś sobie z tym problemem? Czy istnieje rozwiązanie, którego tu nie widzę?

lagarkane
źródło
84
Najważniejszą zasadą zapewniania API wtyczek do systemu jest to, że jest on stabilny lub przynajmniej kompatybilny wstecz. Zmiany w rdzeniu bez celowych zmian w interfejsie API wtyczek nigdy nie przerywają kompilacji żadnych wtyczek (może się zdarzyć, że zepsuje funkcjonowanie przez przypadek, ale nie kompilację). Jeśli prosta zmiana nazwy zmiennej w rdzeniu może prowadzić do zepsutej kompilacji wtyczki , separacja między wtyczkami a rdzeniem wydaje się całkowicie zepsuta.
Doc Brown,
1
@KevinKrumwiede: Jestem pewien, że już to wiedzą ;-) Jeśli doświadczyłeś niezgodności, jestem pewien, że celowo zmienili interfejs API.
Doc Brown,
3
Chciałbym przeformułować pytanie, ponieważ jest ono naprawdę mylące. Coś w rodzaju Jak mogę zarządzać PRami, gdy łamią nasz obecny CI? lepiej uchwycić swoją sytuację, myślę.
bracco23
2
Jak trudny / złożony jest proces kompilacji / testowania? Powinno to polegać tylko na uruchomieniu jednego polecenia lub kliknięciu jednego przycisku. W tym momencie uzasadnione jest oczekiwanie, że użytkownicy przeprowadzą wszystkie testy dla siebie przed przesłaniem PR.
Alexander

Odpowiedzi:

68

Rozwój oparty na CI jest w porządku! Jest to o wiele lepsze niż brak uruchamiania testów i włączanie uszkodzonego kodu! Jest jednak kilka rzeczy, które mogą to ułatwić wszystkim zaangażowanym:

  • Określ oczekiwania: przygotuj dokumentację dotyczącą wkładu, która wyjaśnia, że ​​CI często znajduje dodatkowe problemy i że będą musiały zostać naprawione przed scaleniem. Być może wyjaśnij, że małe, lokalne zmiany są bardziej prawdopodobne, że dobrze się sprawdzi - więc podzielenie dużej zmiany na wiele PR może być rozsądne.

  • Zachęcaj do testowania lokalnego: Ułatw konfigurację środowiska testowego dla swojego systemu. Skrypt weryfikujący, czy wszystkie zależności zostały zainstalowane? Kontener Docker, który jest gotowy do pracy? Obraz maszyny wirtualnej? Czy Twój tester ma mechanizmy, które pozwalają na ważniejsze testy?

  • Wyjaśnij, jak używać CI dla siebie: Częścią frustracji jest to, że ta informacja zwrotna pojawia się dopiero po przesłaniu PR. Jeśli współautorzy skonfigurują CI dla swoich własnych repozytoriów, otrzymają wcześniejsze opinie i wygenerują mniej powiadomień CI dla innych osób.

  • Rozwiąż wszystkie PR, tak czy inaczej: Jeśli czegoś nie można scalić, ponieważ jest zepsute, i jeśli nie ma postępu w usuwaniu problemów, po prostu go zamknij. Te porzucone otwarte PR po prostu zaśmiecają wszystko, a każda informacja zwrotna jest lepsza niż ignorowanie problemu. Można to bardzo ładnie sformułować i wyjaśnić, że chętnie się połączysz, gdy problemy zostaną naprawione. (patrz także: Sztuka zamknięcia przez Jessie Frazelle , Najlepsze praktyki dla konserwatorów: nauka odmawiania )

    Zastanów się również, czy te opuszczone PR są możliwe do wykrycia, aby ktoś inny mógł je odebrać. Może to być nawet dobre zadanie dla nowych autorów, jeśli pozostałe problemy są bardziej mechaniczne i nie wymagają głębokiej znajomości systemu.

W perspektywie długoterminowej zmiany wydają się łamać niepowiązaną funkcjonalność tak często, że może to oznaczać, że twój obecny projekt jest nieco problematyczny. Na przykład, czy interfejsy wtyczek poprawnie obudowują elementy wewnętrzne twojego rdzenia? C ++ ułatwia przypadkowe wyciekanie szczegółów implementacji, ale umożliwia także tworzenie silnych abstrakcji, których bardzo trudno użyć niewłaściwie. Nie możesz tego zmienić w ciągu nocy, ale możesz poprowadzić długoterminową ewolucję oprogramowania w kierunku mniej delikatnej architektury.

amon
źródło
13
„Te porzucone otwarte PR po prostu zaśmiecają wszystko” Chciałbym, żeby więcej opiekunów miało takie podejście 😔
GammaGames
34

Budowanie trwałego modelu wtyczek wymaga, aby Twoja podstawowa struktura udostępniała stabilny interfejs, na którym mogą polegać wtyczki. Złotą zasadą jest to, że możesz z czasem wprowadzać nowe interfejsy, ale nigdy nie możesz modyfikować już opublikowanego interfejsu. Jeśli zastosujesz się do tej zasady, możesz refaktoryzować implementację podstawowego frameworka bez obawy przypadkowego zerwania wtyczek, niezależnie od tego, czy jest to konsorcjum, czy zewnętrzne.

Z tego, co opisałeś, wygląda na to, że nie masz dobrze zdefiniowanego interfejsu, co utrudnia stwierdzenie, czy zmiana spowoduje uszkodzenie wtyczek. Pracuj nad zdefiniowaniem tego interfejsu i nadaniem mu wyraźnego charakteru w swojej bazie kodu, aby współautorzy wiedzieli, czego nie powinni modyfikować.

Casablanka
źródło
20
CI powinien mieć zautomatyzowane testy. Jeśli chcesz upewnić się, że wtyczki mają ten sam interfejs, każda wtyczka powinna uczestniczyć w testach wyrażających interfejs, którego potrzebują. Przyjdź do tego w ten sposób, a kiedy interfejs się zmieni, co się stanie, będziesz wiedział, które wtyczki łamiesz. Daj mi te testy, aby uruchomić lokalnie, a zanim wydam PR, dowiem się, co robię.
candied_orange
1
@lagarkane dobrze zdefiniowane jest bardziej kwestią polityczną niż techniczną. Istnieją programy, które podobnie jak twoje, po prostu porzuć poprzednie zachowanie podczas aktualizacji. Perl5 nie jest kompatybilny z Perl6, Python2.7 nie jest w pełni kompatybilny z Python3.4 itp. Następnie istnieje oprogramowanie, które cokolwiek się stanie, nadal obsługuje stary kod. Nadal możesz uruchomić prawie cały kod javascript napisany dla Netscape Navigator 4 we współczesnych przeglądarkach. Język programowania Tcl jest kompatybilny z backwords z powrotem do oryginalnej wersji itp.
Slebetman
3
@lagarkane: Utworzenie konsorcjum było krokiem we właściwym kierunku, a jeśli członkowie kluczowi skoncentrują swoją energię na tworzeniu tych interfejsów, możesz wykorzystać moc przyszłych doktorantów i stażystów, aby utrzymać silny projekt przy minimalizacji uszkodzeń. :)
Casablanca,
4
@Fattie: Działa to dla Apple, ponieważ tworzą udane produkty skierowane do konsumentów, a programiści muszą grać razem, jeśli chcą być częścią tego. Jest mało prawdopodobne, aby ci programiści naprawdę lubili przełamywanie zmian i zdecydowanie nie jest to dobry model dla projektu typu open source.
casablanca
1
@casablanca, zarówno MacOS, jak i WindowsOS, odniosły ogromny sukces. (Prawdopodobnie dwa największe produkty w kategoriach zwykłego dolara w ludzkiej egzystencji.) Przez dziesięciolecia mieli całkowicie przeciwne podejście. Najwyraźniej oba były udane!
Fattie,
8

Szczerze mówiąc, nie sądzę, że można sobie z tym poradzić w lepszy sposób - jeśli zmiany spowodują uszkodzenie utrzymywanych części projektu, CI powinien zawieść.

Czy twój projekt ma contributing.mdcoś podobnego, aby pomóc nowym i okazjonalnym współpracownikom w przygotowaniu swojego wkładu? Czy masz jasną listę, które wtyczki są częścią rdzenia i muszą pozostać kompatybilne?

Jeśli trudno jest zbudować wszystko na komputerze z powodu zależności itp., Możesz pomyśleć o tworzeniu gotowych do użycia obrazów dokerów jako środowisk kompilacji, z których będą mogli korzystać współtwórcy.

mhr
źródło
1
Dziękuję za odpowiedź! Tak, udostępniamy publicznie wytyczne, ale nie zawiera listy wtyczek, które sugerujesz, co byłoby dobrym pomysłem. Tworzenie obrazów dokerów wydaje się już świetnym ulepszeniem obecnego procesu współtworzenia! Dzięki za wkład
lagarkane
8

więc kiedy proponują zmiany refaktoryzacji w rdzeniu (co obecnie zdarza się dość regularnie), sprawdzili, czy kod kompiluje się na ich maszynie przed wysłaniem żądania ściągnięcia na github.

Myślę więc, że tutaj może upaść luźny styl projektów open source; większość centralnie zorganizowanych projektów jest ostrożna w zakresie refaktoryzacji rdzenia, szczególnie gdy przekracza ona granicę API. Jeśli dokonają refaktoryzacji granicy interfejsu API, zwykle jest to „wielki wybuch”, w którym wszystkie zmiany są planowane jednocześnie z przyrostem głównej wersji interfejsu API, a stary interfejs API zostaje zachowany.

Proponuję zasadę „wszystkie zmiany API muszą być planowane z wyprzedzeniem”: jeśli pojawi się PR, który spowoduje cofnięcie niezgodnej wstecz do API, ktoś, kto nie był w kontakcie z opiekunami, z góry zgodził się na ich podejście, po prostu się zamyka i zgłaszający wskazuje na regułę.

Będziesz także potrzebował jawnej wersji interfejsu API wtyczki. Umożliwia to tworzenie wersji 2, podczas gdy wszystkie wtyczki w wersji 1 nadal się budują i działają.

Chciałbym również zadać trochę więcej pytania, dlaczego wprowadzono tak wiele podstawowych zmian refaktoryzacji i zmian API. Czy są naprawdę potrzebni, czy po prostu ludzie narzucają projekt osobisty gust?

pjc50
źródło
2

Wygląda na to, że proces CI musi być ściślejszy, bardziej kompleksowy i bardziej widoczny dla autorów, zanim podniosą PR. Na przykład BitBucket ma funkcję potoków, która pozwala na to, gdy dajesz mu plik, który definiuje w kodzie proces kompilacji CI, a jeśli się nie powiedzie, gałąź nie zostanie scalona.

Bez względu na technologię, automatyczne kompilacje, gdy współtwórca przesyła się do oddziału, dadzą im znacznie szybsze informacje zwrotne na temat tego, na co należy zwracać uwagę podczas wprowadzania zmian i doprowadzą do PR, które nie wymagają naprawy po fakcie.

Problemy projektowe dobrze byłoby naprawić, ale są prostopadłe do tego problemu.

Nathan Adams
źródło
2

Kod działa, są szczęśliwi, a następnie CI kończy budowanie i zaczynają się problemy: kompilacja nie powiodła się w utrzymywanej przez konsorcjum wtyczce, której współtwórca nie zbudował na swoim komputerze.

Ta wtyczka może zależeć od bibliotek stron trzecich, takich jak na przykład CUDA, a użytkownik nie chce, nie wie, jak, lub po prostu nie może z powodów sprzętowych, skompilować tej uszkodzonej wtyczki.

Twoje rozwiązanie jest proste: obniż barierę wkładu .

Najprostszym sposobem (1) przyspieszenia cyklu edycji-kompilacji-testu oraz (2) płynnego różnicowania środowiska jest zapewnienie serwerów kompilacji :

  • Podnieś mocne maszyny: 24, 48 lub 96 rdzeni, 2 GB pamięci RAM / rdzeń, dysk SSD, aby przyspieszyć kompilację.
  • Upewnij się, że mają odpowiedni sprzęt: FPGA, karta graficzna, cokolwiek jest potrzebne.
  • Utwórz obraz Docker ze wstępnie zainstalowanymi wszystkimi niezbędnymi bibliotekami oprogramowania.

A następnie otwórz te serwery kompilacji dla współpracowników. Powinni mieć możliwość zdalnego zalogowania się na nowym obrazie Docker oraz zdalnej edycji-testu-kompilacji na tym komputerze.

Następnie:

  • Nie mają wymówki, by nie budować / testować utrzymywanych wtyczek: mają wszystko dostępne.
  • Nie muszą czekać na długie opinie z PR opartymi na CI: mają przyrostową kompilację i możliwość debugowania (zamiast zgadywania).

Ogólnie rzecz biorąc, serwery kompilacji mogą być współużytkowane przez wielu współautorów, jednak gdy zaangażowane są specjalne sprzętowe urządzenia peryferyjne, może być konieczne, aby współtwórca sam używał wspomnianych urządzeń peryferyjnych.


Źródło: pracując nad oprogramowaniem wykorzystującym układy FPGA, biorąc pod uwagę cenę bestii i różnorodność modeli, których potrzebujemy, nie znajdziesz każdego modelu układu FPGA zainstalowanego na każdym komputerze dewelopera.

Matthieu M.
źródło
1

Jeśli wkład w rdzeń bez zmiany jakiejkolwiek umowy może spowodować uszkodzenie oprogramowania zależnego, sugeruje to, że:

  • Umowy dotyczące interfejsów mogą być niejednoznaczne. Może dodanie atrybutów do funkcji i parametrów funkcji pomogłoby w ujawnieniu dodatkowych ograniczeń w kodzie klienta, aby umowy były jaśniejsze. Lub jeśli stosujesz zmiany, które mogą doprowadzić do zerwania kontraktu, być może pomocne może być zastosowanie wersji semantycznej.
  • Testy jednostkowe nie obejmują wystarczającej liczby możliwych scenariuszy połączeń.

Oba problemy powinny być łatwe do rozwiązania, ale wspominasz, że zespół podstawowy może nie mieć takiej możliwości. Jedną z opcji byłoby zwrócenie się do społeczności o pomoc w rozwiązaniu problemu.

jcayzac
źródło
1

Wydaje się, że nikt inny nie podniósł tego jako potencjalnego rozwiązania.

  • wypisz wszystkie wtyczki, do których masz dostęp.
  • uruchom wszystkie testy zdefiniowane przez te wtyczki
  • rejestruj wszystkie żądania / odpowiedzi / interakcje między rdzeniem a wszystkimi wtyczkami
  • przechowuj te nagrania, są to z grubsza testy zgodności.

Podczas opracowywania rdzenia zachęcaj programistów do uruchamiania testów zgodności. Jeśli się nie uda, nie melduj się.

Nie zapewni to w 100% zgodności, ale wcześnie wykryje o wiele więcej problemów.

Druga korzyść polega na tym, że nagrania te mogą podkreślać, które interfejsy są aktywnie używane i jakie funkcje są aktywnie używane.

Kain0_0
źródło
0

Mam problem ze zrozumieniem obecnej sytuacji: CI buduje tylko jedną gałąź?

Czy istnieje powód, dla którego nie można zbudować więcej niż jednego oddziału za pomocą CI?

Najprostszym rozwiązaniem tego problemu byłoby umożliwienie każdemu współpracownikowi uruchomienia kompilacji CI w jego / jej gałęzi funkcji .

Następnie po prostu potrzebujesz udanej kompilacji CI w gałęzi funkcji, aby zaakceptować żądanie ściągnięcia tej gałęzi.

Kyralessa
źródło
To wydaje się podsumować problem.
Fattie
1
Pytanie brzmi: „Albo współautor [...] zmienia kod, naciska na swoją gałąź, czeka na zakończenie kompilacji przez CI, zwykle dostaje więcej błędów i powtarza proces, aż CI będzie zadowolony” - więc myślę, że to jest już w tym przypadku, ale problem polega na tym, że opracowanie tego długiego cyklu edycji i debugowania jest nieco bolesne.
npostavs
@npostavs Dzięki, myślę, że za tym tęskniłem za pierwszym lub dwoma czytaniem. Mimo to ... Chyba nie wydaje mi się, że to problem. Istnieje wiele zależności, których nie można złamać, więc współpracownik musi pozostać kompatybilny ze wszystkimi. Taka jest natura dużego oprogramowania. Z pewnością można by zrobić pracę, aby przyspieszyć kompilację, ale w przeciwnym razie jaki mógłby być skrót?
Kyralessa