Este artículo es un artículo espejo de traducción automática, por favor haga clic aquí para saltar al artículo original.

Vista: 1081|Respuesta: 1

Una breve introducción a Reproducible Build

[Copiar enlace]
Publicado el 30-4-2025 10:09:27 | | | |
¿Qué es una build repetible?

Construcción determinista o construcción reproducible son algo diferentes, pero pueden entenderse como lo mismo según este artículo.

Las Construcciones Reproducibles se refieren a laMúltiples ejecuciones del proceso de compilación con la misma entrada y entorno de compilación pueden producir exactamente los mismos resultados。 Esta tecnología es importante para el desarrollo de software, la distribución y la validación de la seguridad.

Una compilación es reproducible si proporciona exactamente la misma salida independientemente de cuándo y dónde se ejecute. No importa en qué ordenador estés usando, a qué hora del día o a qué servicios externos accedas por la red, las compilaciones reproducibles producen la misma salida byte a byte. Esto es ideal tanto para el desarrollo (porque las compilaciones reproducibles son fáciles de compartir entre diferentes dispositivos de desarrollo) como para la producción (porque es fácil asegurarse de que los resultados de las compilaciones reproducibles no han sido manipulados: simplemente reejecuta la compilación en tu propia máquina y comprueba que los resultados sean consistentes). son muy útiles.



Los tres pilares de las construcciones repetibles

Pilar 1: Construcciones repetibles

La repetibilidad de la construcción se refiere a lo que ocurre con la propia máquina de compilación. Suponiendo que nuestras entradas de compilación estén disponibles y que nada cambie en el mundo que nos rodea, ¿nuestra compilación produce la misma salida cuando se repite?

Plan de instalación determinista

El primero, más sencillo y más evidente requisito en una compilación repetible es un plan de instalación de dependencias determinista.

En la mayoría de los idiomas, es tan sencillo como comprobar un archivo bloqueado. Las herramientas de compilación modernas a menudo permiten a los proyectos expresar requisitos directos de dependencias como restricciones, y luego resolver esas restricciones para generar un plan de instalación (una lista de nombres de dependencias y pares de versiones para instalar). Muchas de estas herramientas también generan archivos de bloqueo para planes de instalación serializados. Los desarrolladores pueden enviar estos archivos de bloqueo al control de versiones para que futuras versiones usen los mismos nombres de dependencias y versiones.

Ten en cuenta que también necesitamos deterministas en la propia compilación de dependencias (no solo en la selección de versiones), y un plan de instalación determinista no nos permite lograr esto.

Construcción determinista

Una vez que sabemos qué construir, nuestra propia construcción (incluyendo nuestro propio código y la construcción del código de dependencias) debe ser determinista.

¡Esto puede que no sea un problema para proyectos sin un paso de compilación! Por ejemplo, un proyecto Node con todas las dependencias es JavaScript puro, y no se requiere trabajo adicional para lograr determinidad efectiva.

Para proyectos que sí incluyen pasos de compilación o traducción (compilación de código a código), asegurar el determinismo es, con diferencia, la parte más difícil de construir una compilación reproducible. El proceso de compilación puede introducir implícitamente el no determinismo de varias maneras, incluyendo:

  • Los scripts de compilación de programas Turing-completo pueden cambiar la salida compilada a voluntad.
  • Scripts posteriores a la instalación que dependen de búsquedas ejecutables en sistemas de archivos o llamadas de red.
  • C vinculación a un encapsulado instalado por el sistema, donde las enlazantes en diferentes sistemas con distintos encabezados pueden producir salidas distintas.
  • Pasos para construir un archivo que se lea fuera del control de versiones.
  • Compila pasos para generar marcas de tiempo usando la hora del sistema.
  • Pasos para construir dependencias que no se expresan en el plan de instalación de descarga de red (por ejemplo, descargar una dependencia NPM desde GitHub para una compilación binaria en caché que esté vinculada a C).
  • Cambia el comportamiento según la variable de entorno establecida actualmente, pero no envíes una compilación con la configuración de la variable de entorno.


No todos estos comportamientos necesariamente introducen incertidumbre cuando se configuran correctamente, pero configurar correctamente el proceso de compilación puede ser complejo y difícil. Por ejemplo, puedes leer esta entrada de blog sobre la incertidumbre en las construcciones de Chromium. Muchos de estos problemas pueden mitigarse controlando el entorno local de construcción, que trataremos en la siguiente sección.

Pilar 2: Entorno inmutable

Incluso con builds repetibles, tenemos que asegurarnos de que las entradas de build no cambien. A menudo, esto significa que queremos asegurarnos de construir sobre una instantánea inmutable de nuestro entorno.

Entorno local inmutable

Como comentamos antes, una fuente común de incertidumbre en la compilación es depender de "dependencias" que no son capturadas por la herramienta de compilación. Las bibliotecas de sistema encadernadas en C son los ejemplos más comunes, pero otros factores ambientales locales como la configuración de variables de entorno y los archivos fuera del alcance del control de versiones también pueden afectar la compilación.

