Integración continua - Continuous integration

En ingeniería de software , la integración continua ( CI ) es la práctica de fusionar las copias de trabajo de todos los desarrolladores en una línea principal compartida varias veces al día. Grady Booch propuso por primera vez el término CI en su método de 1991 , aunque no defendió la integración varias veces al día. La programación extrema (XP) adoptó el concepto de CI y defendió la integración más de una vez al día, quizás hasta decenas de veces al día.

Razón fundamental

Al embarcarse en un cambio, un desarrollador toma una copia del código base actual sobre el que trabajar. A medida que otros desarrolladores envían el código modificado al repositorio de código fuente , esta copia deja de reflejar gradualmente el código del repositorio. No solo se puede cambiar la base del código existente, sino que se puede agregar nuevo código, así como nuevas bibliotecas y otros recursos que crean dependencias y posibles conflictos.

Cuanto más tiempo continúe el desarrollo en una rama sin volver a fusionarse con la línea principal, mayor será el riesgo de múltiples conflictos de integración y fallas cuando la rama del desarrollador finalmente se vuelva a fusionar. Cuando los desarrolladores envían código al repositorio, primero deben actualizar su código para reflejar los cambios en el repositorio desde que tomaron su copia. Cuantos más cambios contenga el repositorio, más trabajo deben hacer los desarrolladores antes de enviar sus propios cambios.

Con el tiempo, el repositorio puede volverse tan diferente de las líneas de base de los desarrolladores que ingresan a lo que a veces se denomina "infierno de fusión" o "infierno de integración", donde el tiempo que lleva la integración excede el tiempo necesario para realizar los cambios originales. .

Flujos de trabajo

Ejecutar pruebas de forma local

CI está destinado a ser utilizado en combinación con pruebas unitarias automatizadas escritas a través de las prácticas de desarrollo impulsado por pruebas . Esto se hace ejecutando y pasando todas las pruebas unitarias en el entorno local del desarrollador antes de comprometerse con la línea principal. Esto ayuda a evitar que el trabajo en curso de un desarrollador rompa la copia de otro desarrollador. Cuando sea necesario, las funciones parcialmente completas se pueden deshabilitar antes de comprometerse, utilizando funciones alternadas, por ejemplo.

Compilar código en CI

Un servidor de compilación compila el código periódicamente o incluso después de cada confirmación e informa los resultados a los desarrolladores. El uso de servidores de compilación se introdujo fuera de la comunidad de XP (programación extrema) y muchas organizaciones han adoptado CI sin adoptar todo XP.

Ejecutar pruebas en CI

Además de las pruebas unitarias automatizadas, las organizaciones que utilizan CI suelen utilizar un servidor de compilación para implementar procesos continuos de aplicación del control de calidad en general: pequeños esfuerzos, que se aplican con frecuencia. Además de ejecutar las pruebas unitarias y de integración, dichos procesos ejecutan análisis estáticos adicionales, miden y perfilan el rendimiento, extraen y dan formato a la documentación del código fuente y facilitan los procesos manuales de control de calidad . En el popular servicio Travis CI para código abierto, solo el 58,64% de los trabajos de CI ejecutan pruebas.

Esta aplicación continua de control de calidad tiene como objetivo mejorar la calidad del software y reducir el tiempo necesario para entregarlo, reemplazando la práctica tradicional de aplicar el control de calidad después de completar todo el desarrollo. Esto es muy similar a la idea original de integrar con más frecuencia para facilitar la integración, solo se aplica a los procesos de control de calidad.

Implementar un artefacto de CI

Ahora, CI a menudo se entrelaza con la entrega continua o la implementación continua en lo que se denomina canalización de CI / CD. La "entrega continua" asegura que el software registrado en la línea principal esté siempre en un estado que se pueda implementar para los usuarios y la "implementación continua" hace que el proceso de implementación sea completamente automatizado.

Historia

El primer trabajo conocido sobre integración continua fue el entorno Infuse desarrollado por GE Kaiser, DE Perry y WM Schell.

En 1994, Grady Booch usó la frase integración continua en Análisis y Diseño Orientado a Objetos con Aplicaciones (2da edición) para explicar cómo, al desarrollar usando microprocesos, "los lanzamientos internos representan una especie de integración continua del sistema, y ​​existen para forzar cierre del microproceso ".

En 1997, Kent Beck y Ron Jeffries inventaron Extreme Programming (XP) mientras estaban en el proyecto Chrysler Comprehensive Compensation System , incluida la integración continua. Beck publicó sobre la integración continua en 1998, enfatizando la importancia de la comunicación cara a cara sobre el soporte tecnológico. En 1999, Beck elaboró ​​más en su primer libro completo sobre programación extrema. CruiseControl , una de las primeras herramientas de CI de código abierto, se lanzó en 2001.

