Cet article est un article miroir de traduction automatique, veuillez cliquer ici pour accéder à l’article original.

Vue: 1081|Répondre: 1

Une brève introduction à Reproducible Build

[Copié le lien]
Publié le 30-04-2025 à 10:09:27 | | | |
Qu’est-ce qu’une construction reproductible ?

La construction déterministe ou la construction reproductible sont légèrement différentes, mais on peut les comprendre comme la même chose d’après cet article.

Les constructions reproductibles désignent lePlusieurs exécutions du processus de compilation avec la même entrée et le même environnement de compilation peuvent produire exactement les mêmes résultats。 Cette technologie est importante pour le développement logiciel, la distribution et la validation de la sécurité.

Une compilation est reproductible si elle fournit exactement la même sortie, quel que soit le moment et l’endroit où elle est exécutée. Peu importe l’ordinateur sur lequel vous utilisez, l’heure de la journée et les services externes auxquels vous accédez via le réseau, les compilations reproductibles produisent la même sortie octet par octet. C’est idéal aussi bien pour le développement (car les compilations reproductibles sont faciles à partager entre différents appareils de développement) que pour la production (car il est facile de s’assurer que les résultats des compilations reproductibles n’ont pas été altérés – il suffit de relancer la compilation sur votre propre machine et de vérifier que les résultats sont cohérents !). sont très utiles.



Les trois piliers des constructions répétables

Pilier 1 : Builds reproductibles

La répétabilité de la compilation fait référence à ce qui arrive à la machine de construction elle-même. En supposant que nos entrées de construction soient disponibles, et que rien ne change dans le monde autour de nous, notre build produit-elle la même sortie lorsqu’elle est répétée ?

Plan d’installation déterministe

La première, la plus simple et la plus évidente exigence dans une construction reproductible est un plan d’installation de dépendances déterministe.

Dans la plupart des langues, c’est aussi simple que de vérifier un fichier verrouillé. Les outils de compilation modernes permettent souvent aux projets d’exprimer des exigences de dépendances directes sous forme de contraintes, puis de résoudre ces contraintes pour générer un plan d’installation (une liste de noms de dépendances et de paires de versions à installer). Beaucoup de ces outils génèrent également des fichiers de verrouillage pour des plans d’installation sérialisés. Les développeurs peuvent soumettre ces fichiers de verrouillage au contrôle de version afin que les futures versions utilisent les mêmes noms de dépendances et versions.

Notez que nous avons aussi besoin d’un système déterministe dans la compilation de dépendance elle-même (pas seulement dans la sélection de version), et un plan d’installation déterministe ne nous permet pas d’y parvenir !

Construction déterministe

Une fois que nous savons quoi construire, notre build lui-même (y compris notre propre code et celui du code de dépendance) doit en fait être déterministe.

Cela ne pose peut-être pas vraiment de problème pour les projets sans étape de compilation ! Par exemple, un projet Node avec toutes les dépendances est du JavaScript pur, et aucun travail supplémentaire n’est nécessaire pour atteindre une déterministicité effective.

Pour les projets qui incluent des étapes de compilation ou de traduction (compilation source-à-source), garantir le déterminisme est de loin la partie la plus difficile de la construction d’une compilation reproductible. Le processus de compilation peut implicitement introduire le non-déterminisme de plusieurs manières, notamment :

  • Les scripts de compilation de programme Turing-complet peuvent modifier la sortie compilée à volonté.
  • Des scripts post-installation qui reposent sur des recherches de systèmes de fichiers exécutables ou des appels réseau.
  • La liaison C à un package installé par le système où les liaisons sur différents systèmes avec des en-têtes différents peuvent produire des sorties différentes.
  • Étapes pour construire un fichier qui se lit en dehors du contrôle de version.
  • Construis des étapes pour générer des horodatages en utilisant le temps système.
  • Étapes pour construire des dépendances qui ne sont pas exprimées dans le plan d’installation du téléchargement réseau (par exemple, télécharger une dépendance NPM depuis GitHub pour une compilation binaire mise en cache liée à C).
  • Changez le comportement en fonction de la variable d’environnement actuellement définie, mais ne soumettez pas de compilation avec la configuration de la variable d’environnement.


Tous ces comportements n’introduisent pas nécessairement de l’incertitude lorsqu’ils sont bien configurés, mais bien configurer le processus de construction peut être complexe et difficile. Par exemple, vous pouvez lire cet article de blog sur l’incertitude dans les montages Chromium. Beaucoup de ces problèmes peuvent être atténués en contrôlant l’environnement local de construction, ce que nous aborderons dans la section suivante.

Pilier 2 : Environnement immuable

Même avec des builds répétables, il faut s’assurer que les entrées de build ne changent pas. Souvent, cela signifie que nous voulons nous assurer de construire sur un instantané immuable de notre environnement.

Environnement local immuable

Comme nous l’avons évoqué plus haut, une source courante d’incertitude dans la compilation est de s’appuyer sur des « dépendances » qui ne sont pas capturées par l’outil de compilation. Les bibliothèques système liées à C sont les exemples les plus courants, mais d’autres facteurs environnementaux locaux tels que les paramètres des variables d’environnement et les fichiers en dehors du contrôle de version peuvent également influencer la compilation.

