Capítulo 1. Implementación continua

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Desde que la ingeniería de software es una disciplina,, se ha prestado mucho cuidado y atención al código de las aplicaciones y a su arquitectura. Se han originado todo tipo de paradigmas, lenguajes de programación y patrones arquitectónicos para garantizar que el código esté bien organizado en los editores de los desarrolladores y funcione eficientemente después en producción. Hizo falta más de medio siglo para darnos cuenta colectivamente de que no habíamos pensado lo suficiente en lo que ocurre entre medias.

Implementaciones cada pocos meses o años

Antes de a principios de la década de 2000, el camino del producto de software medio hacia la producción era un viaje propenso a errores y torpe, lleno de tareas manuales repetitivas. En este viaje, los cambios de los colaboradores individuales se integraban a menudo con retrasos, los artefactos se construían a mano, las configuraciones y dependencias se ajustaban fuera del control de versiones, los pasos de implementación mal documentados se ejecutaban en secuencias meticulosas... y no olvidemos las pruebas, que se realizaban minuciosamente a mano para cada nueva versión. Como resultado, los ciclos de vida de las versiones podían durar meses o incluso años. La Figura 1-1 es una representación basada en hechos de aquellos tiempos.

Figura 1-1. El camino típico hacia la producción antes de principios de la década de 2000

Un camino tan largo hasta la producción significaba que toda la inversión inicial en ingeniería de diseño de software no daría sus frutos hasta mucho más tarde. A menudo, para cuando el nuevo código llegaba por fin a los usuarios (si es que llegaba), los requisitos originales ya habían cambiado o, por desgracia, el mercado había cambiado, con lo que el código resultaba irrelevante.

Afortunadamente, eso ha cambiado. En las dos últimas décadas, las empresas y organizaciones se han acostumbrado cada vez más a lanzar software rápidamente para impulsar sus operaciones sin sacrificar la fiabilidad. Incluso en un escenario (muy) hipotético en el que una empresa pueda presumir de una base de código impecable y un producto excelente, un lanzamiento a lo grande cada uno o dos años ya no es una estrategia sostenible para seguir el ritmo de las demandas del mercado. Por eso, en las dos últimas décadas, hemos visto que cada vez se presta más atención a acortar el camino que va del "código comprometido" al "código ejecutándose delante de los usuarios". La atención ya no se centra sólo en escribir código de buena calidad, sino también en garantizar que se libere rápidamente y sin dolor a producción. Al fin y al cabo, la producción es el único entorno en el que el código puede pagar la deuda que ha contraído por haber sido escrito en primer lugar.

Implementaciones cada pocos días

Las empresas ya han ido acortando cada vez más sus ciclos de vida de entrega de software, y lo han conseguido principalmente mediante el uso de la automatización. La razón de ser de las ventajas de la automatización no es ningún misterio. Cualquier tarea o decisión humana representa un cuello de botella en el vertiginoso mundo del desarrollo de software. Tanto nuestro tecleo como nuestro pensamiento son varios órdenes de magnitud más lentos que el ritmo al que se ejecuta el código, y ambos son mucho más propensos a cometer errores. Por lo tanto, los principales componentes del camino a la producción que solían realizarse manualmente, como la creación de artefactos, las pruebas y la implementación, se han automatizado a través de diversas herramientas a lo largo del tiempo (véase la Figura 1-2).

Figura 1-2. El camino típico hacia la producción en la actualidad

Sin embargo, reducir la absorción de la automatización a simplemente "algunas herramientas" sería hacer un flaco favor a mis lectores, ya que las herramientas son sólo un resultado tangible de algo mucho más interesante: un conjunto de escuelas de pensamiento que cambiaron el paradigma de escribir código a entregar software. Prácticas como eXtreme Programming (XP), DevOps, integración continua (CI) y entrega continua (CD), todas ellas ampliamente adoptadas en la actualidad, defendieron este cambio de enfoque. Si no has oído hablar de ellos, te animo a que te familiarices un poco más con ellos antes de sumergirte en este libro.1 Al fin y al cabo, la implementación continua se apoya en los hombros de gigantes, y esos son sus nombres.

XP, DevOps, CI y CD introdujeron la automatización y la repetibilidad en el camino hacia la producción, desde el momento en que se registra el código hasta el momento en que se implementa, reduciendo al mínimo la intervención manual. Esta automatización proporcionó la base técnica tan necesaria para alcanzar la velocidad sin comprometer la seguridad. Lo que siguió fue también un reto para que los ingenieros de software cultivaran un conjunto aún más amplio de habilidades en torno a las secuencias de comandos y la infraestructura, y asumieran la propiedad de su trabajo a un nivel que va mucho más allá de ver su código ejecutarse en un ordenador portátil. Este cambio de mentalidad no se limita sólo a la gente técnica: estas prácticas también han desafiado a las organizaciones a replantearse su cultura general (y su estructura) en torno a la fabricación de software a medida. Antes de ellas, enormes lotes de trabajo se pasaban de un departamento segregado a otro, con poca o ninguna comunicación entre ellos. Después de ellos, empezamos a ver la aparición de equipos interfuncionales capaces de ocuparse de sus productos de principio a fin.

Estos movimientos ya han producido resultados que antes eran impensables: hacer que los ciclos de lanzamiento de software sean más fiables y drásticamente más rápidos. Como resultado, más de dos tercios de las empresas pueden ahora implementar en producción entre una vez al día y una vez al mes.2

Implementación continua

Implementación continua es otro paso adelante en la progresión de la excelencia en ingeniería que ha visto cómo la automatización se apoderaba del camino del software hacia la producción. En cierto sentido, la implementación continua representa su culminación lógica. Mientras que sus predecesores automatizaban parte o incluso la mayor parte del recorrido del código hasta los usuarios, la implementación continua lo automatiza todo. Incluso la decisión de realizar la implementación final en producción la toma un agente de canalización, no una persona.

En pocas palabras, la implementación continua significa que una confirmación que se envía o fusiona en la rama principal siempre da lugar a una implementación en producción (siempre que todas las puertas de calidad estén en verde). Por primera vez, el viaje desde "código confirmado" a "código ejecutándose delante de los usuarios" no encuentra intervención manual alguna, y se completa en la granularidad de cada confirmación. Al eliminar hasta el último cuello de botella humano, la implementación continua reduce aún más el bucle de retroalimentación del software, de días u horas a meros minutos.

Una aceleración tan drástica tiene importantes consecuencias para los ingenieros, que trabajan sabiendo que el más mínimo incremento de código será sometido a una retroalimentación de calidad de producción completa prácticamente de inmediato. Con la implementación continua, las tareas ya no están "hechas en desarrollo, a la espera de que la implementación en producción tenga éxito más adelante"; están hechas de forma real y demostrable. Las propias Implementaciones de producción se vuelven triviales en virtud de su frecuencia, ya que el delta de cambios es de unas pocas líneas, en lugar de días o semanas de cambios acumulados, lo que reduce enormemente los riesgos asociados a cada implementación. (Arrojaré más luz sobre la relación entre el tamaño de la implementación y la frecuencia de la misma en el Capítulo 2.)

