Ten artykuł jest lustrzanym artykułem tłumaczenia maszynowego, kliknij tutaj, aby przejść do oryginalnego artykułu.

Widok: 1081|Odpowiedź: 1

Krótkie wprowadzenie do Reproducible Build

[Skopiuj link]
Opublikowano 30.04.2025 10:09:27 | | | |
Czym jest powtarzalny build?

Deterministyczny build lub Reproducible Build to nieco inne cechy, ale można je zrozumieć jako to samo, co można powiedzieć w tym artykule.

Konstrukcje powtarzalne odnoszą się doWielokrotne uruchomienia procesu budowania przy tym samym wejściu i środowisku budowania mogą dać dokładnie te same rezultaty。 Technologia ta jest ważna dla tworzenia oprogramowania, dystrybucji i weryfikacji bezpieczeństwa.

Build jest powtarzalny, jeśli dostarcza dokładnie ten sam wynik niezależnie od czasu i miejsca uruchomienia. Niezależnie od tego, na jakim komputerze działasz, o jakiej porze dnia i jakie zewnętrzne usługi korzystasz przez sieć, powtarzalne kompilacje generują ten sam bajt po bajcie wyjścia. To świetne zarówno dla tworzenia (ponieważ reproducowalne kompilacje łatwo udostępniać na różnych urządzeniach deweloperskich), jak i produkcji (ponieważ łatwo upewnić się, że wyniki reprotwornych kompilacji nie zostały zmienione – wystarczy ponownie uruchomić kompilację na własnym komputerze i sprawdzić, czy wyniki są spójne!). są bardzo przydatne.



Trzy filary powtarzalnych konstrukcji

Filar 1: Powtarzalne buildy

Powtarzalność budowy odnosi się do tego, co dzieje się z samą maszyną do budowania. Zakładając, że nasze dane wejściowe są dostępne i nic się nie zmienia w otaczającym nas świecie, czy nasz build generuje ten sam wynik po powtórzeniu?

Plan instalacji deterministycznej

Pierwszym, najprostszym i najbardziej oczywistym wymogiem w powtarzalnej budowie jest deterministyczny plan instalacji zależności.

W większości języków wystarczy sprawdzić zablokowany plik. Nowoczesne narzędzia budowania często pozwalają projektom wyrażać bezpośrednie wymagania zależności jako ograniczenia, a następnie rozwiązywać te ograniczenia, generując plan instalacji (listę nazw zależności i par wersji do instalacji). Wiele z tych narzędzi generuje także pliki blokad dla serializowanych planów instalacji. Programiści mogą przesyłać te pliki blokad do kontroli wersji, tak aby przyszłe wersje używały tych samych nazw i wersji zależności.

Należy zauważyć, że potrzebujemy determinizmu także w samej budowie zależności (nie tylko wyboru wersji), a deterministyczny plan instalacji nie pozwala nam tego osiągnąć!

Konstrukcja deterministyczna

Gdy już wiemy, co zbudować, nasza budowa (w tym nasz własny kod i kod zależności) musi być faktycznie deterministyczna.

To może nie być problem dla projektów bez kroku kompilacji! Na przykład projekt Node ze wszystkimi zależnościami to czysty JavaScript i nie wymaga dodatkowej pracy, aby osiągnąć efektywną deterministyczność.