Un moyen simple de réduire ce problème est d’exécuter la compilation dans un conteneur connu et immuable. Par exemple, un runtime de conteneur comme Docker aide à garantir que tout le monde utilise les mêmes dépendances système, les mêmes variables d’environnement et s’exécute sur le même système de fichiers. De plus, il est facile de vérifier que le contenu du conteneur correspond à un conteneur de construction bien connu, et si nécessaire, le conteneur peut être complètement retiré de l’image connue et recréé.

Notez que nous sommes très clairs sur les conteneurs connus ou les images de conteneurs connus. Il ne suffit pas de soumettre un fichier Docker ! Pourquoi? Parce que le fichier Docker lui-même ne décrit pas un processus de compilation entièrement reproductible pour les images Docker, car elles ne s’exécutent pas dans un environnement global immuable.

Environnement mondial immuable

Les systèmes de build interagissent souvent avec des services externes pour accomplir des tâches telles que la résolution de versions et le téléchargement de dépendances. Mais les services externes changent fréquemment.

Faire tourner des nodejs d’installation d’apt aujourd’hui vous donnera des résultats différents de l’année dernière, et probablement l’année prochaine aussi. C’est pourquoi Dockerfiles eux-mêmes ne peut pas décrire les builds reproductibles – exécuter le même Dockerfile à différents moments produira des sorties de build différentes !

La solution simple ici est de configurer la compilation dès que possible, en spécifiant une version exacte (idéalement, un hachage de contenu exact également) afin que les futures versions utilisent la même version que la version actuelle. Mais les services externes peuvent aussi modifier leur comportement de manière inattendue – une build reproductible vraiment pessimiste exécute une image interne avec autant de ressources réseau que possible.

Pilier 3 : Disponibilité des ressources

Disons que notre build est reproductible et que le monde sous nos pieds ne change pas. Tout ce dont nous avons besoin maintenant, c’est d’accéder à l’entrée de build. Ça semble simple, non ? Puits......

Le registre plante parfois des pannes

La plupart des développeurs de Node ont connu au moins une panne NPM, durant laquelle le pipeline de build sans mise en cache ni miroir des paquets NPM est perturbé. De nombreux développeurs de Node ont également subi des suppressions de sticks gauches et de fakers, ce qui a gravement endommagé l’écosystème NPM et équivalé en pratique à une panne.

La seule façon fiable d’atténuer ces interruptions de compilation est de lancer votre propre miroir du registre de paquets. Lorsque les services externes ne sont pas disponibles, l’image peut rester en ligne ; Lorsque le registre officiel supprime l’ancien paquet, le miroir peut continuer à fournir des services. Le même principe s’applique à d’autres services distants : à moins d’exécuter votre propre image, la disponibilité d’un pipeline de compilation n’est comparable qu’à celle de ses services.

Choisir de gérer une image de service est toujours un compromis délicat. D’une part, des registres comme NPM disposent d’équipes d’ingénierie et d’opérations dédiées, qui possèdent l’expertise nécessaire pour maintenir ces systèmes en ligne. D’un autre côté, il est beaucoup plus facile d’exécuter une petite image pour un petit ensemble de dépendances que d’exécuter toutes les images NPM. Vous devez prendre des décisions adaptées en fonction des spécificités de chaque service, en tenant compte de la fiabilité des services externes historiques ainsi que des besoins en disponibilité des montages et du personnel de votre équipe.

Les fournisseurs garantissent une disponibilité maximale

Un moyen simple d’assurer une disponibilité maximale des dépendances de votre projet est de les ajouter à votre fournisseur. La plupart des gestionnaires de paquets supportent une forme de « vendoring », ce qui signifie qu’au lieu de dépendre des téléchargements depuis des services externes, nous stockons le code source de dépendance dans le contrôle de version, coexistant avec notre code source. Par exemple, dans Node, cela peut ressembler à un commit de node_modules sous contrôle de version.

Bien que cette solution ne soit pas parfaite (selon la configuration de votre fournisseur et de votre projet, ce qui peut mettre beaucoup de pression sur votre contrôle de version), c’est souvent la solution la plus simple et la plus simple pour une disponibilité maximale.

Référence:

La connexion hyperlientérée est visible.
La connexion hyperlientérée est visible.




Précédent:.NET/C# Utiliser UnsafeAccessor pour modifier le contenu des champs en lecture seule
Prochain:Contrôle personnalisé de formulaire ControlValueAccessor Angular 18 Series (32)
 Propriétaire| Publié le 30-04-2025 à 10:10:23 |
À propos de l’utilisation de builds répétables lors de la création de packages NuGet en C# :

La connexion hyperlientérée est visible.
La connexion hyperlientérée est visible.
Démenti:
Tous les logiciels, supports de programmation ou articles publiés par Code Farmer Network sont uniquement destinés à l’apprentissage et à la recherche ; Le contenu ci-dessus ne doit pas être utilisé à des fins commerciales ou illégales, sinon les utilisateurs assumeront toutes les conséquences. Les informations sur ce site proviennent d’Internet, et les litiges de droits d’auteur n’ont rien à voir avec ce site. Vous devez supprimer complètement le contenu ci-dessus de votre ordinateur dans les 24 heures suivant le téléchargement. Si vous aimez le programme, merci de soutenir un logiciel authentique, d’acheter l’immatriculation et d’obtenir de meilleurs services authentiques. En cas d’infraction, veuillez nous contacter par e-mail.

Mail To:help@itsvse.com