Pero como ocurre con la mayoría de las prácticas de ingeniería, el verdadero cambio de paradigma en la implementación continua se evalúa mejor desde el punto de vista de las empresas que lo adoptan. Si los incrementos de código de producción pueden ser máximamente granulares y rápidos como el rayo, los incrementos de producto también pueden serlo. Las pequeñas (o grandes) decisiones de producto pueden tomarse y revertirse mucho más fácilmente, y hacerse en el último momento posible, que es también la forma más responsable de tomar tales decisiones.3 Las sorpresas repentinas en el comportamiento o los requisitos de los usuarios pueden abordarse inmediatamente, sin implementaciones pendientes que atasquen el camino hacia la producción y compliquen los cambios de última hora. Las propias versiones ordinarias se dividen en trozos tan pequeños que es posible experimentar y calibrar el comportamiento del usuario con precisión, si eso es lo que se desea hacer. Un proceso así lleva al extremo el valor de "responder al cambio" de Agile, y ofrece los bucles de retroalimentación más estrechos posibles dentro del paradigma del desarrollo iterativo.

En mi experiencia profesional, la implementación continua se ha traducido en una mejora de todas las métricas que importaban a mis equipos a la hora de entregar software: el tiempo que se tardaba en entregar cualquier cambio, el número de cambios que podíamos entregar en total, la tasa de defectos y la velocidad a la que nos recuperábamos de ellos. En este libro, quiero compartir esa experiencia porque creo que la conversación sobre el viaje desde el "código comprometido" hasta el "código funcionando en producción" está todavía muy presente. Espero que este libro represente una contribución positiva a ello: situar la implementación continua al mismo nivel que todas esas otras prácticas tan apreciadas.

Entonces, ¿cómo funciona exactamente la implementación continua? ¿Qué más aporta al camino del código hacia la producción que no se haya conseguido ya? ¿En qué se diferencia de su pariente muy cercano, la entrega continua? ¿Y por qué importa esa diferencia?

Para responder a estas preguntas, tenemos que remontarnos a los orígenes de este movimiento de automatización y dedicar algún tiempo a comprender las prácticas que lo precedieron. Sólo comprendiendo los principios que guían a sus predecesores podremos apreciar cómo se basa en ellos la implementación continua .

Empecemos cronológicamente: con la introducción de la Programación eXtreme.

Programación eXtreme

Las tareas como las pruebas, la revisión, la integración y la implementación son fundamentales en el camino del código hacia la producción, pero también pueden ser dolorosas y difíciles de ejecutar. Por ello, solían relegarse al final de las iteraciones largas, se realizaban con poca frecuencia y se hacían casi siempre a mano.

El cambio de discurso en torno a estas tareas se aceleró entre finales de los 90 y principios de los 2000 con la popularización de la Programación eXtrema (XP), que llevó al centro de la conversación estas actividades no relacionadas con la codificación que se encuentran en los márgenes del desarrollo de software. XP es una metodología de software ágil que hace hincapié en realizar las partes más importantes del desarrollo de software (que no son necesariamente escribir software) con la mayor frecuencia posible. Como escribe Kent Beck en Extreme Programming Explained: "Toma todo lo valioso de la ingeniería de software y pon los diales a 10".4 Este proceso implica prácticas como la programación por parejas, en la que dos programadores trabajan juntos en una misma estación de trabajo (revisando así el código continuamente); el desarrollo dirigido por pruebas, que implica escribir pruebas antes que el código (probando continuamente); y la integración continua, en la que los cambios de código se integran en la rama principal con la mayor frecuencia posible (ésta incluso tiene "continua" en el nombre).

XP fue uno de los primeros movimientos en desafiar el anticuado comportamiento de retrasar los pasos dolorosos, y sugirió en su lugar que aumentar la frecuencia de estas tareas (hacerlas continuamente) reducirá a su vez su dificultad. Puede parecer contraintuitivo, pero el lema de XP fue el primer principio que permitió la automatización del viaje del código a la producción: "Si duele, hazlo más a menudo".

Si duele, hazlo más a menudo

Cuando empecé, pensaba que si revisar, integrar, probar e implementar eran tareas dolorosas, seguramente querríamos aplazarlas todo lo posible. ¿Por qué íbamos a querer hacerlas más a menudo de lo necesario? Podríamos escribir nuestro código en nuestros pequeños jardines amurallados (o ramas de características) durante semanas y semanas, y cuando el infierno de la fusión y la liberación no pudiera posponerse más, podríamos agachar la cabeza unos días y acabar de una vez. Entonces podíamos olvidarnos por completo del calvario y volver a la paz y tranquilidad de nuestros jardines de código personales. Eso, hasta que alguien pidiera a nuestro equipo que mostrara otra versión funcional del software, incluyendo todas las nuevas funciones en las que habíamos estado trabajando individualmente. Entonces, tendríamos que empezar de nuevo. Si esas molestas partes interesadas dejaran de interrumpirnos con sus demostraciones y lanzamientos, pensé. Entonces, ¡los desarrolladores podríamos hacer el trabajo de verdad por aquí!

Empecé a comprender lo que significaba realmente "Si duele, hazlo más a menudo" sólo después de trabajar en equipos en los que teníamos que integrar y liberar en distintos calendarios. Curiosamente, cuanto más corta era la cadencia, menos trabajo tenía que hacer nuestro equipo para tener listo nuestro software, y menos retrabajo llegaba a nuestros escritorios. "Si duele, hazlo más a menudo" no se refiere a sentir más dolor por la integración y las Implementaciones, sino a cómo aumentar su frecuencia nos permite sentir menos dolor. Y no sólo menos dolor en cada lanzamiento, sino menos dolor en general.

Tandas más pequeñas y menos dolorosas

Realizar las actividades más dolorosas, como fusionar, probar e implementar, más a menudo significa que cantidades cada vez menores de código tienen que pasar por esa actividad. Esto se debe a que los commits no tienen la oportunidad de acumularse mientras esperan a ser procesados. Cuanto más a menudo integremos, probemos e implementemos nuestro software, menos software necesitaremos integrar, probar e implementar cada vez.

Integrando a menudo, los deltas de los cambios son lo suficientemente pequeños como para que las fusiones sean sencillas. Al implementar a menudo, los errores que podrían haber llevado días de investigación pueden, en cuestión de horas, ser rastreados hasta el cambio que los introdujo; después de todo, las líneas de código que hay que examinar son muchas menos.

Incentivo para la automatización

Hacer las cosas más a menudo (y en lotes más pequeños) es también un fuerte incentivo para que los desarrolladores agilicen los procesos repetitivos y arriesgados. Automatizar una tarea -por pesadillesca que fuera- que solía realizarse una vez cada luna azul no tenía mucho sentido antes de que las iteraciones cortas se convirtieran en la norma. Pero automatizar una secuencia diaria de pasos propensos a errores sí que lo tenía. Así que la automatización empezó a tomar el relevo, y ahora tenemos canalizaciones que sondean automáticamente nuestros últimos cambios de código desde el control de versiones, construyen artefactos a partir de él, ejecutan todo tipo de pruebas automatizadas e incluso realizan implementaciones por sí solas. Tendemos a automatizar estas tareas cuando hacerlas más a menudo pone de manifiesto lentitud e ineficiencias y, francamente, las convierte en un montón de trabajo. Una de las mejores virtudes de nosotros, los programadores, es nuestra pereza.

