Trunk-Based Development - Dora
Existen dos patrones principales para que los equipos de desarrollo colaboren mediante el control de versiones. Uno consiste en usar ramas de características (feature branches), donde un desarrollador o un grupo de desarrolladores crea una rama, generalmente desde el trunk (también conocido como main o mainline), y luego trabaja de forma aislada en ella hasta que la funcionalidad que están desarrollando esté completa. Cuando el equipo considera que la funcionalidad está lista, la fusiona de nuevo con el trunk.
El segundo patrón se conoce como trunk-based development (desarrollo basado en tronco), donde cada desarrollador divide su trabajo en pequeños lotes y los integra en el trunk al menos una vez (y potencialmente varias) al día. La diferencia clave entre estos enfoques es el alcance. Las ramas suelen involucrar a varios desarrolladores y requieren días o incluso semanas de trabajo. En cambio, las ramas en trunk-based development no suelen durar más de unas pocas horas, y muchos desarrolladores integran sus cambios individuales en el trunk con frecuencia.
El siguiente diagrama muestra un cronograma típico basado en trunk-based development:
Cronología Trunk-based Development
En trunk-based development, los desarrolladores envían el código directamente al trunk. Los cambios realizados en las ramas de lanzamiento (release branches) (instantáneas del código cuando está listo para su lanzamiento) suelen fusionarse en trunk (representado por las flechas hacia abajo) lo antes posible. Con este enfoque, hay casos en los que es necesario seleccionar cuidadosamente las correcciones de errores e integrarlas en las versiones (representado por la flecha hacia arriba), pero estos casos no son tan frecuentes como el desarrollo de nuevas funciones en el trunk. En los casos en que los despliegues se producen varias veces al día, las ramas de lanzamiento no son necesarias, ya que los cambios pueden enviarse directamente al trunk e implementarse desde allí. Una ventaja clave del enfoque basado en el trunk es que reduce la complejidad de los eventos de fusión y mantiene el código actualizado al tener menos líneas de desarrollo y realizar fusiones pequeñas y frecuentes.
Por el contrario, el siguiente diagrama muestra un estilo de desarrollo típico no basado en el trunk:
Estilo de desarrollo típico basado en ramas de larga duración
En este enfoque, los desarrolladores realizan cambios en ramas de larga duración. Estos cambios requieren eventos de fusión más grandes y complejos en comparación con trunk-based development. Este enfoque también requiere esfuerzos adicionales de estabilización y periodos de “bloqueo de código” o “congelación de código” para garantizar que el software se mantenga en buen estado de funcionamiento, ya que las fusiones extensas suelen introducir errores o regresiones. Por lo tanto, es necesario probar exhaustivamente el código posterior a la fusión y, a menudo, corregir errores.
Cómo implementar trunk-based development#
Trunk-based development es una práctica necesaria para la integración continua. La integración continua (CI) combina la práctica del trunk-based development con el mantenimiento de un conjunto de pruebas automatizadas rápidas que se ejecutan tras cada confirmación del trunk para garantizar el funcionamiento continuo del sistema.
El objetivo de la integración continua es eliminar las largas fases de integración y estabilización mediante la integración frecuente de pequeños lotes de código. De esta forma, los desarrolladores se aseguran de comunicar lo que hacen y la integración elimina las grandes fusiones que pueden generar una carga de trabajo considerable para otros desarrolladores y testers.
En el paradigma de CI, los desarrolladores son responsables de mantener el proceso de compilación en funcionamiento. Esto significa que, si el proceso de CI falla, deben detener lo que estén haciendo para solucionar el problema inmediatamente o revertir el cambio si no se puede solucionar en pocos minutos.
Practicar trunk-based development requiere que los desarrolladores comprendan cómo dividir su trabajo en pequeños lotes. Esto supone un cambio significativo para quienes no están acostumbrados a trabajar de esta manera.
El análisis de los datos de DORA de 2016 (PDF) y 2017 (PDF) muestra que los equipos logran niveles más altos de entrega de software y rendimiento operativo (velocidad de entrega, estabilidad y disponibilidad) si siguen estas prácticas:
- Tener tres o menos ramas activas en el repositorio de código de la aplicación.
- Fusionar ramas con el trunk al menos una vez al día.
- No tenga congelamientos de código ni fases de integración.
Errores comunes#
Algunos obstáculos comunes para la adopción total del desarrollo basado en troncos incluyen los siguientes:
Un proceso de revisión de código excesivamente complejo. Muchas organizaciones tienen un proceso de revisión de código complejo que requiere múltiples aprobaciones antes de que los cambios se puedan integrar en el trunk. Cuando la revisión de código es laboriosa y toma horas o días, los desarrolladores evitan trabajar en lotes pequeños y, en su lugar, agrupan muchos cambios. Esto, a su vez, conduce a una espiral descendente donde los revisores procrastinan con revisiones de código extensas debido a su complejidad.
En consecuencia, las solicitudes de fusión suelen perder importancia porque los desarrolladores las evitan. Dado que es difícil razonar sobre el impacto de grandes cambios en un sistema mediante la inspección, es probable que los defectos pasen desapercibidos para los revisores y se reduzcan los beneficios del trunk-based development.
Realizar revisiones de código asincrónamente. Si su equipo practica la programación en parejas (pair programming), el código ya ha sido revisado por otra persona. Si se requieren más revisiones, deben realizarse de manera sincróna: cuando el desarrollador esté listo para confirmar el código, debe pedirle a otra persona del equipo que lo revise en ese momento. No deben solicitar una revisión asincróna; por ejemplo, enviando una solicitud a una herramienta y luego comenzando una nueva tarea mientras esperan la revisión. Cuanto más se retrase una fusión, más probable será que se generen conflictos y problemas asociados. Implementar revisiones sincrónas requiere el acuerdo del equipo para priorizar la revisión del código de los demás sobre otras tareas.
No ejecutar pruebas automatizadas antes de confirmar el código. Para garantizar que el trunk se mantenga en funcionamiento, es fundamental ejecutar pruebas con los cambios en el código antes de confirmarlo. Esto se puede hacer en las estaciones de trabajo de los desarrolladores, y muchas herramientas también ofrecen la posibilidad de ejecutar pruebas remotamente con los cambios locales y confirmarlos automáticamente cuando se aprueban. Cuando los desarrolladores saben que pueden introducir su código en el trunk sin mayor formalidad, el resultado son pequeños cambios de código fáciles de comprender, revisar y probar, y que pueden implementarse en producción más rápidamente.
Formas de mejorar trunk-based development#
Con base en la discusión anterior, aquí hay algunas prácticas que puedes implementar para mejorar el desarrollo basado en tronco:
- Desarrollar en lotes pequeños. Uno de los factores más importantes para trunk-based development es que los equipos aprendan a desarrollar en lotes pequeños. Esto requiere capacitación y apoyo organizacional para el equipo de desarrollo.
- Realizar una revisión de código sincróna. Como se mencionó anteriormente, adoptar la revisión de código sincróna, o al menos garantizar que los desarrolladores la prioricen, ayuda a garantizar que los cambios no tengan que esperar horas, o incluso días, para integrarse en el trunk.
- Implementa pruebas automatizadas integrales. Asegúrate de contar con un conjunto completo y eficaz de pruebas unitarias automatizadas, y de que estas se ejecuten antes de cada confirmación. Por ejemplo, si usas GitHub, puedes proteger las ramas para permitir la fusión de PRs solo cuando todas las pruebas hayan pasado. El tutorial Ejecutar compilaciones con GitHub Checks muestra cómo integrar GitHub Checks con Cloud Build.
- Mantenga una compilación rápida. El proceso de compilación y prueba debería ejecutarse en pocos minutos. Si esto parece difícil de lograr, probablemente indica oportunidades de mejora en la arquitectura del sistema.
- Crea un grupo central de promotores y mentores. Trunk-based development supone un cambio sustancial para muchos desarrolladores, y es previsible cierta resistencia. Muchos desarrolladores simplemente no se imaginan trabajando de esta manera. Una buena práctica es encontrar desarrolladores que ya hayan trabajado de esta manera y que asesoren a otros desarrolladores. También es importante que algunos equipos trabajen con un estilo trunk-based. Una forma de lograrlo es reunir a un grupo crítico de desarrolladores con experiencia en trunk-based development para que al menos un equipo siga estas prácticas. Después, puedes migrar a otros equipos a este estilo cuando estés seguro de que el equipo que sigue esta práctica está rindiendo como se espera.
Formas de medir trunk-based development#
Puede medir la eficacia del desarrollo basado en tronco haciendo lo siguiente.
| Factor a probar | Qué medir | Meta |
|---|---|---|
| Ramas activas en el repositorio de código de la aplicación. | Mida la cantidad de ramas activas en los sistemas de control de versiones de sus repositorios de aplicaciones y haga visible esta cifra para todos los equipos. A continuación, monitoree el progreso gradual hacia el objetivo. | Tres o menos ramas activas. |
| Periodos de congelación de código. | Mida la cantidad de bloqueos de código que tiene su equipo y su duración. Estas mediciones también permiten categorizar el tiempo dedicado a la fusión de conflictos, bloqueos de código, estabilización, etc. | Ningún código se congela cuando nadie puede enviarlo. |
| Frecuencia de fusión de ramas y bifurcaciones hacia el trunk. | Mida un valor binario (sí/no) para cada rama que se fusiona, o mida un porcentaje de ramas y bifurcaciones que se fusionan cada día. | Fusionarse al menos una vez al día. |
| Verifique el tiempo que toma aprobar los cambios de código. | Si realiza la revisión de código de forma asincrónica, mida el tiempo promedio que lleva aprobar las solicitudes de cambio y preste especial atención a las solicitudes que demoran considerablemente más que el promedio. | Encuentre formas de hacer que la revisión del código sea una actividad sincróna que se realice como parte del desarrollo. |
¿Qué sigue?#
- Para obtener enlaces a otros artículos y recursos, consulte la página de Google Cloud DevOps.
- Consulta Ejecución de compilaciones con GitHub Checks para aprender a conectar Google Cloud a GitHub mediante Cloud Build.
- Consulte un artículo de Martin Fowler sobre feature branching.
- Consulte la publicación de Jez Humble sobre DVCS and feature branches.
- Consulte el portal de Paul Hammant dedicado al trunk-based development.
- Explora nuestro programa de investigación de DevOps.
- Realice la verificación rápida de DORA para comprender dónde se encuentra en comparación con el resto de la industria.
Nota: Este post es una traduccion de Trunk-based development bajo la licencia: CC BY-NC-SA 4.0.