DevOps y las metodologías Ágiles han transformado el desarrollo de software enfatizando la colaboración, automatización y mejora continua. Aplicar los principios de DevOps a mis diseños y proyectos ha sido un cambio radical, mejorando la eficiencia y fiabilidad. En este artículo, vamos a guiarlos en la configuración de un flujo de trabajo de integración continua (CI) para un proyecto de sistemas embebidos existente que utiliza el microcontrolador ATmega328P. Al final de este artículo, verás cómo estas prácticas pueden agilizar tu proceso de desarrollo y entregar productos de mayor calidad.
DevOps es un conjunto de prácticas, popularizadas por el mundo del software, que une el desarrollo de software (Dev) y las operaciones de TI (Ops) en un flujo continuo. En el mundo del software, solía ser común desarrollar software y “lanzarlo por encima del muro” a los equipos de operaciones para su despliegue a los clientes. DevOps introdujo una manera de no solo derribar ese muro, sino de automatizar todo el proceso de principio a fin. En el mundo del hardware encontramos similitudes entre el desarrollo de productos y la producción, lanzando constantemente el diseño “por encima del muro” a nuestros equipos de ingeniería de manufactura para asegurar que todo esté listo para la producción.
En el diseño de productos embebidos todavía tenemos que llevar nuestro software a través de la producción, pero enfrentamos el desafío de movernos más rápido que nunca y entregar con la máxima calidad posible. Con los principios de DevOps buscamos resolver algunos de esos desafíos.
Al aplicar los principios de DevOps, somos capaces de iterar rápidamente utilizando metodologías Ágiles dentro del paradigma de construir-probar-desplegar para cada característica adicional que deseamos lanzar a producción.
"Construir, probar y desplegar" es un conjunto común de palabras que a menudo escucharás cuando se habla de DevOps. En los sistemas embebidos hacemos lo mismo ya que nuestro despliegue también va a producción (y luego al cliente final). En el repositorio del proyecto estamos utilizando Gitlab CI para impulsar nuestro flujo de trabajo de principio a fin para Embedded DevOps. Utilizamos lo que se llama "pipelines" para crear trabajos que logren ciertas tareas como compilar el software, ejecutar pruebas en el objetivo o liberarlo como un paquete oficial. En Gitlab, un pipeline es una colección de trabajos que se ejecutan en un flujo secuencial como este:
Figura 1: Ejemplo de pipeline utilizado con el flujo de trabajo de DevOps de ATmega328P en Gitlab
Aquí hay un desglose del script CI (.gitlab-ci.yml) para darte una idea de cómo funciona esto.
Hay algunos detalles menores que convierten este flujo de trabajo de una implementación básica de DevOps en un sistema que funciona de manera fluida, bien documentada y fácilmente observable. Hay algunos detalles sutiles dentro del flujo de trabajo de CI que es importante señalar.
if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then
export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:latest
else
export IMAGE_TAG=$CI_REGISTRY_IMAGE/$IMAGE_TYPE:$CI_COMMIT_REF_SLUG
fi
Esta lógica prepara el escenario para que nuestra etiqueta “latest” solo use la imagen Docker construida en la rama principal (es decir, después de que una solicitud de fusión se aprueba con éxito). Esto asegura que solo las solicitudes de fusión exitosas publiquen la imagen docker más reciente y mejor que todos y cada uno de los pipelines extraen.Informes y Cobertura: En sistemas CI modernos como Gitlab, podemos extraer y mostrar informes de pruebas y cobertura dentro de nuestras solicitudes de fusión y pipelines. Por ejemplo, en esta solicitud de fusión hemos capturado la cobertura de código:
Figura 2: Cobertura de código dentro de una solicitud de fusión
En esta captura de pantalla, Gitlab resume las pruebas realizadas en el objetivo usando hardware en el bucle:
Figura 3: Resumen de pruebas para las pruebas realizadas en el objetivo
Al final, una vez que nuestro código ha sido validado tanto con pruebas unitarias como en el objetivo, las etapas de publicación y lanzamiento generan un paquete atractivo que puede ser consumido por el equipo de producción:
Figura 4: Lanzamiento del paquete de software
Con todos estos pasos automatizados podemos lanzar una nueva característica de manera iterativa en un modo Ágil. No hay necesidad de desarrollar muchas características, enviarlas al departamento de QA y luego una revisión para el lanzamiento del paquete por el equipo de producción. Todo aquí ocurre en un único flujo de trabajo y está completamente automatizado.
En este artículo, exploramos cómo se pueden aplicar las metodologías DevOps y Agile al desarrollo de sistemas embebidos, específicamente utilizando el microcontrolador ATmega328P. Discutimos los beneficios de implementar un flujo de trabajo CI en Gitlab, que incluye automatización, tiempos de construcción más rápidos y pruebas eficientes. Al desglosar el script CI y explicar cada etapa, mostramos cómo crear un proceso de desarrollo robusto y optimizado que aumenta la eficiencia y la calidad del producto. Siguiendo esta guía práctica (y el código fuente dentro del repositorio) también deberías poder configurar tu propio flujo de trabajo Embedded DevOps.
El código fuente del proyecto se puede encontrar aquí:https://gitlab.com/embedded-designs/atmega328p-serial-led-control.