Integración Continua 2.0

El sábado pasado en el contexto de Agiles 2019 hice una sesión en formato mini-taller sobre este tema. Era la primera vez que hacía este taller pero más allá de eso creo que salió muy bien.

Integración Continua 2.0 es una idea que viene a reflejar algunos cambios en la forma de implementación de esta práctica que he visto a lo largo de los años. Yo empecé a utilizar esta práctica allá por 2005 / 2006 utilizando la herramienta CruiseControl. Desde aquella época al día de hoy varias cosas hay cambiado:

  • Antiguamente la definición del proceso de integración continua se hacía «dentro del build server», en la actualidad la mayoría de las herramientas permiten (y promueven) la definición del proceso de integración continua dentro del propio repositorio donde se encuentra el código fuente a integrar. Esto es lo que hacen los archivos .travis-ci.yml, Jenkinsfile, etc.
  • Antiguamente los servidores de integración continua corrían típicamente on-premises mientras que en la actualidad es muy común utilizarlos en la nube e incluso en algunos casos en un modelo «as a service»
  • Antiguamente el build se armaba en base a plugins del build server, mientras que en la actualidad hay un clara tendencia a armar todo el proceso de build en scripts que luego son invocados por el build server
  • Antiguamente los servidores de integración continua estaban enfocados en tareas concretas de integración continua, mientras que en la actualidad tienen un foco más amplio apuntando todo el proceso de delivery

Creo que estos puntos quedaron bien claros durante el taller, aún cuando en los ejercicios prácticos no fueron necesariamente en este sentido. De hecho los ejercicios tuvieron más foco en el proceso de delivery.

El taller tuvo una muy buena valoración por los participantes.

Aquí están disponibles los slides que utilicé durante el taller.

Agradezco a todos los participantes y espero que la sesión les haya resultado útil.

Trabajo en grupo durante el taller
Valoración del taller por los participantes en una escala de 1 a 5

Build de 10 minutos y categorización de tests

Cuando el equipo actual tomó a su cargo el sistema este tenía una alto grado de inestabilidad y prácticamente no tenía tests automatizados. Gradualmente se fueron agregando tests que ayudaron a mejorar a la estabilidad del sistema. En un punto se llegó a tener unos ~2600 tests de componentes/unitarios cuya ejecución excedía los 30 minutos. Todos estos tests eran ejecutados como parte del build de integración continua. A esto se sumaba el hecho de que equipo hacía feature-branches, los cuales también eran buildeados automáticamete, aumentando la carga del build server. Llegado un punto, cada vez que un developer hacía un commit (+push) tenía que esperar, en el mejor de los casos, unos 40 minutos para obtener feedback. Podía llevar a pasar que el build server estuviera ocupado y entonces el build quedaba encolado estirando aún más el tiempo de espera.

Ante esta situación hicimos dos cosas. En primer lugar instalamos un segundo agente del Build Server, para bajar el tiempo tiempo de espera en cola. En segundo lugar categorizamos los tests y ajustamos la configuración del build server. En este segundo punto quiero profundizar.

Es un práctica muy difundida y aceptaba, el tener un build de integración/feedback continua que no exceda los 10 minutos (algunas referencias para profundizar aquí y aquí). En línea con esto decidimos categorizar los ~2600+ tests, identificando aquellos que cubrían las partes críticas de la iteración. Identificamos unos ~600 tests fundamentales cuyo tiempo de ejecución resultó en unos 7 minutos. Categorizamos esos tests como «core». Al mismo tiempo ajustamos el build server para que se ejecuten en forma continua (ante cada commit+push) los tests «core» y de los «current» (pertenecientes a la iteración actual), de manera de poder tener un feedback «rápido». Por otro lado, creamos otra tarea que se ejecuta al fin del día para correr el set completo de tests.

 

Nuevo proyecto de CI / CD

Hacía fines de diciembre del año pasado me contactaron de una empresa para que los ayudara con una iniciativa de Integración Continua. Intercambiamos un par de mails, tuvimos una llamada telefónica de 20 minutos y acordamos una primera reunión.