Como resultado, las fases de integración, prueba y lanzamiento, que solíamos temer, se han vuelto mucho menos dolorosas, básicamente rutinarias para muchas empresas. Esto no ocurrió a pesar de que los mercados exigieran que hiciéramos estas cosas más a menudo, sino porque las empresas empezaron a hacerlas más a menudo.

La reducción del dolor y el aumento de la frecuencia también han permitido a nuestras empresas recabar opiniones sobre nuevas iniciativas mucho antes y ayuda a reducir el despilfarro definitivo: construir cosas que los usuarios no quieren o no necesitan.

Aplicar esta idea de "hacer las cosas dolorosas más a menudo, en lotes más pequeños, y automatizar todo lo posible" ha simplificado radicalmente las partes más dolorosas de la entrega de software. Pero, como ya hemos comentado, estas mejoras no se produjeron de golpe. Diferentes prácticas tomaron el relevo de los primeros buenos instintos de XP para desempeñar un gran papel en los años siguientes. Siguiendo el principio de "si duele, hazlo más a menudo", el camino del software hacia la producción se automatizó más tarde de una en una: empezando por la creación de artefactos y terminando en las implementaciones en producción.

Por ejemplo, podría decirse que las conocidas prácticas de CI y CD tienen sus raíces, respectivamente, en el dolor de integrar nuestro código con el de otras personas y en el dolor, aún peor, de entregar software listo para producción. Algunos podrían incluso decir que la práctica de DevOps tiene sus raíces en el dolor de la falta de comunicación y la fricción entre los departamentos tradicionales de Desarrollo y Operaciones.

Pocas personas citarán XP hoy en día, pero la mentalidad que sembró sigue guiando a equipos y organizaciones a medida que reducen sus bucles de retroalimentación y salen al mercado cada vez más rápido. Repasemos un poco más la historia para comprender lo que ocurrió tras su introducción en .

DevOps

DevOps es no un título de trabajo (lo siento, reclutadores), sino el nombre de un movimiento que surgió como respuesta a la separación disfuncional entre las actividades de escribir y ejecutar software. Surgió entre 2007 y 2008, y en 2009 Patrick Debois fundó la primera conferencia DevOpsDays.5 El movimiento continuó con la publicación de dos obras clave El Proyecto Phoenix6 y más tarde, El Manual DevOps.7

DevOps pretende derribar la barrera tradicional entre el desarrollo de software y las operaciones de TI, que solían ser departamentos distintos y aislados. En otras palabras, los desarrolladores solían centrarse únicamente en escribir código, mientras que operaciones era responsable de su implementación y mantenimiento en producción.

El movimiento DevOps trató de cambiar eso, ya que identificó esa separación como la culpable de gran parte del dolor asociado a la liberación y el funcionamiento del software en aquel momento. En su lugar, fomentó una cultura de colaboración e integración entre ambas funciones, con el objetivo de establecer una vía de aprendizaje continuo entre ellas. A nivel técnico, esto también fomentaba el aprendizaje continuo en términos de lecciones aprendidas en producción que se retroalimentaban al proceso de desarrollo.

Profundicemos en esas disfunciones para entender por qué.

La barrera entre desarrollo y operaciones

Antes de DevOps, la mayoría de los equipos de desarrollo y operaciones trabajaban aislados unos de otros, a veces físicamente, con departamentos en plantas diferentes o incluso en edificios distintos. Esto conducía rápidamente a una falta de comprensión del trabajo y las prioridades de cada uno, y dificultaba los traspasos entre departamentos. Por supuesto, la falta de comunicación sólo empeoraba cuando la última implementación no funcionaba como se esperaba (lo que ocurría a menudo), lo que daba lugar a muchas acusaciones y a una actitud general de "tirarse los trastos a la cabeza".

La separación también dio lugar a silos de conocimiento, que dificultaban la capacidad de abordar los problemas con eficacia (especialmente los que se situaban en la frontera entre el código de la aplicación y la infraestructura). Los desarrolladores tenían una visibilidad limitada de cómo funcionaba su código en producción, mientras que los de operaciones tenían una visión limitada del código base y de sus dependencias y configuración. Esta falta de visibilidad hacía mucho más difícil diagnosticar los problemas, lo que se traducía en tiempos de resolución más largos y un aumento general del tiempo de inactividad. También hacía que el software fuera más propenso a desarrollar esos problemas en primer lugar, ya que no se escribía teniendo en cuenta las condiciones de producción o la operatividad.

Sin embargo, y lo que es más importante, este proceso de "traspaso" entre departamentos era uno de los principales responsables de la lentitud de los ciclos de entrega en aquella época. Un traspaso de código entre departamentos con fines de implementación conllevaría, por supuesto, tiempos de implementación más largos. Los tiempos de implementación más largos provocarían retrasos en la publicación de nuevas funciones y la incapacidad de responder con rapidez a los cambios de requisitos o a los comentarios de los usuarios.

Abordar todas estas disfunciones sólo sería posible eliminando el problema organizativo que las origina: la separación entre departamentos.

Uniendo Desarrollo y Operaciones

Debido a estos problemas, el movimiento DevOps aboga por tender un puente entre ambas funciones. No debería sorprender que el principal principio del movimiento se centre en la comunicación, la colaboración y una reorganización organizativa fundamental.

DevOps consiste en evitar los traspasos y garantizar la propiedad compartida del código, su proceso de implementación y su permanencia en producción. Hoy en día, un "verdadero equipo DevOps" es interfuncional. Es un equipo que realiza cambios tanto en el código como en la infraestructura, los despliega y da soporte a los sistemas resultantes en producción; como dijo el famoso CTO de Amazon, Werner Vogels: "Tú lo construyes, tú lo ejecutas". Y no se detiene en la infraestructura. DevOps aboga por que todas las funciones necesarias para evolucionar y mantener un producto se integren en el equipo (por ejemplo, control de calidad, seguridad). Esto no significa que los ingenieros especializados sean cosa del pasado, por supuesto. Significa que cada equipo puede, y debe, responsabilizarse de la pila tecnológica de su aplicación de arriba abajo. Citando el Manual DevOps:

Imagina un mundo en el que los propietarios del producto, Desarrollo, QA, Operaciones de TI e Infosec trabajan juntos, no sólo para ayudarse mutuamente, sino también para garantizar el éxito de toda la organización. Trabajando por un objetivo común, permiten el flujo rápido del trabajo planificado a la producción (por ejemplo, realizando decenas, cientos o incluso miles de implementaciones de código al día), al tiempo que logran una estabilidad, fiabilidad, disponibilidad y seguridad de primera clase. En este mundo, los equipos multidisciplinares comprueban rigurosamente sus hipótesis sobre las funciones que más satisfarán a los usuarios y promoverán los objetivos de la organización. No sólo se preocupan de implementar las funciones para los usuarios, sino que también se aseguran activamente de que su trabajo fluya con fluidez y frecuencia a través de todo el flujo de valor, sin causar caos ni interrupciones a Operaciones de TI ni a ningún otro cliente interno o externo. [...] Al añadir la experiencia de QA, Operaciones de TI e Infosec a los equipos de entrega y a las herramientas y plataformas automatizadas de autoservicio, los equipos pueden utilizar esa experiencia en su trabajo diario sin depender de otros equipos.8