En 2010, Timothy Fitz publicó un artículo detallando cómo el equipo de ingeniería de IMVU había construido y estado utilizando el primer sistema de CI práctico. Si bien su publicación fue recibida originalmente con escepticismo, rápidamente se hizo popular y encontró una adopción generalizada como parte de la metodología de desarrollo de software Lean , también basada en IMVU.

Prácticas habituales

Esta sección enumera las mejores prácticas sugeridas por varios autores sobre cómo lograr una integración continua y cómo automatizar esta práctica. La automatización de la construcción es una práctica recomendada en sí misma.

La integración continua (la práctica de integrar frecuentemente el código nuevo o modificado con el repositorio de código existente) debe ocurrir con la frecuencia suficiente para que no quede una ventana intermedia entre la confirmación y la compilación , y de manera que no puedan surgir errores sin que los desarrolladores los noten y los corrijan de inmediato. La práctica normal es activar estas compilaciones por cada confirmación en un repositorio, en lugar de una compilación programada periódicamente. Los aspectos prácticos de hacer esto en un entorno de múltiples desarrolladores de confirmaciones rápidas son tales que es habitual desencadenar poco tiempo después de cada confirmación y luego iniciar una compilación cuando expira este temporizador o después de un intervalo bastante más largo desde la última compilación. . Tenga en cuenta que, dado que cada nueva confirmación restablece el temporizador utilizado para el disparo de corta duración, esta es la misma técnica utilizada en muchos algoritmos de eliminación de rebotes de botones. De esta manera, los eventos de confirmación se "eliminan" para evitar compilaciones innecesarias entre una serie de confirmaciones rápidas. Muchas herramientas automatizadas ofrecen esta programación automáticamente.

Otro factor es la necesidad de un sistema de control de versiones que admita confirmaciones atómicas ; es decir, todos los cambios de un desarrollador pueden verse como una única operación de confirmación. No tiene sentido intentar compilar solo a partir de la mitad de los archivos modificados.

Para lograr estos objetivos, la integración continua se basa en los siguientes principios.

Mantener un repositorio de código

Esta práctica aboga por el uso de un sistema de control de revisiones para el código fuente del proyecto. Todos los artefactos necesarios para construir el proyecto deben colocarse en el repositorio. En esta práctica y en la comunidad de control de revisiones, la convención es que el sistema debe poder compilarse a partir de una caja nueva y no requerir dependencias adicionales. El defensor de la programación extrema, Martin Fowler, también menciona que cuando la ramificación es compatible con herramientas, su uso debe minimizarse. En cambio, se prefiere que los cambios se integren en lugar de que se mantengan simultáneamente varias versiones del software. La línea principal (o troncal ) debe ser el lugar para la versión de trabajo del software.

Automatiza la construcción

Un solo comando debe tener la capacidad de construir el sistema. Muchas herramientas de construcción, como make , existen desde hace muchos años. Otras herramientas más recientes se utilizan con frecuencia en entornos de integración continua. La automatización de la compilación debe incluir la automatización de la integración, que a menudo incluye la implementación en un entorno similar a la producción . En muchos casos, el script de compilación no solo compila binarios, sino que también genera documentación, páginas de sitios web, estadísticas y medios de distribución (como Debian DEB , Red Hat RPM o archivos MSI de Windows ).

Realice la autocomprobación de la construcción

Una vez creado el código, se deben ejecutar todas las pruebas para confirmar que se comporta como los desarrolladores esperan que se comporte.

Todos se comprometen con la línea de base todos los días

Al comprometerse con regularidad, cada confirmador puede reducir el número de cambios conflictivos. Registrar el trabajo de una semana corre el riesgo de entrar en conflicto con otras funciones y puede ser muy difícil de resolver. Los pequeños conflictos tempranos en un área del sistema hacen que los miembros del equipo se comuniquen sobre el cambio que están realizando. Confirmar todos los cambios al menos una vez al día (una vez por función creada) generalmente se considera parte de la definición de Integración Continua. Además, generalmente se recomienda realizar una construcción nocturna . Estos son límites inferiores; se espera que la frecuencia típica sea mucho mayor.

Cada compromiso (a la línea de base) debe construirse

El sistema debe construir confirmaciones con la versión de trabajo actual para verificar que se integren correctamente. Una práctica común es utilizar la integración continua automatizada, aunque esto se puede hacer manualmente. La Integración Continua Automatizada emplea un servidor o demonio de integración continua para monitorear el sistema de control de revisiones en busca de cambios y luego ejecutar automáticamente el proceso de compilación.

Cada confirmación de corrección de errores debe venir con un caso de prueba