Desde mi punto de vista la práctica de integración continua no es un fin en sí mismo sino que es una herramienta. Por ello, una de las primeras cosas que pregunté fue: ¿Cuál es su problema? ¿Qué esperan solucionar con esta práctica? La respuesta fue clara, había dos problemas principales: por un lado la calidad del producto y por otro el desperdicio de tiempo invertido en el despliegue de la aplicación a los distintos ambientes. Esto me permitió entender que la cuestión iba bastante más allá de la integración continua.

El desafió me pareció muy interesante, pues se trataba de una empresa grande, con equipos distribuidos geográficamente en distintos lugares de latinoamérica y cuyo negocio estaba centrado en la venta de soluciones de banca. La empresa contaba con un plataforma de productos que vendía a distintos clientes y cada venta implicaba una implementación/customización de los productos. De esta forma había equipos trabajando sobre los productos y en paralelo un equipo de implementación para cada cliente que compraba el producto.

En términos de administración de la configuración a primera vista la naturaleza del negocio llevaba a tener un trunk de producto con un branch por cada cliente. Fácil decirlo, no tan fácil de implementarlo sobre todo teniendo el código de todos los productos en un único repositorio CVS.

La plataforma tecnológica era Java, un clásico en sistemas de banca. Pero dado que la solución se vendía a distintos clientes la aplicación debía funcionar sobre distintos ecosistemas tanto a nivel base de datos, application server y service bus.

Un último condimento no menor es que gran parte del código venía arrastrándose desde hacía varios años y tenía dependencia con componentes open source ya sin soporte (por ejemplo Apache Hivemind). Adicionalmente también se estaban usando versiones viejas de algunas herramientas (por ejemplo java6  y maven2).

Cabe destacar que varias de este cuestiones no las sabia inicialmente, sino que las fui descubriendo una vez empecé a trabajar.

La situación era compleja y las expectativas del cliente eran muy grandes. Mi propuesta fue simple y concreta:

Busca un equipo que esté interesado en trabajar en esta iniciativa. Yo me siento y trabajo con el equipo codo a codo 1 mes para resolver los impedimentos que el equipo considere le impiden construir software de calidad.

Al cliente, le gustó la propuesta y la bola empezó a rodar.

Continuará…

Continuous: Integration vs Delivery vs Deployment

En los últimos dos años he repetido incontables veces la diferencia entre estas tres prácticas y dado que no encontré ninguna explicación online que me satisfaciera, he decidido escribir mi propia explicación.

Continuous Integration: el software suele desarrollarse en equipo, donde cada miembro trabaja en su máquina en una porción del software. En ese contexto, la práctica de Continuous Integration propone integrar de forma continua el trabajo realizado por cada miembro del equipo. Esto implica una serie de cuestiones como ser el uso de controlador de versiones y contar con un ambiente de integración donde puedan ejecutarse verificaciones sobre software integrado.

Continuous Delivery: en términos organizacionales esta práctica es poner en manos del negocio la decisión de cuándo ir a producción. Más concretamente eso implica que cada build exitoso pueda (si el negocio así lo decide) ir a producción. entiéndasee build como el artefacto resultante del proceso de integración)

Continuous Deployment: está práctica va más allá de Continuous Delivery e implica que cada build exitoso va automáticamente a producción. Tal como propone Jez Humble, un mejor nombre para esta práctica sería Continuous Release. Continuous Deployment implica Continuous Delivery pero no al reves.

Estas tres prácticas tienen un aspecto técnico relacionado a herramientas y aspecto humano relacionado a hábitos y reglas que las personas deben incorporar y que personalmente considero que es el mayor desafío a la hora de intentar implementar estas prácticas. Ejemplo: de nada sirve tener un controlador de versiones si los miembros del equipo hacen commit una vez por día.

El orden en que describí cada práctica tiene que ver con el orden natural de adopción de las misma. Cabe aclarar cada práctica puede implementarse con distintos «niveles de profundidad» los cuales dependerán del contexto de cada proyecto/organización.

Muchas veces al explicar estas prácticas la audiencia tiende a decir que quiere implementar Continuous Delivery ante lo cual suelo aclarar: «No todas las prácticas son necesarias para todo contexto» y a continuación pregunto: «¿Su negocio realmente necesita continuous delivery?» En determinados contextos tener Continuous Delivery puede ser imprescindible para que el negocio sea competitivo, mientras en otros contextos (posiblemente más estables a nivel de negocio), sea simplemente un nice-to-have.