Este cambio de departamentos aislados a equipos interfuncionales fue fundamental. La colaboración temprana y frecuente en el ciclo de vida del software mejora la calidad del propio software porque todas las perspectivas necesarias se tienen en cuenta al principio de la fase de desarrollo, lo que reduce los problemas y la repetición del trabajo más adelante. Por ejemplo, el software se vuelve más operable en producción porque los desarrolladores se benefician (o sufren) finalmente las consecuencias de operabilidad de las decisiones que toman. Considero que éste es un ejemplo perfecto del principio "Duele [la comunicación entre Dev y Ops], así que lo hacemos más a menudo" en la práctica.

La colaboración y los equipos interfuncionales son también lo que desbloqueó la automatización del camino del software a la producción, que es el segundo principio del movimiento DevOps y el tema central de este capítulo. Al fin y al cabo, la automatización del camino a la producción no habría sido posible si su propiedad hubiera estado dispersa en múltiples departamentos.

Automatización, Automatización, Automatización

El otro principio básico de del movimiento DevOps es, de hecho, su enfoque explícito en la automatización. La automatización de tareas repetitivas y manuales, como el aprovisionamiento de la infraestructura, la gestión de la configuración, las pruebas y la implementación, ha sido un interés clave de DevOps por todas las razones que ya hemos comentado: es más rápido, reduce el riesgo y permite a los equipos agilizar procesos que, de otro modo, serían torpes y propensos a errores.

Aunque la automatización ya había sido popular antes, DevOps es el movimiento que más énfasis ha puesto en ella, elevándola a principio básico y ciudadano de primera clase en lugar de un agradable efecto secundario de otras prácticas.

El auge de la computación en nube también coincidió convenientemente con la aparición de DevOps, y constituyó una excelente base técnica para apoyar este principio.

La computación en nube proporcionó a los desarrolladores una capa de abstracción muy necesaria sobre la infraestructura física, y disminuyó la necesidad de conocimientos profundos en las áreas de mantenimiento de servidores y redes. También permitió a los equipos desmontar y reconstruir rápidamente la infraestructura, lo que ha tendido a hacerla más inmutable y predecible. Para entender por qué, me basaré en una distinción popular en la comunidad DevOps: la que existe entre servidores "mascota" y "ganado". Los servidores de los centros de datos locales suelen tratarse como "mascotas", mientras que los servidores en la nube son más análogos al "ganado". Las mascotas son servidores muy personalizados que no se pueden apagar (y al igual que las mascotas reales, suelen pertenecer a alguien, lo que va en contra del principio de propiedad compartida). Por otro lado, los servidores de ganado son desechables: pueden borrarse y reconstruirse desde cero en caso de fallos, perdiendo cualquier personalización en el proceso. Esto significa que la inmutabilidad se convierte en un requisito y que los cambios manuales puntuales se convierten en un antipatrón, lo que constituye una gran base para la automatización.

Desde entonces, la capa de abstracción que proporciona la computación en nube ha evolucionado aún más, generalizándose las herramientas de infraestructura como código (IaC) de. La IaC ha permitido a los equipos representar la infraestructura necesaria para ejecutar su software como archivos "ejecutables" controlados por versiones. Esto ha permitido una automatización aún mayor, y ha hecho que la infraestructura sea tan fácilmente versionable y autodocumentable como el código de la aplicación, por no mencionar que es más fácil de gestionar por los desarrolladores.

La capacidad tanto de abstraer la infraestructura física como de representarla dentro de su propia base de código es lo que desbloqueó las capacidades de implementación para las canalizaciones automatizadas, que son fundamentales para la práctica de la integración continua y la entrega continua. Ésas son las prácticas de las que hablaremos a continuación .

Integración continua

La siguiente práctica fundamental para la automatización de la entrega de software fue la integración continua (IC), que cambió radicalmente los pasos iniciales del camino a la producción. Fue popularizada en 2007 por Paul Duvall en Integración Continua. En realidad, la integración continua ya fue descrita como práctica por XP, pero como las prácticas de apoyo que la rodean tardaron en desarrollarse y el libro de Duvall es el relato más completo al respecto, lo inserto aquí en nuestra historia. Desde entonces, las herramientas de IC han proliferado y se han generalizado.

Debido a la abundancia de herramientas y a su popularidad, la integración continua ha sufrido una difusión semántica9 y se ha convertido en sinónimo de herramientas de canalización automatizada a lo largo de los años. Pero en su esencia, la IC no es una instalación de Jenkins, CodeShip o Travis. Es la práctica de integrar los cambios de los desarrolladores con la mayor frecuencia posible en la misma rama controlada por versiones.

Integrar grandes trozos de cambios es doloroso y propenso a errores (duele), por lo que se puede mejorar haciéndolo continuamente (lo hacemos más a menudo). En resumen, la IC consiste en garantizar que la cantidad de código que hay que fusionar y verificar se reduce al mínimo.

La IC puede conseguirse añadiendo cambios de código al "tronco" (maestro, o principal) tan a menudo como sea posible. El tronco es donde reside la última versión del código de todos, por lo que es el único lugar donde puede producirse una verdadera integración. En la práctica, esto se consigue mejor con el desarrollobasado en el tronco (TBD), en el que el código siempre se envía directamente a la rama principal. TBD significa renunciar a las ramas de características, que son la definición misma de "jardines amurallados" de código, donde los commits pueden acumularse y la integración puede retrasarse infinitamente.

Entonces, ¿es imposible hacer IC con ramas? Exploraremos este tema más a fondo en el Capítulo 3, pero por ahora puedo decir lo siguiente: no es estrictamente imposible, pero sin duda es mucho más difícil. Algunos equipos logran una integración continua satisfactoria utilizando ramas de corta duración y/o pull requests (PRs), pero lo hacen integrando en el tronco con la mayor frecuencia posible -idealmente, al menos una vez al día-.10 Así que, aunque es posible, las ramas y los PR dificultan hacer lo correcto (acordarse de integrar a menudo) y facilitan hacer lo incorrecto (añadir "sólo" otra confirmación sin integrar). TBD hace lo contrario.

Ahora que hemos hablado de la integración, hablemos del aspecto más conocido de la metodología CI: el canal de construcción automatizado . Puedes verlo en la Figura 1-3. Funciona así: una vez que el código se fusiona o se confirma en el tronco, un servidor centralizado compartido por todo el equipo detectará un cambio en el sistema de control de versiones. Cuando detecta el cambio, convierte el código en un artefacto. Un artefacto es el "paquete" final que contiene todo el código, las dependencias y la configuración necesarios para que funcione la nueva versión de la aplicación. Por ejemplo, un artefacto puede ser un binario compilado, un archivo comprimido, un archivo .jar o .war, o incluso mejor, una imagen contenedora. Una vez creado ese artefacto, la canalización verifica su corrección mediante pruebas automatizadas y herramientas de inspección del código. A continuación, la canalización de compilación compartida proporciona información al equipo mediante radiadores de información, y les notifica cuando falla alguna de las comprobaciones.