Al corregir un error, es una buena práctica impulsar un caso de prueba que reproduzca el error. Esto evita que se revierta la corrección y que vuelva a aparecer el error, lo que se conoce como regresión . Los investigadores han propuesto automatizar esta tarea: si una confirmación de corrección de errores no contiene un caso de prueba, se puede generar a partir de las pruebas ya existentes.

Mantenga la construcción rápida

La compilación debe completarse rápidamente, de modo que si hay un problema con la integración, se identifique rápidamente.

Prueba en un clon del entorno de producción

Tener un entorno de prueba puede provocar fallas en los sistemas probados cuando se implementan en el entorno de producción porque el entorno de producción puede diferir del entorno de prueba de manera significativa. Sin embargo, construir una réplica de un entorno de producción tiene un costo prohibitivo. En su lugar, el entorno de prueba o un entorno de preproducción independiente ("puesta en escena") debe construirse para que sea una versión escalable del entorno de producción para aliviar los costos y, al mismo tiempo, mantener la composición y los matices de la pila de tecnología . Dentro de estos entornos de prueba, la virtualización de servicios se usa comúnmente para obtener acceso bajo demanda a dependencias (p. Ej., API, aplicaciones de terceros, servicios, mainframes , etc.) que están más allá del control del equipo, aún están en evolución o son demasiado complejas para configurar. en un laboratorio de pruebas virtual.

Facilite la obtención de los últimos entregables

Hacer que las compilaciones estén fácilmente disponibles para las partes interesadas y los evaluadores puede reducir la cantidad de reelaboración necesaria cuando se reconstruye una función que no cumple con los requisitos. Además, las pruebas tempranas reducen las posibilidades de que los defectos sobrevivan hasta la implementación. Encontrar errores antes puede reducir la cantidad de trabajo necesario para resolverlos.

Todos los programadores deben comenzar el día actualizando el proyecto desde el repositorio. De esa manera, todos se mantendrán actualizados.

Todos pueden ver los resultados de la última versión.

Debería ser fácil averiguar si la compilación se rompe y, de ser así, quién realizó el cambio relevante y cuál fue ese cambio.

Automatizar la implementación

La mayoría de los sistemas de CI permiten la ejecución de scripts después de que finaliza una compilación. En la mayoría de las situaciones, es posible escribir un script para implementar la aplicación en un servidor de prueba en vivo que todos puedan ver. Otro avance en esta forma de pensar es la implementación continua , que requiere que el software se implemente directamente en producción, a menudo con automatización adicional para evitar defectos o regresiones.

Costos y beneficios

La integración continua está destinada a producir beneficios como:

  • Los errores de integración se detectan temprano y son fáciles de rastrear debido a pequeños conjuntos de cambios. Esto ahorra tiempo y dinero durante la vida útil de un proyecto.
  • Evita el caos de último minuto en las fechas de lanzamiento, cuando todos intentan verificar sus versiones ligeramente incompatibles
  • Cuando las pruebas unitarias fallan o surge un error , si los desarrolladores necesitan revertir la base de código a un estado libre de errores sin depurar , solo se pierde una pequeña cantidad de cambios (porque la integración ocurre con frecuencia)
  • Disponibilidad constante de una compilación "actual" para fines de prueba, demostración o lanzamiento
  • El registro frecuente de código impulsa a los desarrolladores a crear código modular y menos complejo

Con las pruebas automatizadas continuas, los beneficios pueden incluir:

Algunas desventajas de la integración continua pueden incluir:

  • La construcción de un conjunto de pruebas automatizado requiere una cantidad considerable de trabajo, incluido un esfuerzo continuo para cubrir nuevas funciones y seguir las modificaciones intencionales del código.
  • Hay algo de trabajo involucrado para configurar un sistema de compilación , y puede volverse complejo, lo que dificulta su modificación de manera flexible.
  • La integración continua no es necesariamente valiosa si el alcance del proyecto es pequeño o contiene código heredado no comprobable.
  • El valor agregado depende de la calidad de las pruebas y de lo comprobable que sea realmente el código.
  • Los equipos más grandes significan que se agrega código nuevo constantemente a la cola de integración, por lo que el seguimiento de las entregas (mientras se conserva la calidad) es difícil y las colas de compilaciones pueden ralentizar a todos.
  • Con múltiples confirmaciones y fusiones al día, el código parcial para una función podría enviarse fácilmente y, por lo tanto, las pruebas de integración fallarán hasta que la función esté completa.
  • La seguridad y la garantía del desarrollo de misión crítica (por ejemplo, DO-178C , ISO 26262 ) requieren una documentación rigurosa y una revisión en proceso que son difíciles de lograr mediante la integración continua. Este tipo de ciclo de vida a menudo requiere que se completen pasos adicionales antes del lanzamiento del producto cuando se requiere la aprobación regulatoria del producto.

Ver también

Referencias

enlaces externos