Como comentaba un amigo que trabaja en la industria petrolera: «Nosotros tenemos 3 releases anuales planificados e inamovibles», en un contexto así posiblemente no se justifique el esfuerzo que implica adoptar continuous delivery. Distinto es el caso de un negocio muy variable que requiere de cambios constantes en sus aplicaciones donde no tener Continuous Delivery podría implicar perder el negocio.

Por su parte la práctica de Continuous Integration tiene algunas particularidades respecto de las otras dos prácticas. En primer lugar, es una práctica higiénica, lo cual implica que en términos generales siempre debe utilizarse. En segundo lugar es una práctica «a puertas cerradas» en el sentido que su uso está complementamente en manos del equipo de desarrollo. No es necesario aprobación y/o interacción con personas de otras áreas de las organización ni con el usuario. Si bien puede ser útil tener ayuda del grupo de infraestructura para montar un servidor de integración continua, la realidad es que no es algo imprescindible, el propio equipo puede montar un servidor de integración continua en la máquina de alguno de los miembros del equipo o bien podría utilizar algún servicio online (como Travis o CloudBees).

Para quienes quieran profundizar les recomiendo es artículo de Jez Humble: Continuous Delivery vs. Continuous Deployment.

Para cerrar les comparto un par de imagenes (de mi autoría) que esquematiza la diferencia/relación entre estas prácticas.

ci_y_cd

 

cd_y_cd

Build Tools for .NET

Setting up a build server for .NET development is not so easy like in Java. We could find several explanations for this and one of them could be the huge dependency .net developers have with Visual Studio. I have met many developer that have no idea of how to generate a build of their application without using Visual Studio. Even more, it is very common to find people installing Visual Studio in their build servers 😦 (I did that several times!). Maybe because of this, command line tools never had much popularity among .NET developers. At the same time, Visual Studio along could be not enough to create a quality build (Visual Studio out of the box can not run NUnit tests and StyleCop analysis).

My approach to build my applications is to use a build tool. For the case of .NET there a couple of build tools out there. I think the most popular are:

  • NAnt: it is basically a port of Ant, the famous build tool for Java
  • MSBuild: the Microsoft proposal
  • PSake: is a relatively new tool based on Power Shell

In my case, I choose MSBuild, but it is not enough, because this tool does not have out of box support for integration with some other tools that I use like Nunit, StyleCop, JsLint.  So  in additional to MSBuild I use a set of community extensions called MSBuild Community Tasks.

But the story does not end here, when I want to setup a new build server (or when a new member joins my team) several stuff must be installed in a new box. To simplify this setup, I have created an installation package that contains all the tools I commonly use to build my applications. I have called this package BuildTools4Net. Its current version includes the following items:

  • MsBuildCommunity Taks
  • NUnit
  • SharptLinter
  • FluentMigrator
  • StyleCop

Because of licensing concerns I can not share the my BuildTools4Net installation package, but I am working on script some you can create your own installations package.

Resultados del Taller de lntegración Continua

El jueves pasado hicimos en Kleer el taller de integración contínua. No tuvo tanta práctica como yo esperaba, pues hubo muchas consultas, pero creo que estuvo muy bien. Cubrimos todos los puntos del programa y atendimos a todas consultas de los asistentes.

Algunas variantes a considerar para futuras ediciones:

  • Enfocar el taller sólamente en Jenkins
  • Enfocar el taller en una única tecnología (Java , .Net, etc)
  • Hacer el taller de día completo o de dos medios días para poder hacer más práctica

Les dejo algunos frases de las encuestas de la evaluación completadas por los asistentes:

  • “Excelente las explicaciones y conocimientos expuestos”
  • “Muy bueno, si bien conocía algunas de las herramientas, vi un poco más en detalle todo el potencial de uso que tienen”
  • “Nada para agregar, el taller fue genial..”
  • “Excelente Didáctica y cobertura del tema”

Screencast sobre despliegue automático en .NET

El jueves pasado participé de un Meet up organizado por Microsoft Argentina en el cual presenté la estrategia de despliegue automático que estoy usando en uno de mis proyectos actuales.Como la sesión no fue grabada, grabé este screencast.