Figura 1-3. El proceso automatizado de IC

Esta automatización en torno al pipeline, unida a la integración temprana y frecuente, mejora enormemente la granularidad de las fases de construcción y prueba. Mientras que antes se realizaban de vez en cuando, ahora se activan con cada commit, lo que acorta el bucle de retroalimentación integrar-construir-probar y hace que los defectos sean mucho más fáciles de detectar.

La cadena de construcción automatizada es, en efecto, un concepto poderoso, pero la IC es más que una herramienta. Es un conjunto de prácticas y acuerdos mutuos que funcionan dentro de un equipo. Integrar a menudo y mantener en verde el pipeline compartido son los principios cruciales de la IC, ya que el estado del pipeline representa la capacidad fundamental de tener una versión de trabajo probada del software. Si tenemos una última versión de nuestro código que funcione y esté probada, estar preparados para su implementación a corto plazo ya no es un gran esfuerzo.

Si el pipeline de está en rojo, o si no hemos fusionado en mucho tiempo, no hay ningún artefacto más reciente ni nada nuevo que implementar: es como si el código nuevo no existiera en absoluto y el equipo no hubiera hecho ningún progreso desde la última compilación en verde. Como me dijo David Farley al revisar este libro: "¡Eso es porque, en términos prácticos, no lo han hecho!".

Disponer de esta fuente centralizada de verdad y validación ha cambiado radicalmente la forma de trabajar de los desarrolladores, desplazando la definición de hecho de "Bueno, funciona en mi máquina" a "Funciona una vez que se integra, se construye y se demuestra que funciona". Fusionar, construir y probar eran antes tareas penosas que ahora se han convertido en algo corriente, eliminando la necesidad de cualquier apuro de última hora para tener algo listo. Y las partes interesadas no podrían estar más agradecidas por ello.

Como mencioné al principio del capítulo, antes de que apareciera el concepto de IC, había poca ingeniería en torno al proceso para que el código llegara a sus usuarios una vez escrito. La integración continua fue la primera práctica que cambió eso, y el concepto de canalización centralizada ha sido la base de toda la automatización que le siguió.

Entrega continua

Poco después de la integración continua, llegó el concepto de entrega continua (EC), que puede considerarse el siguiente paso obvio en la automatización del camino a la producción. Fue popularizado en 2010 por Jez Humble y David Farley en Entrega Continua, y desde entonces ha disfrutado de un nivel de popularidad similar al de la integración continua. Se ha convertido en el último estándar de facto para las prácticas de ingeniería y el que la mayoría de las empresas se esfuerzan por implantar hoy en día. Esto se hace evidente por el hecho de que la mayoría de las herramientas de canalización automatizada más populares cuentan ahora con todas las capacidades necesarias para realizar la DC además de la IC.

De hecho, la base técnica de esta práctica requiere ampliar la funcionalidad de la canalización automatizada(Figura 1-4). El canal en sí sigue construyendo y validando la última versión del código, pero la DC también establece que debe ser capaz de implementarse en cualquier entorno de forma automatizada, en cualquier momento. Esto puede lograrse mediante herramientas de IaC y de aprovisionamiento (otro regalo del movimiento DevOps), que garantizan la automatización y repetibilidad de las Implementaciones.

Figura 1-4. El proceso automatizado de DC

En la implementación más habitual de la CD, cada compilación se promocionará automáticamente y se desplegará en un entorno de ensayo o UAT, o incluso en varios de ellos. Una vez automatizadas las Implementaciones, se pueden ejecutar sofisticadas pruebas automatizadas contra esos entornos de producción. Como resultado, cada incremento de código que llega al final de la canalización tiene una probabilidad de corrección tan alta que puede considerarse un candidato a versión. La implementación en producción de esta versión candidata puede activarse bajo demanda, normalmente a través de la misma herramienta de canalización.

Con la CD, el pipeline automatizado propiedad del equipo de desarrollo se convierte en la herramienta que cubre todo el camino de la aplicación hasta la producción. De este modo, por fin cierra la brecha entre las funciones tradicionales de Desarrollo y Operaciones, permitiendo que un solo equipo se encargue por completo tanto del desarrollo como de las Implementaciones.

Sin embargo, al igual que la IC, la DC no representa sólo una herramienta. Ante todo, representa un conjunto de formas de trabajar para aprovechar la herramienta con éxito. En el caso de la CD, esas formas de trabajar se centran en un concepto sencillo: garantizar que el código base esté siempre en estado desplegable (tratar cada confirmación como una versión candidata), de modo que se pueda aprovechar el canal automatizado para desplegarlo en producción en cualquier momento. Esto permite a los equipos aumentar drásticamente su frecuencia de implementación. Una mayor frecuencia de despliegue conlleva cada vez menos líneas de código entre una implementación y la siguiente, lo que reduce el riesgo medio de despliegue. Una vez más, se trata del principio "Si duele, hazlo más a menudo" en acción.

Los bucles de retroalimentación más cortos que introduce esta práctica también ponen sobre la mesa algo mucho más valioso que reducir las molestias de las Implementaciones. Con el CD, mostrar la última versión de nuestro software a las partes interesadas no es ni mucho menos un inconveniente como lo era antes. Es probable que la versión más reciente del software se encuentre en todo momento en una instancia de preprod recién implementada, ya que ha sido enviada allí por la última ejecución del pipeline. En la mayoría de los casos, todo lo que tenemos que hacer es abrir una nueva pestaña en nuestro navegador para obtener una demostración funcional en un entorno real. Esto era impensable en la época de las Implementaciones manuales, especialmente con la sobrecarga de comunicación añadida por tener equipos de Desarrollo y Operaciones separados.

Con el CD, las partes interesadas pueden ver el software rápidamente, y ponerlo a disposición de los usuarios finales es sólo un paso más. La implementación en producción no tiene que programarse con meses de antelación; puede hacerse fácilmente varias veces a la semana. Los requisitos pueden ser validados mucho más rápidamente que antes, por los probadores, las partes interesadas y, lo que es más importante, el mercado. Resulta que cuando realizamos implementaciones más a menudo, permitimos que nuestra organización obtenga información y se adapte al mercado también más a menudo. En muchos casos, esto se traduce en construir menos software, ya que la retroalimentación temprana hace que los propietarios del producto se den cuenta de que una característica o todo un sistema llegó a ser "suficientemente bueno" antes de lo esperado.

Si la entrega continua ha establecido algo, es que "el verdadero trabajo por aquí" para nosotros, los desarrolladores, nunca fue producir código sin fin en un jardín amurallado, sino publicar software que funcione pronto y a menudo. Sólo así podemos aportar valor a los usuarios lo antes posible.

En resumen, la evolución de la IC a la DC puede enmarcarse en términos de lo que se está automatizando: CI automatiza la determinación de "¿Parece mi cambio seguro y autónomo?", mientras que CD automatiza la determinación de "¿Es mi cambio desplegable?". Más adelante, veremos cómo la DC automatiza la pregunta: "¿Debo desplegarlo ahora?".

Una puerta final a la producción

