Dieser Artikel ist ein Spiegelartikel der maschinellen Übersetzung, bitte klicken Sie hier, um zum Originalartikel zu springen.

Ansehen: 1081|Antwort: 1

Eine kurze Einführung in Reproducible Build

[Link kopieren]
Veröffentlicht am 30.04.2025, 10:09:27 | | | |
Was ist ein wiederholbarer Build?

Deterministischer Build oder Reproduzierbarer Build sind leicht unterschiedlich, können aber als dasselbe verstanden werden, wie in diesem Artikel.

Reproduzierbare Builds beziehen sich auf dieMehrere Ausführungen des Build-Prozesses mit derselben Eingabe und derselben Build-Umgebung können exakt die gleichen Ergebnisse liefern。 Diese Technologie ist wichtig für Softwareentwicklung, Verbreitung und Sicherheitsvalidierung.

Ein Build ist reproduzierbar, wenn er unabhängig davon, wann und wo er ausgeführt wird, exakt denselben Output liefert. Egal, auf welchem Computer Sie laufen, zu welcher Tageszeit und auf welche externen Dienste Sie über das Netzwerk zugreifen, reproduzierbare Builds liefern die gleiche Byte-für-Byte-Ausgabe. Das ist sowohl für die Entwicklung (weil reproduzierbare Builds leicht über verschiedene Entwicklergeräte verteilt werden können) als auch für die Produktion (weil es einfach ist, sicherzustellen, dass die Ergebnisse reproduzierbarer Builds nicht manipuliert wurden – führe den Build einfach auf deinem eigenen Rechner erneut aus und prüfe, ob die Ergebnisse konsistent sind!). sind sehr nützlich.



Die drei Säulen wiederholbarer Bauten

Säule 1: Wiederholbare Builds

Build-Wiederholbarkeit bezieht sich darauf, was mit der Build-Maschine selbst passiert. Angenommen, unsere Build-Eingaben sind verfügbar und sich in der Welt um uns herum nichts ändert, erzeugt unser Build dann beim Wiederholen denselben Output?

Deterministischer Installationsplan

Die erste, einfachste und offensichtlichste Voraussetzung bei einem wiederholbaren Bau ist ein deterministischer Installationsplan für Abhängigkeit.

In den meisten Sprachen ist es so einfach, eine gesperrte Datei einzuchecken. Moderne Build-Tools erlauben es Projekten oft, direkte Abhängigkeitsanforderungen als Constraints auszudrücken und diese dann aufzulösen, um einen Installationsplan zu erstellen (eine Liste von Abhängigkeitsnamen und Versionspaaren zu installieren). Viele dieser Tools erstellen auch Sperrdateien für serialisierte Installationspläne. Entwickler können diese Sperrdateien der Versionskontrolle vorlegen, damit zukünftige Builds dieselben Abhängigkeitsnamen und Versionen verwenden.

Beachten Sie, dass wir auch deterministisch im Dependenz-Build selbst benötigen (nicht nur in der Versionsauswahl), und ein deterministischer Installationsplan erlaubt uns das nicht!

Deterministische Konstruktion

Sobald wir wissen, was wir bauen sollen, muss unser Build selbst (einschließlich unseres eigenen Codes und des Builds des Abhängigkeitscodes) tatsächlich deterministisch sein.

Das ist vielleicht kein Problem für Projekte ohne Kompilierungsschritt! Zum Beispiel ist ein Node-Projekt mit allen Abhängigkeiten reines JavaScript, und es ist keine zusätzliche Arbeit erforderlich, um eine effektive Deterministizität zu erreichen.