Para aquellos interesados en profundizar en este tema, les recomiendo que se sumen al taller de integración continua que voy a dictar a comienzos de diciembre.

cd_en_net

Continuous Delivery en FIUBA

La semana pasada asistí a la presentación del trabajo profesional de Hernán Carrizo.

El trabajo consistió en la implementación de un pipeline de continuous delivery en un proyecto existente. Tomé algunas notas interesantes, de directa aplicación en mi actividad profesional actual. Pero sin duda lo mejor de todo es ver que en Fiuba se hacen trabajos sobre temáticas actuales e incluso innovadoras en un punto.

Algo que me llamó la atención fue una de las preguntas de apertura de la presentación:  ¿Cuanto tiempo lleva poner en producción el cambio de una línea de código?

La presentación y el trabajo en general me resultaron muy interesantes, lo cual no me extraña considerando quienes fueron los directores del trabajo: Carlos Fontela y Juan Gabardini, Say no more.

Jenkins: Plugins infaltables

De cara a automatizar parte de la corrección de los trabajos de los alumnos de la materia que dicto en UNQ, ayer estuve configurando un Jenkins. La idea es que los alumnos entreguen sus trabajos via Github, o sea, cada alumno tendrá un repositorio en GitHub. Llegada la fecha de entrega de cada trabajo, el build server (Jenkins en este caso) descaga los repositorios y verifica que existan archivos correspondientes a la entrega.

Como parte de la configuración de este Jenkins, instalé los siguientes plugins que me parecen fundamentales:

  • Git: la función de este plugin es obvia, permite a Jenkins conectarse con repositorios Git
  • Green Balls: por defecto, Jenkins representa el estado «build exitoso» con el ícono de una pelotita azul. Este plugin cambia dicha pelotita azul por una pelotita verde.
  • Copy Artifact: permite copiar artefactos de un proyecto a otro
  • Email Ext: extiende la funcionalidad de notificaciones de email provista por nativamente por Jenkins

Anteriormente había comentado sobre un plugin para enviar notificaciones via Jabber (particularmente gtalk), en esta ocasión no lo instalé, pues creo que dicho plugin resulta útil para cuando uno trabajar en desarrollo y este no es el caso.

Cierre de cuatrimestre a puro TDD (algo3, 1c-2012)

Y se fué uno más, pero distinto y para bien. En líneas generales mantuvimos la misma modalidad que los cuatrimestres anteriores, pero creo que en esta ocasión hemos manejado mejor los tiempos y hemos resultado «más convincentes» en algunas cuestiones.

Entre los cambios del curso Jueves-tarde sumamos un nuevo colaborador docente: Diego Marcet, graduado de la casa, ex-alumno de la materia y ex-compañero mio de trabajo en Southworks.

Otro de los cambios implementados fue el uso del campus virtual (basado en Moodle) para la publicación del material de estudio. Yo personalmente fuí un poco más allá y lo utilicé para manejar la interacción con mis grupos vía los foros. La ventaja que le veo al uso de foros tiene que ver con que la resulta muy cómodo visualizar el hilo completo de la conversación.

A mi parecer la particularidad más destacada (al menos de nuestro curso) fue el fuerte incampié que hicimos en el uso de TDD, lo cual dió sus frutos en el trabajo final, donde varios alumnos desarrollaron gran parte de trabajo usando esta técnica.  Es más, la cantidad de pruebas unitarias de los TP finales fue record en el caso de los TPs que yo corregí: me entregaron TPs con más de 200 pruebas unitarias, llegando a niveles de cobertura llegando al 80%.

La última innovación a mencionar es la práctica de integración contínua. Si bien este tema lo vemos en la teoría desde hace varios cuatrimestres, este año fui más allá y levante un servidor de integración contínua para mis alumnos (lamentablemente no tenía una gran infraestructura, asi que solo lo pude hacer para los 3 grupos a mi cargo). El proceso de build incluyó: compilación, ejecución de pruebas y medición de cobertura.

Si bien no hicimos la dinámica de retrospectiva global, yo hice una más reducida con los alumnos de mis grupos y el feedback fué muy positivo: solo surgieron algunas cosas menores para mejorar que comentaré en un próximo post.