Para proporcionar un ejemplo práctico de un intento de crear una compilación verdaderamente repetible, considere lo siguiente:
Una tubería de compilación que comienza con un repositorio git para el que ningún usuario puede volver a escribir el historial o eliminar ramas no fusionadas.
El primer paso de "compilación" después de verificar el código fuente es girar un contenedor que contiene todas las dependencias de tiempo de compilación.
La salida del contenedor de tiempo de compilación en ejecución es un contenedor que contiene el binario compilado.
Más importante para la repetibilidad de la compilación, las siguientes etiquetas se agregan al contenedor final:
- El hash exacto del código fuente en el repositorio original y la url del repositorio git y una instantánea de bola de alquitrán del código que se carga en un repositorio de artefactos.
- La versión exacta del contenedor de compilación que se utilizó para ejecutar la compilación.
- La versión exacta de la imagen base original en la que se cargó el binario.
- Los valores de todas las variables de tiempo de construcción utilizadas para crear el binario.
- La versión de Docker con la que se construyeron los tres contenedores, así como la versión con la que se ejecutaban cuando se construyeron.
Al agregar todos estos metadatos podemos asegurarnos de que en cualquier momento en el futuro podamos extraer el conjunto exacto de dependencias de compilación (a través del contenedor de compilación), compilar el binario con un conjunto exacto de pasos conocidos (consagrados en el contenedor de compilación ) y empaquete esto en otra imagen base conocida con todas las dependencias de tiempo de ejecución (usando la etiqueta de imagen base) y todo esto puede basarse en la versión correcta exacta del código fuente basada en la etiqueta en el contenedor.
Teóricamente, esto debería darnos la capacidad de reproducir exactamente una versión de compilación.
La importancia de esto es que nos permite ver lo que se está ejecutando en la producción e, incluso si todo ha progresado significativamente en las versiones, retroceder y extraer la versión del código, la imagen base y el contenedor de compilación utilizado originalmente para que podamos, por ejemplo , aplique una revisión a esa versión antes de reconstruir exactamente como antes para que podamos volver a implementar sabiendo que es exactamente el mismo artefacto con el único delta que es la revisión.