W projektach, które obejmują etapy kompilacji lub tłumaczenia (kompilacja źródło-źródłowe), zapewnienie determinizmu jest zdecydowanie najtrudniejszą częścią tworzenia powtarzalnej konstrukcji. Proces kompilacji może domyślnie wprowadzać niedeterministyczność na różne sposoby, w tym:

  • Skrypty budowania programu Turing-complete mogą dowolnie zmieniać skompilowane wyjście.
  • Skrypty po instalacji opierające się na wyszukiwaniach systemu plików lub wywołaniach sieciowych do wykonywalnych plików.
  • Binding C do pakietu zainstalowanego w systemie, gdzie bindingi na różnych systemach z różnymi nagłówkami mogą generować różne wyjścia.
  • Kroki do stworzenia pliku, który odczytuje poza kontrolą wersji.
  • Stwórz kroki do generowania znaczników czasu na podstawie czasu systemowego.
  • Kroki budowania zależności niewyrażonych w planie instalacji pobrania sieciowego (na przykład pobranie zależności NPM z GitHub dla buforowanego kompilu binarnego ograniczonego do C).
  • Zmień zachowanie na podstawie aktualnie ustawionej zmiennej środowiskowej, ale nie przesyłaj wersji z konfiguracją zmiennej środowiska.


Nie wszystkie te zachowania muszą wprowadzać niepewność, gdy są poprawnie skonfigurowane, ale prawidłowa konfiguracja procesu budowania może być skomplikowana i trudna. Na przykład możesz przeczytać ten wpis na blogu o niepewności w buildach Chromium. Wiele z tych problemów można złagodzić poprzez kontrolę lokalnego środowiska budowy, o czym omówimy w następnej sekcji.

Filar 2: Niezmienne środowisko

Nawet przy powtarzalnych buildach musimy upewnić się, że dane wejściowe buildów się nie zmieniają. Często oznacza to, że chcemy budować na niezmiennym obrazie otoczenia.

Niezmienne środowisko lokalne

Jak omówiliśmy powyżej, częstym źródłem niepewności budowania jest poleganie na "zależnościach", które nie są rejestrowane przez narzędzie budowania. Biblioteki systemowe ograniczone w C są najczęstszymi przykładami, ale także inne lokalne czynniki środowiskowe, takie jak ustawienia zmiennych środowiskowych czy pliki spoza kontroli wersji, mogą również wpływać na kompilację.

Łatwym sposobem na rozwiązanie tego problemu jest uruchomienie builda w znanym, niezmiennym kontenerze. Na przykład środowisko uruchomieniowe kontenera, takie jak Docker, pomaga zapewnić, że wszyscy korzystają z tych samych zależności systemowych, tych samych zmiennych środowiskowych i działają na tym samym systemie plików. Ponadto łatwo jest zweryfikować, czy zawartość kontenera odpowiada znanemu dobremu kontenerowi budowlanym, a jeśli zajdzie taka potrzeba, można go łatwo całkowicie usunąć z obrazu znanego dobra i odtworzyć.

Należy zauważyć, że jesteśmy bardzo jasni co do znanych kontenerów lub znanych obrazów kontenerów. Nie wystarczy tylko przesłać Dockerfile! Dlaczego? Ponieważ sam plik Dockera nie opisuje w pełni powtarzalnego procesu budowania obrazów Docker, ponieważ nie działają one w niezmiennym środowisku globalnym.

Niezmienne środowisko globalne

Systemy budowania często współdziałają z usługami zewnętrznymi, aby wykonać zadania takie jak rozwiązywanie wersji i pobieranie zależności. Ale usługi zewnętrzne często się zmieniają.

Uruchomienie instalacyjnych nodejów na apt dziś da inne wyniki niż w zeszłym roku, a prawdopodobnie w przyszłym roku też inne rezultaty. Dlatego same Dockerfile nie potrafią opisać powtarzalnych buildów – uruchamianie tego samego pliku Dockerfile w różnych momentach daje różne wyjścia buildów!

Prostym rozwiązaniem jest konfigurowanie builda, kiedy tylko to możliwe, określając dokładną wersję (najlepiej także dokładny hash content), aby przyszłe buildy korzystały z tej samej wersji co aktualna wersja. Ale usługi zewnętrzne mogą też niespodziewanie zmieniać swoje zachowanie – prawdziwie pesymistyczna powtarzalna wersja uruchamia wewnętrzny obraz z jak największą liczbą zasobów sieciowych.

Filar 3: Dostępność zasobów