La mayoría de las empresas implementan la entrega continua de tal forma que las implementaciones se producen sin intervención humana en al menos algunos entornos de preproducción para cada compilación. Sin embargo, esa misma automatización no lleva los cambios hasta la producción. Para cubrir ese último paso, un humano todavía tiene que pulsar un botón en la herramienta de canalización para desplegar la versión candidata(Figura 1-5). La presencia de ese "botón" manual es el principal diferenciador entre la entrega continua y la implementación continua.

Figura 1-5. La puerta final a la producción

Incluso con una puerta manual final, se agilizan muchas más fases del camino a la producción: las implementaciones a preproducción y las pruebas a niveles superiores de abstracción pueden ejecutarse para cada incremento de código en lugar de para semanas de cambios acumulados. El 99% del camino a la producción está completamente automatizado. Es casi perfecto.

Sin embargo, esta implementación de la entrega continua sigue teniendo un cuello de botella en el proceso global de poner el código a disposición de los usuarios: la aprobación manual del último humano para realizar esa implementación final. Este 1% puede parecer insignificante, pero marca la diferencia.

Los equipos pueden gestionar las Implementaciones de producción de diferentes maneras, desde implementaciones ad hoc cuando hay suficientes cambios sustanciales, hasta sofisticados calendarios en los que las implementaciones se producen con una cadencia fija. Sin embargo, en el momento en que se produce la intervención manual, es posible que se haya acumulado un lote de confirmaciones en preproducción, y normalmente se desplegarán todas a la vez, lo que aumenta el riesgo de despliegue, retrasa la retroalimentación y ralentiza la depuración si (cuando) algo va mal.

Cuanto mayor es la implementación, más supervisión se requiere, y más defectos potenciales acechan en el creciente número de líneas de código que esperan a ser desplegadas. Además, cuantos más cambios se hagan a la vez, más código tendremos que revisar para diagnosticar la causa de los problemas posteriores a la implementación.

Si el proceso de implementación en producción requiere una verificación manual prolongada (por ejemplo, pruebas manuales exhaustivas en la fase de ensayo o UAT), no se trata realmente de un proceso continuo, por lo que ni siquiera podría calificarse estrictamente de entrega continua. La intervención manual retrasa aún más el punto de lanzamiento y agrava este problema, haciendo que cada implementación sea mayor y más compleja.

Además, al igual que ocurre con TBD frente a las ramas, un entorno de producción cerrado dificulta hacer lo correcto (desplegar lo más a menudo posible) y facilita hacer lo incorrecto (añadir "una confirmación más" antes de la implementación).

Aunque la mayoría de las empresas están disfrutando de grandes beneficios gracias a la entrega continua, todavía no están implementando en producción con la frecuencia que podrían; es decir, con la granularidad de cada commit.11

Un paso más allá: Implementación Continua

Ahora que en hemos aprendido los principios de XP, DevOps, CI y CD, por fin podemos entender el pensamiento que hay detrás de la implementación continua.

Un par de décadas después de que empezara a cambiar el discurso sobre el camino a la producción, apareció el programa de investigación DORA State of DevOps, dirigido por Nicole Forsgren, para validar los instintos anteriores de XP sobre la realización frecuente de las partes más dolorosas del software.12 Este programa es la investigación académica más larga sobre prácticas de entrega de software hasta la fecha. A lo largo de seis años de investigación, ha confirmado que un plazo más corto para los cambios y una mayor frecuencia de las Implementaciones de producción son predictores fiables de un alto rendimiento en los equipos de desarrollo de software (y en sus organizaciones). También merece la pena mencionar, desde un punto de vista egoísta, que la investigación DORA ha encontrado una fuerte correlación entre esas métricas y una mejor calidad de vida para los ingenieros, con una mayor satisfacción general en el trabajo y menos agotamiento. Estos resultados se aplican tanto a las organizaciones comerciales como a las no comerciales.

Animados por las conclusiones del DORA, los equipos que ya siguen los valores de XP, DevOps, CI y CD intentan ahora que sus Implementaciones se produzcan cada vez con más frecuencia y con menos control. Las prácticas de ingeniería que permiten la implementación en producción con la mayor frecuencia posible se han convertido en un objetivo clave de las organizaciones que buscan reducir su tiempo de comercialización y su capacidad de respuesta al cambio.

Por tanto, es natural que algunos equipos estén pensando en ir un paso más allá con la entrega continua y eliminar la última barrera manual a la producción: automatizar el último paso de su canalización automatizada y, por tanto, permitir la implementación continua (mostrada en la Figura 1-6).

Figura 1-6. El proceso automatizado de implementación continua

El término implementación continua fue acuñado por Timothy Fitz en su artículo de 2009 del mismo nombre. El concepto no se ha incluido en mucha literatura desde entonces, pero ha ganado tracción y ha sido adoptado con éxito por empresas como Facebook, Google y muchas más. Como la implementación continua sigue estando relativamente poco documentada, no hay datos oficiales que muestren exactamente cuántas empresas la han adoptado en general (la mayoría de los estudios se centran más en general en la entrega continua, no específicamente en la implementación continua). Por eso he recopilado varios casos prácticos en este libro: para que puedas hacerte una idea de cómo una buena muestra de empresas lo hacen funcionar en su día a día en todo tipo de sectores: desde el comercio minorista a la banca, pasando por la automoción y muchos más.

El despliegue continuo puede entenderse como una implementación específica de la entrega continua, que actúa dentro de su marco de garantizar que cada incremento de código esté listo para la producción. De hecho, la implementación continua toma el principio de "listo para producción" de forma bastante literal. Su característica definitoria es que la decisión de implementar el código en producción está totalmente automatizada por la canalización, sin necesidad de intervención manual.

Cada confirmación que pase por la canalización no sólo se considerará desplegable en producción, sino que realmente se desplegará en producción.

Esto significa que se acabaron las esperas en un entorno UAT o staging para realizar pruebas exploratorias manuales, y la intervención humana para decidir si se envían los cambios en directo. El canal lo hace todo, y los humanos pueden por fin sentarse y ver cómo la automatización hace su trabajo hasta el final.

Ya hemos hablado de cómo el principio "Si duele, hazlo más a menudo" de XP se refleja en las prácticas de DevOps, IC y DC. Todos estos años después, considero que el mismo principio es también la principal motivación para adoptar la implementación continua en producción. Quizá la implementación continua sea la práctica que lleva este concepto hasta sus últimas consecuencias.

¿Qué ha sido más doloroso para cualquier equipo de software que la implementación en producción? La integración con las versiones activas de servicios de terceros, las condiciones de alto tráfico, los comportamientos imprevistos de los usuarios y los datos reales generados por los usuarios han causado históricamente estragos incluso en los planes de lanzamiento mejor trazados. Y las consecuencias han sido mucho peores que un mal día de fusión o una demo decepcionante. Los usuarios reales se han encontrado con aplicaciones rotas, funciones inutilizables e incluso la pérdida de sus datos. La implementación en producción ha provocado interrupciones de la actividad que han durado horas o días para innumerables equipos. Como veremos en capítulos posteriores, el entorno de producción está lleno de peculiaridades que son difíciles o imposibles de reproducir en los portátiles de los desarrolladores. Incluso las configuraciones de preproducción más sofisticadas y elegantes no suelen ser lo bastante parecidas a las de producción como para detectar todas esas peculiaridades.