Für Projekte, die Kompilierungs- oder Übersetzungsschritte (Quellcode-zu-Quelle-Kompilierung) enthalten, ist Determinismus bei weitem der schwierigste Teil beim Erstellen eines reproduzierbaren Builds. Der Kompilierungsprozess kann implizit Nichtdeterminismus auf verschiedene Weise einführen, darunter:

  • Turing-vollständige Programm-Build-Skripte können die kompilierte Ausgabe nach Belieben ändern.
  • Nachinstallationsskripte, die auf ausführbaren Dateisystemsuchen oder Netzwerkaufrufen angewiesen sind.
  • C-Bindung an ein systeminstalliertes Paket, bei dem Bindungen auf verschiedenen Systemen mit unterschiedlichen Headern unterschiedliche Ausgaben erzeugen können.
  • Schritte, um eine Datei zu erstellen, die außerhalb der Versionskontrolle gelesen werden kann.
  • Erstelle Schritte, um Zeitstempel mithilfe der Systemzeit zu generieren.
  • Schritte zum Erstellen von Abhängigkeiten, die im Netzwerk-Download-Installationsplan nicht ausgedrückt sind (zum Beispiel eine NPM-Abhängigkeit von GitHub für einen C-gebundenen Cache-Binärbuild herunterladen).
  • Ändere das Verhalten basierend auf der aktuell gesetzten Umgebungsvariable, reiche aber keinen Build mit der Konfiguration der Umweltvariablen ein.


Nicht alle diese Verhaltensweisen führen bei korrekter Einrichtung zwangsläufig zu Unsicherheit, aber die richtige Konfiguration des Bauprozesses kann komplex und schwierig sein. Zum Beispiel können Sie diesen Blogbeitrag über Unsicherheit bei Chromium-Builds lesen. Viele dieser Probleme können durch die Kontrolle des lokalen Bauumfelds gemildert werden, worauf wir im nächsten Abschnitt eingehen werden.

Säule 2: Unveränderliche Umgebung

Selbst bei wiederholbaren Builds müssen wir sicherstellen, dass sich die Build-Eingaben nicht ändern. Oft bedeutet das, dass wir sicherstellen wollen, dass wir auf einem unveränderlichen Schnappschuss unserer Umgebung aufbauen.

Unveränderliches lokales Umfeld

Wie oben besprochen, ist eine häufige Quelle für Build-Unsicherheit die Abhängigkeit von "Abhängigkeiten", die vom Build-Tool nicht erfasst werden. C-gebundene Systembibliotheken sind die häufigsten Beispiele, aber auch andere lokale Umweltfaktoren wie Umgebungsvariableneinstellungen und Dateien außerhalb des Versionskontrollbereichs können den Build beeinflussen.

Eine einfache Möglichkeit, dieses Problem zu mindern, besteht darin, den Build in einem bekannten, unveränderlichen Container auszuführen. Zum Beispiel hilft eine Containerlaufzeit wie Docker sicherzustellen, dass alle dieselben Systemabhängigkeiten, dieselben Umweltvariablen verwenden und auf demselben Dateisystem laufen. Außerdem ist es einfach zu überprüfen, ob der Inhalt des Containers mit einem bekannten guten Build-Container übereinstimmt, und falls nötig, kann der Container ganz aus dem bekannten guten Image entfernt und neu erstellt werden.

Beachten Sie, dass wir uns sehr klar über bekannte Container oder bekannte Containerabbildungen befinden. Es reicht nicht, einfach eine Dockerfile einzureichen! Warum? Weil die Dockerfile selbst keinen vollständig reproduzierbaren Build-Prozess für Docker-Images beschreibt, da sie nicht in einer unveränderlichen globalen Umgebung laufen.

Unveränderliches globales Umfeld

Build-Systeme interagieren häufig mit externen Diensten, um Aufgaben wie Versionsauflösung und Downloads von Abhängigkeiten zu erledigen. Aber externe Dienste ändern sich häufig.

Wenn du heute apt install nodejs benutzt, wirst du andere Ergebnisse liefern als im letzten Jahr, und wahrscheinlich auch im nächsten Jahr andere Ergebnisse. Deshalb können Dockerfiles selbst keine reproduzierbaren Builds beschreiben – das Ausführen derselben Dockerfile zu unterschiedlichen Zeitpunkten erzeugt unterschiedliche Build-Ausgaben!

Die einfache Minderung besteht darin, den Build wann immer möglich zu konfigurieren und eine exakte Version (idealerweise auch einen exakten Inhalts-Hash) anzugeben, damit zukünftige Builds dieselbe Version wie der aktuelle Build verwenden. Aber externe Dienste können ihr Verhalten auch unerwartet ändern – ein wirklich pessimistischer, reproduzierbarer Build betreibt ein internes Image mit so vielen Netzwerkressourcen wie möglich.

Säule 3: Verfügbarkeit von Ressourcen