Una forma sencilla de mitigar este problema es ejecutar la compilación en un contenedor conocido e inmutable. Por ejemplo, un entorno de ejecución en contenedor como Docker ayuda a garantizar que todos usen las mismas dependencias del sistema, las mismas variables de entorno y se ejecuten en el mismo sistema de archivos. Además, es fácil verificar que el contenido del contenedor coincide con un contenedor de construcción bien conocido y, si es necesario, el contenedor puede ser retirado completamente de la imagen conocida y recreado.

Ten en cuenta que tenemos muy claro lo que es contenedor conocido o imágenes de contenedores conocidos. ¡No basta con enviar un archivo Dockerfile! ¿Por qué? Porque el propio Dockerfile no describe un proceso de compilación completamente reproducible para imágenes Docker, ya que no se ejecutan en un entorno global inmutable.

Entorno global inmutable

Los sistemas de compilación suelen interactuar con servicios externos para completar tareas como la resolución de versiones y la descarga de dependencias. Pero los servicios externos cambian con frecuencia.

Ejecutar apt install nodejs hoy te dará resultados diferentes a los del año pasado, y probablemente el año que viene también obtendrás resultados distintos. Por eso los propios Dockerfiles no pueden describir compilaciones reproducibles: ejecutar el mismo Dockerfile en diferentes momentos del tiempo producirá diferentes salidas de compilación.

La mitigación sencilla aquí es configurar la compilación siempre que sea posible, especificando una versión exacta (idealmente, también un hash exacto de contenido) para que futuras versiones usen la misma versión que la actual. Pero los servicios externos también pueden cambiar su comportamiento de forma inesperada: una build verdaderamente pesimista y reproducible ejecuta una imagen interna con la mayor cantidad posible de recursos de red.

Pilar 3: Disponibilidad de recursos

Supongamos que nuestra construcción es repetible y el mundo bajo nuestros pies no cambia. Ahora solo necesitamos acceso a la entrada de la compilación. Parece sencillo, ¿verdad? Pozo......

El registro a veces falla

La mayoría de los desarrolladores de Node han experimentado al menos una caída de NPM, durante la cual la pipeline de compilación sin caché ni espejo de paquetes NPM se ve interrumpida. Muchos desarrolladores de Node también han experimentado eliminaciones de left-pad y faker, lo que ha dañado gravemente el ecosistema NPM y ha supuesto efectivamente una interrupción.

La única forma fiable de mitigar estos fallos de compilación es ejecutar tu propio espejo del registro de paquetes. Cuando no hay servicios externos disponibles, la imagen puede permanecer en línea; Cuando el registro oficial elimina el paquete antiguo, el espejo puede seguir ofreciendo servicios. El mismo principio se aplica a otros servicios remotos: a menos que ejecutes tu propia imagen, la disponibilidad de una pipeline de compilación solo es comparable a la disponibilidad de sus servicios.

Elegir ejecutar una imagen de servicio siempre es un compromiso delicado. Por un lado, registros como NPM cuentan con equipos de ingeniería y operaciones dedicados que tienen la experiencia necesaria para mantener estos sistemas en línea. Por otro lado, es mucho más fácil ejecutar una imagen pequeña para un conjunto reducido de dependencias que ejecutar todas las imágenes NPM. Deberías tomar decisiones espejo basadas en los detalles de cada servicio, teniendo en cuenta la fiabilidad de los servicios externos históricos y la disponibilidad de construcción y necesidades de personal de tu equipo.

Los proveedores garantizan la máxima disponibilidad

Una forma sencilla de asegurar la máxima disponibilidad de las dependencias de tu proyecto es añadirlas a tu proveedor. La mayoría de los gestores de paquetes soportan alguna forma de "vendoring", lo que significa que, en lugar de depender de descargas de servicios externos, almacenamos el código fuente de dependencia en control de versiones, coexistiendo con nuestro código fuente. Por ejemplo, en Node, esto podría parecer comprometer node_modules al control de versiones.

Aunque esta solución no es perfecta (dependiendo de cómo esté configurado tu proveedor y proyecto, lo que puede suponer mucha presión en el control de versiones), a menudo es la más sencilla y sencilla para maximizar la disponibilidad.

Referencia:

El inicio de sesión del hipervínculo es visible.
El inicio de sesión del hipervínculo es visible.




Anterior:.NET/C# Usa UnsafeAccessor para modificar el contenido de campos de solo lectura
Próximo:Angular 18 Series (32) ControlValueAccessor controles personalizados de formulario
 Propietario| Publicado el 30-4-2025 10:10:23 |
Sobre el uso de compilaciones repetibles al crear paquetes NuGet en C#:

El inicio de sesión del hipervínculo es visible.
El inicio de sesión del hipervínculo es visible.
Renuncia:
Todo el software, materiales de programación o artículos publicados por Code Farmer Network son únicamente para fines de aprendizaje e investigación; El contenido anterior no se utilizará con fines comerciales o ilegales; de lo contrario, los usuarios asumirán todas las consecuencias. La información de este sitio proviene de Internet, y las disputas de derechos de autor no tienen nada que ver con este sitio. Debes eliminar completamente el contenido anterior de tu ordenador en un plazo de 24 horas desde la descarga. Si te gusta el programa, por favor apoya el software genuino, compra el registro y obtén mejores servicios genuinos. Si hay alguna infracción, por favor contáctanos por correo electrónico.

Mail To:help@itsvse.com