La implementación en producción es una prueba terrible, y cuando sale mal puede decepcionar a mucha gente. Me cuesta pensar en algo más doloroso para un equipo de software que la implementación en producción después de días o semanas de duro trabajo, sólo para darse cuenta de que su código tenía un defecto imprevisto que ahora se exhibe ante los usuarios y las partes interesadas. La mayoría de los desarrolladores experimentados saben lo mortificante que puede ser eso. O peor aún, pueden conocer la decepción de trabajar largas horas para conseguir que la Gran Nueva Característica supere la línea de meta, sólo para descubrir que los usuarios la ignoran alegremente.

Definitivamente, la implementación en producción puede hacer daño. Por lo tanto (al más puro estilo XP), deberíamos hacerlo tan a menudo como sea posible; idealmente, en cada commit que nuestras mejores pruebas automatizadas demuestren que merece la pena. Sólo entonces será posible aliviar ese dolor y tener ganas de realizar la implementación varias veces al día, en lugar de temerla una vez al mes. Eso es la implementación continua y, en pocas palabras, de eso trata este libro.

Desde mi punto de vista , la implementación continua representa la culminación del viaje de décadas de automatización que he descrito en este capítulo. Con ella, la automatización puede cubrir por fin todo el camino hacia la producción de extremo a extremo y no dejar ningún trabajo manual en el flujo de valor del software.

Con las Implementaciones inmediatas, el ciclo de vida de la confirmación de código coincide con el ciclo de vida de la implementación. Cada incremento de código en la base de código corresponde a un incremento de código casi inmediato en producción, por lo que cada confirmación debe estar lista para producción desde su inicio. Los desarrolladores trabajan dentro del bucle de retroalimentación más estrecho posible cada día, e incluso cada hora.

De hecho, cada desarrollador puede supervisar fácilmente varias Implementaciones de producción mientras crea código para una sola tarea. Esto hace que estén íntimamente familiarizados con el entorno de producción y todas sus peculiaridades, interdependencias y limitaciones de rendimiento. La implementación continua capacita plenamente a los desarrolladores para responsabilizarse tanto del valor como del potencial destructivo de sus cambios. En general, este marco promueve la producción a un ciudadano de primera clase en el esfuerzo cognitivo diario de escribir código. Ya debería serlo, pero es fácil olvidarse de ello cuando las Implementaciones ocurren "algún tiempo después" o son supervisadas por otra persona.

Con una correspondencia 1:1 entre commits e implementaciones, el estado de la base de código y su relación con el estado de producción se vuelven sencillos: siempre son uno y el mismo. No hay necesidad de cambiar a una versión anterior del código para depurar problemas en vivo, ni de preguntarse qué versión está en producción en ese momento, ni de revertir los cambios no desplegados si hay que apresurarse a realizar una corrección urgente. El más pequeño de los experimentos puede (y debe) ponerse en marcha en un tiempo trivial: lo ideal es medirlo en minutos, ya sea una nueva línea de registro para depurar o cambiar el color de un botón de una función.

En general, trabajar de este modo reduce el riesgo de imprevisibilidad de la producción gestionándolo en los incrementos más pequeños posibles: dentro de la granularidad de cada confirmación.

Aplicación

La propia implementación de la entrega continua en puede ser bastante sencilla. Adaptar una canalización de entrega continua existente para que admita la implementación continua normalmente sólo requiere una reconfiguración del paso de implementación en producción.

Si tu software respeta todas las condiciones siguientes:

  • Está controlado por versiones.

  • Tiene cobertura de pruebas automatizada.

  • Tiene un proceso automatizado.

  • El pipeline automatizado se ejecuta en cada nueva confirmación en trunk (la rama principal).

  • La canalización automatizada es responsable de todo el camino hasta la producción, desde el commit, pasando por las pruebas, hasta la implementación en cualquier entorno (incluido el de producción).

  • La versión "troncal" del software se implementa en tus principales entornos de preproducción y, por supuesto, en producción.

  • El proceso automatizado se ejecuta en un tiempo razonable (digamos que todos los pasos combinados deberían llevar menos de una hora, descontando las pausas para las comprobaciones manuales).

Una vez satisfechas estas condiciones, todo lo que tienes que hacer es asegurarte de lo siguiente: una vez que se ha enviado (o fusionado) un commit al tronco y se han pasado todas las puertas de calidad, la implementación en producción se produce inmediatamente. No debe haber pasos manuales, ni botones esperando a ser pulsados por una forma de vida basada en el carbono. Si ya has adoptado la entrega continua, esto suele significar eliminar una instrucción de "pausa" antes de la implementación en producción en la herramienta de canalización que hayas elegido.

Si hay otros aprobadores de cambios necesarios, o alguna puerta manual anterior entre un push y una implementación en producción, también deben automatizarse. Cuando cualquier evento de inserción o fusión en la rama principal sea capaz de activar su propia implementación en producción, sabrás que has terminado.

¿Cómo sabes cuándo tus puertas automatizadas de calidad y tu infraestructura son lo bastante buenas como para hacer este cambio? Si buscas una indicación de cuándo puedes estar "preparado", quizá te guste leer el Capítulo 3.

Y eso es todo. No habrá más detalles de implementación de canalizaciones en este libro, porque esto es realmente todo lo que hay que hacer para "implementar" la implementación continua.

Una canalización de implementación continua no es ciertamente laboriosa de construir. Para pasar de la entrega continua a la implementación continua, los desarrolladores muy veteranos no tienen que pasarse semanas codificando complicados scripts llenos de pasos de implementación, configuración de permisos en la nube, infraestructura como código y elaboradas configuraciones de pruebas. En la mayoría de los casos, todo lo que tienen que hacer es eliminar un paso de su pipeline existente. Implementar la entrega continua desde cero puede llevar meses o años, mientras que cambiar a la implementación continua a menudo sólo requiere un cambio de una línea. Como la mayoría de los equipos de hoy en día ya han invertido en un proceso de entrega continua, parece que el cambio no será tan difícil para la mayoría de las empresas.

Entonces, ¿de qué vamos a hablar en el resto de el libro?

Implicaciones

Implementación continua podría descartarse como una subcategoría trivial dentro de la entrega continua, pero esto subestima la simplicidad radical de una canalización automatizada que va directamente del push a la producción.

Los retos de la implementación continua no residen en su implementación engañosamente sencilla. Más bien residen en la adopción de todas las prácticas de las que depende y las que desbloquea. Puede que sea un cambio de una sola línea, pero es un cambio de una sola línea que (según mi experiencia) representa una completa reimaginación del proceso cotidiano de desarrollo de software.