Angenommen, unser Build ist wiederholbar und die Welt unter unseren Füßen verändert sich nicht. Alles, was wir jetzt brauchen, ist der Zugriff auf die Build-Eingabe. Es klingt einfach, oder? Brunnen......

Das Register scheitert manchmal

Die meisten Node-Entwickler haben mindestens einen NPM-Ausfall erlebt, während dessen die Build-Pipeline ohne Caching oder Mirroring von NPM-Paketen gestört wird. Viele Node-Entwickler haben auch Left-Pad- und Faker-Entfernungen erlebt, die das NPM-Ökosystem schwer beschädigt und effektiv zu einem Ausfall geführt haben.

Die einzige verlässliche Möglichkeit, solche Build-Breaks zu mindern, ist das eigene Paket-Registry-Mirror. Wenn externe Dienste nicht verfügbar sind, kann das Bild online bleiben; Wenn das offizielle Register das alte Paket löscht, kann der Spiegel weiterhin Dienste bereitstellen. Das gleiche Prinzip gilt für andere entfernte Dienste: Wenn Sie Ihr eigenes Image nicht ausführen, ist die Verfügbarkeit einer Build-Pipeline nur mit der Verfügbarkeit ihrer Dienste vergleichbar.

Die Entscheidung, ein Dienstleistungsimage zu betreiben, ist immer ein heikler Kompromiss. Einerseits verfügen Register wie NPM über eigene Ingenieur- und Betriebsteams, die über die Expertise verfügen, diese Systeme online zu halten. Andererseits ist es viel einfacher, ein kleines Image für eine kleine Abhängigkeitsmenge auszuführen, als alle NPM-Images auszuführen. Sie sollten Spiegelungsentscheidungen basierend auf den Details jedes Services treffen und dabei die Zuverlässigkeit historischer externer Services sowie die Verfügbarkeit und Personalbedarf Ihres Teams berücksichtigen.

Lieferanten sorgen für maximale Verfügbarkeit

Eine einfache Möglichkeit, die maximale Verfügbarkeit der Abhängigkeiten Ihres Projekts sicherzustellen, besteht darin, sie Ihrem Anbieter hinzuzufügen. Die meisten Paketmanager unterstützen irgendeine Form von "Vendoring", was bedeutet, dass wir statt auf Downloads von externen Diensten den Abhängigkeitscode in der Versionskontrolle speichern, koexistierend mit unserem Quellcode. Zum Beispiel könnte das in Node so aussehen, als würde man node_modules zur Versionskontrolle committen.

Auch wenn diese Lösung nicht perfekt ist (je nachdem, wie Ihr Anbieter und Ihr Projekt aufgebaut sind, was Ihre Versionskontrolle stark belasten kann), ist sie oft die einfachste und einfachste Lösung für maximale Verfügbarkeit.

Referenz:

Der Hyperlink-Login ist sichtbar.
Der Hyperlink-Login ist sichtbar.




Vorhergehend:.NET/C# Verwenden Sie UnsafeAccessor, um den Inhalt von schreibgeschützten Feldern zu ändern
Nächster:Angular 18 Serie (32) ControlValueAccessor benutzerdefinierte Formularsteuerungen
 Vermieter| Veröffentlicht am 30.04.2025, 10:10:23 |
Zum Einsatz wiederholbarer Builds beim Erstellen von NuGet-Paketen in C#:

Der Hyperlink-Login ist sichtbar.
Der Hyperlink-Login ist sichtbar.
Verzichtserklärung:
Alle von Code Farmer Network veröffentlichten Software, Programmiermaterialien oder Artikel dienen ausschließlich Lern- und Forschungszwecken; Die oben genannten Inhalte dürfen nicht für kommerzielle oder illegale Zwecke verwendet werden, andernfalls tragen die Nutzer alle Konsequenzen. Die Informationen auf dieser Seite stammen aus dem Internet, und Urheberrechtsstreitigkeiten haben nichts mit dieser Seite zu tun. Sie müssen die oben genannten Inhalte innerhalb von 24 Stunden nach dem Download vollständig von Ihrem Computer löschen. Wenn Ihnen das Programm gefällt, unterstützen Sie bitte echte Software, kaufen Sie die Registrierung und erhalten Sie bessere echte Dienstleistungen. Falls es eine Verletzung gibt, kontaktieren Sie uns bitte per E-Mail.

Mail To:help@itsvse.com