Cómo mejoramos nuestro desarrollo de software con CI/CD 🚀

En el departamento de Innovación y Desarrollo siempre estamos buscando maneras de trabajar mejor y entregar software de mayor calidad. Uno de los pilares para lograrlo ha sido la implementación de integración continua (CI) y entrega continua (CD) en nuestros proyectos internos. Hace un tiempo nos enfrentábamos a un problema muy común:

  • Al integrar cambios de varios desarrolladores, era frecuente tener conflictos.

  • En ocasiones se llegaba a subir código con errores que rompían el proyecto.

  • A veces se subía directo a la rama de producción y hasta olvidábamos cambiar el número de versión.

  • Cada persona creaba su propia rama, lo que hacía difícil colaborar en una misma funcionalidad.

  • Teníamos un único repositorio con varios proyectos que no necesariamente eran dependientes, lo cual complicaba su manejo.

  • Cada despliegue era un dolor de cabeza, porque había que hacerlo de forma manual.

En pocas palabras: teníamos desorden, perdíamos tiempo y la confianza en el código era baja.

El cambio: CI/CD ✅

Para solucionar esto decidimos implementar integración y entrega continua (CI/CD). Esto nos dio una forma clara y automatizada de trabajar, que nos ayuda a:

  • Detectar errores en cuanto aparecen.

  • Validar que solo se pueda integrar de desarrollo a producción, y únicamente si el código fue aprobado y compila sin errores.

  • Evitar que algo se suba directo a producción sin pasar por revisiones.

  • Tener compilaciones y pruebas automáticas.

  • Empaquetar y desplegar sin complicaciones.

  • Medir la calidad del código de manera constante.

Nuestra forma de hacerlo 🔧

Usamos Azure DevOps Server, que tenemos instalado en un servidor local. Allí corren nuestros pipelines apoyados en varios agentes autohospedados con Docker, montados sobre Windows Server Core y listos con .NET y todo lo que necesitamos para compilar y ejecutar proyectos.

En cuanto al control de versiones, seguimos una variante de Git Flow adaptada a nuestras necesidades:

  • Una rama de producción y una de desarrollo que siempre están vivas.

  • Ramas temporales creadas por funcionalidad, en lugar de por persona.

    • Son ramas de corta vida, pensadas para integrarse rápido.

    • Solo se puede integrar de devmaster.
    • Permiten que varias personas trabajen en la misma funcionalidad y colaboren mejor.

    • El código debe compilar correctamente y pasar los pipelines.

  • Todos los cambios entran a través de pull requests, con al menos dos revisores obligatorios.

Esto redujo los conflictos y permitió que varias personas colaboren en la misma funcionalidad, con ramas de corta vida y rápida integración.

Además, evolucionamos nuestra organización:

  • Separamos los proyectos en repositorios individuales, en lugar de tenerlos todos juntos.

  • Cada repositorio ahora tiene su propio pipeline y configuración específica.

  • Incorporamos un README como documentación en cada proyecto, pensado para que futuras personas que den mantenimiento encuentren ahí la guía básica.

Boards: planificación y trazabilidad

Usamos la parte de Boards en DevOps para organizar el trabajo:

  • Cada tarea se registra como un Work Item (WI), descrito como Historia de Usuario.

  • Se asigna un tiempo estimado y un responsable.

  • Desde el WI se pueden crear ramas vinculadas y asociar Pull Requests relacionados.

De esta forma, tenemos trazabilidad completa entre lo planificado, el código escrito y el despliegue final.

Qué hacen nuestros pipelines

La mayoría de nuestros pipelines siguen un esquema bastante estándar:

  1. Compilan el proyecto.

  2. Ejecutan pruebas automáticas, generando reportes (trx y coverage) que quedan visibles en la canalización.

  3. En muchos repositorios, empaquetan el proyecto y lo publican en nuestro feed interno de Azure Artifacts como paquete NuGet.

  4. En algunos casos, también enviamos el código a SonarQube, que nos da métricas de calidad, seguridad y complejidad cognitiva, ayudándonos a entender qué tan sencillo o difícil es mantener el código a largo plazo.

  5. Fase de despliegue (en algunos repos), que empaqueta y publica en un feed interno de Artifacts (NuGet).

Además, tenemos un repositorio central con plantillas YAML que usamos para armar pipelines de manera más rápida y uniforme.

El resultado

Hoy en día, gracias a CI/CD, dejamos atrás el caos de las integraciones, los errores en producción y hasta los olvidos de versión. Ahora:

  • Cada proyecto tiene su propio repositorio y documentación.

  • Los cambios entran de forma ordenada y revisada.

  • El proceso está automatizado y medido con métricas claras.

  • Contamos con reportes de calidad y complejidad que nos permiten mejorar continuamente.

👉En resumen: pasamos del desorden a un proceso ordenado, automatizado y mucho más ágil.