Por ejemplo, éstas son sólo algunas de las cuestiones que abordaremos en el resto de este libro, y que surgieron para mis equipos sólo después del cambio a la implementación continua:

  • ¿Cómo ocultamos el código inacabado si estamos implementando cada confirmación?

  • ¿Cómo nos aseguramos de que todas las confirmaciones son compatibles con versiones anteriores?

  • ¿Cómo evitamos romper los contratos con otros servicios de producción?

  • ¿Cómo separamos una Implementación de una publicación de funciones?

  • ¿Cuál es el efecto de las Implementaciones muy frecuentes sobre la estabilidad de la infraestructura?

  • ¿Cómo cambia esto la forma de trabajar del equipo y su definición de "hecho"?

  • ¿Qué ocurre con los entornos de preproducción?

  • ¿Ya no hay nada "hecho en desarrollo" si todo está en producción?

  • ¿Cómo pueden seguir haciéndose pruebas exploratorias manuales cuando las Implementaciones son inmediatas?

Un flujo de trabajo de implementación continua es radicalmente distinto de un flujo de trabajo tradicional de entrega continua con una puerta a la producción. Así que, como ya hemos hablado de cómo "implementar" el despliegue continuo, el resto de este libro cubrirá sus ramificaciones y la implementación de todas sus prácticas de apoyo.

¿Es peligroso?

Si tu corazón de ha dado un vuelco al leer que se han eliminado las aprobaciones manuales de producción, no te preocupes. No estás ni mucho menos solo.

Cuando los equipos practican una buena integración continua y utilizan ramas de características de corta duración o, mejor aún, un desarrollo basado en el tronco, envían múltiples cambios a través del pipeline cada día. Algunos equipos pueden incluso enviar múltiples cambios cada hora, todos los cuales acabarán en producción uno tras otro. Esto agiliza considerablemente el flujo de trabajo de los ingenieros, pero también es una responsabilidad que no debe tomarse a la ligera.

Cada commit que acaba en producción requiere que los desarrolladores sean extremadamente disciplinados con todos los principios introducidos por la entrega continua. El pipeline, los entornos de preproducción y las pruebas automatizadas deben mantenerse en una forma impecable para que puedan descartar con precisión los conjuntos de cambios erróneos. Para los desarrolladores, también es obligatorio tratar cada incremento de código como un posible candidato a la implementación. Al fin y al cabo, cada commit se convertirá en una implementación real: ya no son sólo "candidatos".

De hecho, se podría argumentar que la preparación para la producción que ofrece la entrega continua es sólo teórica sin la implementación continua.

Pero por muy guay y brillante que sea esta práctica, presenta algunos riesgos: como cada cambio que hacen los desarrolladores pasa inmediatamente a producción, tiene el potencial de afectar a una compleja red de servicios. Mucho ha cambiado desde los primeros días de XP y del "todo continuo": las organizaciones se han alejado de las "simples" aplicaciones monolíticas y han adoptado arquitecturas distribuidas y orientadas a los servicios. Estos servicios dependen unos de otros de formas a menudo intrincadas, y las interdependencias en los sistemas distribuidos son de las cosas más difíciles de probar. Si la implementación continua no se hace con cuidado y responsabilidad, una confirmación mal pensada puede echar abajo la producción.

Las prácticas de entrega continua son una base necesaria, pero se necesitan algunas precauciones más para realizar una implementación continua segura en producción, que ya he insinuado en "Implicaciones". Es necesario establecer redes de seguridad adicionales para garantizar el menor riesgo posible de regresiones, que han surgido en los años transcurridos desde que se popularizó la entrega continua. Hay que reestructurar las puertas de calidad en torno a la novedosa proximidad del entorno de producción, y ajustar las formas de trabajar del equipo para tener en cuenta las Implementaciones inmediatas.

Sin embargo, hacer una implementación continua de forma responsable es posible. Sí, incluso cuando no todos los miembros del equipo son senior. Los equipos lo hacen todos los días y disfrutan de grandes beneficios y de una retroalimentación increíblemente rápida gracias a ello. En este libro, descubrirás cuáles son esos beneficios y cómo lo hacen. Aprenderás un marco para realizar lanzamientos incrementales seguros durante el trabajo diario de desarrollo, que está estructurado exclusivamente en torno a los retos de la implementación continua en sistemas distribuidos no triviales, .

Resumen

En este capítulo, presentamos la implementación continua: la metodología en la que se centrará este libro. En la implementación continua, todo el camino hasta la producción del código está totalmente automatizado, incluso la decisión final de implementar en producción.

A continuación, recapitulamos las prácticas que se han centrado en el camino del código hacia la producción en los últimos años: empezando por el lema de XP "Si duele, hazlo más a menudo", pasando por DevOps derribando la barrera entre desarrollo y operaciones, hasta la integración continua introduciendo la automatización hasta la construcción de un artefacto, la entrega continua extendiéndola a las pruebas y las implementaciones de alto nivel y, por último, la implementación continua eliminando todos los factores humanos de la canalización automatizada.

Hablamos de cómo la Implementación continua tiene profundas ramificaciones en el flujo de trabajo de los ingenieros, que debe adaptarse para tener en cuenta las continuas Implementaciones de producción. Hablamos de cómo esto da lugar a una retroalimentación más granular y a una mayor responsabilidad a la hora de implantar robustas puertas de calidad. Los commits y las implementaciones deben planificarse cuidadosamente para mantener la producción en un estado de funcionamiento y rendimiento.

En el próximo capítulo veremos qué hace que esta inversión merezca la pena.

1 Paul M. Duvall, Integración continua: Improving Software Quality and Reducing Risk (Boston: Addison-Wesley, 2007). Jez Humble y David Farley, Entrega continua: Reliable Software Releases through Build, Test, and Implementación Automation (Boston: Addison-Wesley, 2010). Kent Beck, Programación Extrema Explicada: Embrace Change (Boston: Addison-Wesley, 2004). Gene Kim y otros, El Manual DevOps: How to Create World-Class Agility, Reliability, & Security in Technology Organizations (Portland, OR: IT Revolution Press, 2016).

2 Consulta https://oreil.ly/ZJS1G para leer íntegramente el informe DORA "Accelerate State of DevOps Report 2023".

3 El último momento responsable (LRM) es la estrategia de retrasar una decisión hasta el momento en que el coste de no tomar la decisión sea mayor que el coste de tomarla, como explican Mary y Tom Poppendieck en su libro Lean Software Development: An Agile Toolkit (Addison-Wesley, 2003). Esta estrategia te ayuda a tomar decisiones sólo cuando dispongas de la máxima cantidad de información.

4 Beck, Extreme Programming Explained, p. 127.

5 Steve Mezak, "El origen de DevOps: ¿Qué hay en un nombre?", DevOps.com, https://oreil.ly/TCzso.

6 Gene Kim y otros, El Proyecto Phoenix: A Novel About IT, DevOps, and Helping Your Business Win (Portland, OR: IT Revolution Press, 2014).

7 Kim et al., El Manual DevOps.

8 Kim et al., El Manual DevOps, Introducción.

9 La difusión semántica es el fenómeno en el que un término se acuña con una definición muy específica, pero luego se difunde por la comunidad en general de forma que debilita esa definición.

10 Martin Fowler escribe sobre integración continua en https://oreil.ly/SqElv.

11 Los aficionados a la fabricación ajustada conocerán esto como "flujo de una pieza". Consulta el Capítulo 2 para más detalles.

12 Puedes descargar el Informe DORA "Acelerar el Estado de DevOps 2023" en https://oreil.ly/epiI8.

Get Despliegue continuo now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.