CI/CD es un dogma de desarrollo de software bien establecido. Internet está lleno de artículos y páginas que hablan sobre CI/CD. Siempre tienen la misma imagen CI/CD . Apuesto a que conoces la imagen de la que estoy hablando.
Leí docenas de artículos sobre el tema y experimenté la implementación de un proceso de CI/CD de extremo a extremo. La realidad es que implementar un proceso de CI/CD es mucho más complejo que leer artículos, comprender el panorama general de CI/CD y utilizar la teoría. El desarrollo de un proceso de CI/CD requiere equipos interdisciplinarios y experimentados.
Este artículo explica cómo construir una canalización de CI mínima viable de una aplicación Python. Puede adaptar el contenido del artículo a otros idiomas y requisitos. El ejemplo utiliza FastAPI y GitHub Actions.
Ejemplo de GitHub:
CI: integración continua
Permítanme agregar mi granito de arena a las descripciones de integración continua existentes. La integración continua significa fusionar periódicamente cambios de código probados, aprobados y entregables automáticamente en el repositorio del proyecto.
Este ejemplo utiliza para ejecutar automáticamente las comprobaciones requeridas en cada evento 'Pull Request' o 'Push to Main' para garantizar que el código cumpla con los estándares de calidad del repositorio. El mercado ofrece una colección diversa de herramientas CI/CD: , , , GitLab, etc. Elija la que mejor se adapte a los requisitos de su canalización.
El flujo de trabajo de ejemplo comprueba que el nuevo código siga las reglas de formato que se ejecutan . Luego ejecuta las pruebas pequeñas usando y, finalmente, las medianas instalando la aplicación en un cluster D.
Su flujo de trabajo de integración continua dependerá del tamaño de su equipo, la madurez, los requisitos de la aplicación y la estrategia de ramificación.
Análisis de código estático
Analizar los cambios de código sin ejecutarlos. Las herramientas de análisis estático verifican que su código cumpla con las reglas de formato, no utilice dependencias obsoletas o corruptas y sea legible y lo suficientemente simple. También sugieren codificar antipatrones y errores según el lenguaje de programación.
Explicaremos cómo instalar, configurar y ejecutar Pre-commit. Puede combinar el compromiso previo con otras herramientas de análisis como o .
Pre cometido
es una herramienta escrita en Python. Configurarlo en su repositorio es tan simple como crear un archivo YAML y agregar los enlaces versionados que desea ejecutar antes de cada confirmación. La confirmación previa gestiona automáticamente las dependencias requeridas por los enlaces y corrige automáticamente los errores encontrados. Admite múltiples tipos de archivos: JSON, YAML, tf, py, ts, etc.
Ahorre costos de infraestructura ejecutando localmente sus comprobaciones de código antes de enviarlas. Puede ejecutar la confirmación previa en su CI para verificar el formato del código enviado.
Instale, configure y ejecute la herramienta de confirmación previa:
repos: - repo: //github.com/pre-commit/pre-commit-hooks rev: v2.3.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace
$ pip install pre-commit $ pre-commit install $ pre-commit run --all-files
Sugerencias de gancho de Python:
- Mypy: Comprobador de tipos estáticos para Python
- Ruff: Comprobador de formato estático para Python
- Renovar: sugerir mejores prácticas de codificación para Python
- Compromiso: Garantizar el uso de compromisos estándar y la gestión de versiones.
Prueba
Las definiciones y el alcance de las pruebas unitarias, de integración y de extremo a extremo a veces son difusos. Como hice con la descripción de Integración continua, agregaré mi granito de arena a los tipos de prueba :
Pequeño : Pruebas rápidas. Pruebe pequeños fragmentos de código. Utilice dobles de prueba o entornos simulados (por ejemplo, SQLite). No es necesario construir ningún artefacto. Tiempo: ~ 60 segundos.
Medio : prueba la interacción entre múltiples fragmentos de código. Pueden incluir la creación de artefactos, el uso de artefactos de terceros (por ejemplo, base de datos ) y la conexión a la red localhost. Uso de entornos falsos (por ejemplo, docker-compose, Kind, Minikube, etc.) o servicios externos (por ejemplo, Azure Blob Storage o AWS S3). Tiempo: ~ 300 segundos.
Grande : utilizan entornos similares a los de producción (por ejemplo, pruebas de rendimiento). Tiempo: + 900 segundos.
Tener o no pruebas medianas/grandes en su canal de integraciones continuas depende de sus requisitos.
Pequeño
El ejemplo utiliza Pytest para ejecutar las pruebas y el cliente de pruebas FastAPI para simular el entorno. Sin secretos; su herramienta de prueba de lenguajes de programación debe proporcionarle todas las dependencias necesarias para probar su aplicación.
Además, puede agregar una verificación de cobertura mínima de la prueba y cargarla como parte de sus resultados. La cobertura de la prueba es una métrica complicada. Una alta cobertura de pruebas no significa implícitamente tener un código bien probado, pero un 50% es más que un 0% de código probado.
Medio
D es un clúster de Kubernetes ligero acoplable en acoplable que se utiliza para desarrollo local o CI. Usamos Kind para configurar un entorno de prueba y ejecutar las pruebas en él:
- Crear el grupo Kind
- Construya la imagen de Docker
- Cargue la imagen de Docker en tipo
- Instale MetalLB y aplique los CDR necesarios
- Instalar Ingress-Nginx
- Instale su tabla de timón
- Configure el host de su sistema operativo
Cargar imágenes de Docker
Kind no podrá descargar su imagen porque no se puede descargar desde un registro. Kind requiere que la imagen se cargue antes de usarla.
MetalLB
es un equilibrador de carga de Kubernetes sin sistema operativo. Lea más sobre por qué se requiere un equilibrador de carga en la página web .
Una vez instalado usando Helm Chart, podemos crear los CRD necesarios:
--- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind-advertisement --- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: kind-address-pool spec: addresses: - "172.26.255.0/24"
Docker crea una subred para el clúster Kind (por ejemplo, 172.26.0.0/16). Inspeccione la interfaz de red Kind para conocer el rango de direcciones IP asignadas y use la dirección como valor para el recurso IPAddressPool. Más información sobre la configuración de MetalLB está en la página web .
Exponer la aplicación
Instale el gráfico de timón Ingress-Nginx. Luego, instale su aplicación Helm Chart, definiendo un objeto Ingress. Establezca la propiedad ingressClassName en nginx y defina un host (por ejemplo, api.local). Finalmente, modifique /etc/host para agregar la siguiente línea:
192.168.1.10 api.local
Puedes definir tantos hosts como quieras, apuntando a la misma dirección. Nginx hará el resto.
Desarrolle una herramienta para iniciar, actualizar y eliminar un entorno local utilizando Kind. Los desarrolladores pueden usarlo para depurar fácilmente la aplicación, reproducir localmente los errores reportados o ejecutar la prueba en CI.
Este ejemplo funciona para distribuciones basadas en Linux. Para Windows/MacOS, es posible que no funcione tal como está, es posible que se requieran cambios.
Entrega
Antes de entregar los artefactos necesarios, el flujo de trabajo ejecuta los pasos de prueba y linting.
Usamos para gestionar los lanzamientos de los artefactos. Commtizen actualiza automáticamente la versión del artefacto e impulsa los cambios. Crea una nueva etiqueta git con el formato de etiqueta configurado. También puede configurar Commtizen para actualizar su registro de cambios con los últimos cambios.
[tool.commitizen] tag_format = "v$major.$minor.$patch" version_scheme = "semver" version_provider = "pep621" major_version_zero = true update_changelog_on_bump = true version_files = [ "charts/ci-example/Chart.yaml:version", "charts/ci-example/Chart.yaml:appVersion" ]
El flujo de trabajo utiliza la versión de salida de Commitizen para configurar la imagen de Docker y la etiqueta Helm Chart.
Puede tener diferentes versiones para cada artefacto (Imagen y Gráfico). Pero entonces los cambios de gráficos e imágenes deben ser compatibles con versiones anteriores. Agregará complejidad al proceso de desarrollo y lanzamiento. Para evitarlo, utilizamos la misma versión para ambos artefactos.
Conclusiones
Este artículo esboza un flujo de trabajo de integración continua simple pero funcional. Es posible que necesite cambios para que funcione con otros lenguajes de programación o se ajuste a sus requisitos, pero algunos pasos deberían ser fácilmente exportables y funcionar tal como están.
Práctica de CI/CD: Implementación continua [Parte 2] Próximamente...