Załóżmy, że nasza budowa jest powtarzalna, a świat pod naszymi stopami się nie zmienia. Teraz potrzebujemy tylko dostępu do danych wejściowych do buildów. Wydaje się to proste, prawda? Studnia......

Rejestr czasem zawodzi

Większość programistów Node doświadczyła przynajmniej jednej awarii NPM, podczas której potok budowy bez buforowania lub lustrzania pakietów NPM został zakłócony. Wielu deweloperów Node doświadczyło także usuwania lewego pada i fakerów, które poważnie uszkodziły ekosystem NPM i w praktyce doprowadziły do awarii.

Jedynym niezawodnym sposobem na ograniczenie takich awarii buildów jest uruchomienie własnego mirrory registry package. Gdy usługi zewnętrzne są niedostępne, obraz może pozostać online; Gdy oficjalny rejestr usunie stary pakiet, lustrzane odbicie może nadal świadczyć usługi. Ta sama zasada dotyczy innych usług zdalnych: jeśli nie uruchomisz własnego obrazu, dostępność pipeline'u build jest porównywalna tylko z dostępnością jego usług.

Decyzja o prowadzeniu wizerunku usługi to zawsze delikatny kompromis. Z jednej strony rejestry takie jak NPM mają dedykowane zespoły inżynieryjne i operacyjne, które mają wiedzę, by utrzymać te systemy w ruchu. Z drugiej strony, znacznie łatwiej jest uruchomić mały obraz dla niewielkiego zestawu zależności niż wszystkie obrazy NPM. Powinieneś podejmować decyzje odzwierciedlające ich na podstawie specyfiki każdej usługi, biorąc pod uwagę wiarygodność historycznych usług zewnętrznych oraz dostępność i potrzeby kadrowe zespołu.

Dostawcy zapewniają maksymalną dostępność

Prostym sposobem na zapewnienie maksymalnej dostępności zależności projektu jest dodanie ich do dostawcy. Większość menedżerów pakietów wspiera jakąś formę "vendoringu", co oznacza, że zamiast polegać na pobieraniu z zewnętrznych usług, przechowujemy kod źródłowy zależności w kontroli wersji, współistniejąc z naszym kodem źródłowym. Na przykład w Node może to wyglądać jak zatwierdzanie node_modules do kontroli wersji wersyjnej.

Chociaż to rozwiązanie nie jest idealne (w zależności od tego, jak skonfigurowany jest Twój dostawca i projekt, co może obciążać kontrolę wersji), często jest najprostszym i najłatwiejszym rozwiązaniem dla maksymalnej dostępności.

Odniesienie:

Logowanie do linku jest widoczne.
Logowanie do linku jest widoczne.




Poprzedni:.NET/C# Użyj UnsafeAccessor do modyfikacji zawartości pola tylko do odczytu
Następny:Angular 18 Series (32) ControlValueOr niestandardowe kontrole formularzy
 Ziemianin| Opublikowano 30.04.2025 10:10:23 |
O używaniu powtarzalnych kompilacji podczas tworzenia pakietów NuGet w C#:

Logowanie do linku jest widoczne.
Logowanie do linku jest widoczne.
Zrzeczenie się:
Całe oprogramowanie, materiały programistyczne lub artykuły publikowane przez Code Farmer Network służą wyłącznie celom edukacyjnym i badawczym; Powyższe treści nie mogą być wykorzystywane do celów komercyjnych ani nielegalnych, w przeciwnym razie użytkownicy ponoszą wszelkie konsekwencje. Informacje na tej stronie pochodzą z Internetu, a spory dotyczące praw autorskich nie mają z nią nic wspólnego. Musisz całkowicie usunąć powyższą zawartość z komputera w ciągu 24 godzin od pobrania. Jeśli spodoba Ci się program, wspieraj oryginalne oprogramowanie, kup rejestrację i korzystaj z lepszych, autentycznych usług. W przypadku naruszenia praw prosimy o kontakt mailowy.

Mail To:help@itsvse.com