Nota perev. : El artículo original fue escrito por Miłosz Smółka, uno de los fundadores de la pequeña empresa polaca Three Dots Labs , especializada en "soluciones avanzadas de backend". El autor se basa en su experiencia en el uso activo de GitLab CI y comparte los consejos acumulados para otros usuarios de este producto Open Source. Después de leerlos, nos dimos cuenta de lo cerca que están los problemas descritos por él, así que decidimos compartir las soluciones propuestas con un público más amplio.
Esta vez trataré temas más avanzados en GitLab CI. Una tarea común aquí es implementar características no estándar en la tubería. La mayoría de los consejos son específicos de GitLab, aunque algunos de ellos se pueden aplicar a otros sistemas de CI.
Ejecute pruebas de integración
Como regla general, la verificación de código mediante
pruebas unitarias es fácil de conectar a cualquier sistema de CI. Por lo general, esto no es más complicado que ejecutar uno de los comandos integrados en el conjunto estándar de utilidades en un lenguaje de programación. En tales pruebas, es probable que use varios moki y stubs para ocultar los detalles de implementación y centrarse en probar la lógica específica. Por ejemplo, puede usar la base de datos en memoria como almacenamiento o apéndices de escritura para clientes HTTP que siempre devolverán respuestas ya preparadas.
Sin embargo, tarde o temprano necesitará
pruebas de integración para cubrir situaciones más inusuales con pruebas. No entraré en discusión sobre todos los tipos posibles de pruebas y solo diré que por
integración me refiero a las pruebas que usan algún tipo de recursos externos. Puede ser un servidor de base de datos real, servicio HTTP, almacenamiento conectado, etc.
En GitLab, es fácil ejecutar recursos conectables como contenedores Docker asociados con el contenedor donde se ejecutan los scripts. Estas dependencias se pueden definir utilizando
services
. Están disponibles por el nombre de la imagen o por el nombre que elija, si lo especifica en el campo de
alias
.
Aquí hay un ejemplo simple de uso de un contenedor conectable con MySQL:
integration_tests: stage: tests services: - name: mysql:8 alias: db script: - ./run_tests.sh db:3306
En este caso, en los scripts de prueba, deberá conectarse al host
db
. El uso de un alias suele ser una buena idea, ya que le permite reemplazar imágenes sin la necesidad de modificar el código de prueba. Por ejemplo, puede reemplazar la imagen
mysql
con
mariadb
, y el script seguirá funcionando correctamente.
Esperando contenedores
Como los contenedores de complementos tardan en cargarse, es posible que deba esperar antes de enviar cualquier solicitud. Una manera simple es
esperar el script script
for-it.sh con un tiempo de espera definido.
Usando Docker Compose
Para la mayoría de los casos, los
services
deberían ser suficientes. Sin embargo, a veces puede ser necesaria la interacción con servicios externos. Por ejemplo, en el caso de lanzar Kafka y ZooKeeper en dos contenedores separados (así es como se recopilan las imágenes oficiales). Otro ejemplo es ejecutar pruebas con un número dinámico de nodos, como Selenium. La mejor solución para ejecutar estos servicios sería
Docker Compose :
version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 ports: - 9092:9092
Si usa su instalación con corredores GitLab en servidores confiables, puede ejecutar Docker Composer a través del
ejecutor Shell . Otra opción posible es el
dind
Docker en Docker (
dind
). Pero en este caso, lea
este artículo primero.
Una forma de usar Compose es configurar su entorno, ejecutar pruebas y luego destruir todo. Un script bash simple se vería así:
docker-compose up -d ./run_tests.sh localhost:9092 docker-compose down
Siempre que ejecute pruebas en un entorno mínimo, todo estará bien. Aunque puede surgir una situación en la que necesite instalar algunas dependencias ... Hay otra forma de ejecutar pruebas en Docker Compose: le permite crear su propia imagen de Docker con un entorno de prueba. En uno de los contenedores, ejecuta pruebas y sale con el código de retorno correspondiente:
version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 tests: image: registry.example.com/some-image command: ./run_tests.sh kafka:9092
Tenga en cuenta que hemos eliminado la necesidad de asignar puertos. En este ejemplo, las pruebas pueden interactuar con todos los servicios directamente.
Y su lanzamiento se lleva a cabo mediante un comando:
docker-compose up --exit-code-from tests
La
--abort-on-container-exit
--exit-code-from
implica
--abort-on-container-exit
, lo que significa: todo el entorno iniciado por
docker-compose up
se detendrá una vez que se complete uno de los contenedores. El código de finalización para este comando será equivalente al código de salida del servicio seleccionado (es decir, estas son
tests
en el ejemplo anterior). Si el comando que inicia las pruebas se completa con un código distinto de cero, entonces todo
docker-compose up
saldrá con él.
Usar etiquetas como etiquetas CI
Advertencia : esta es una idea bastante inusual, pero me pareció muy útil y flexible.
Como ya sabrás, GitLab tiene una función de Etiquetas disponible a nivel de proyecto y grupo. Las etiquetas se pueden establecer en tickets y solicitudes de fusión. Sin embargo, no tienen relación con las tuberías.

Un pequeño refinamiento le permitirá acceder a las etiquetas de la solicitud de fusión en los scripts de trabajo. En GitLab 11.6, todo se ha vuelto aún más fácil, porque La variable de entorno
CI_MERGE_REQUEST_IID
ha aparecido (sí, es con el
IID
, no el
ID
), si la canalización usa
only: merge_requests
.
Si
only: merge_requests
no se usa o si está trabajando con una versión anterior de GitLab, todavía se puede obtener MR, utilizando la llamada API:
curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA/merge_requests?private_token=$GITLAB_TOKEN"
El campo que necesitamos es
iid
. Sin embargo, recuerde que muchos MR pueden regresar para un compromiso determinado.
Cuando se recibe el MR IID, solo queda recurrir a la
API de solicitudes de combinación y usar el campo de
labels
de la respuesta:
curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID?private_token=$GITLAB_TOKEN"
Iniciar sesión
Desafortunadamente, por el momento
no es posible usar
$CI_JOB_TOKEN
para acceder a la API del proyecto (al menos si el proyecto no es público). Si el proyecto tiene acceso limitado (interno o privado), para obtener autorización en la API de GitLab, deberá generar un token de API personal.

Sin embargo, esta no es la solución más segura, así que tenga cuidado. Si el token cae en malas manos, puede aparecer el acceso de escritura a todos sus proyectos. Una forma de reducir los riesgos es crear una cuenta separada con el derecho de leer el repositorio y generar un token personal para esta cuenta.
¿Qué tan seguras son sus variables?
Hace algunas versiones, la sección
Variables se llamaba
Variables secretas , que parece que fueron creadas para almacenar de forma confiable las credenciales y otra información crítica. De hecho, las variables simplemente están ocultas para los usuarios que no tienen privilegios de mantenedor. No están encriptados en el disco, y su fuga puede ocurrir fácilmente a través de variables de entorno en los scripts.
Tenga esto en cuenta al agregar cualquier variable y considere guardar secretos en soluciones más seguras (por ejemplo,
Vault de HashiCorp ).
Casos de uso
Lo que debe hacer con las listas de etiquetas depende de usted. Aquí hay algunas ideas:
- Úsalos para segmentar las pruebas.
- Utilice la semántica de valores clave con dos puntos como separador (por ejemplo, etiquetas como
tests:auth
, tests:user
) - Incluye ciertas características para trabajos.
- Permita la depuración de trabajos específicos si existe la etiqueta.
Llamar a API externas
Aunque GitLab viene con una gama de características ya disponibles, es muy probable que desee utilizar otras utilidades que se puedan integrar con las canalizaciones. La forma más sencilla de implementarlo es, por supuesto, llamar al viejo
curl
.
Si crea sus propias herramientas, puede enseñarles a escuchar
GitLab Webhooks (consulte la pestaña
Integraciones en la configuración del proyecto). Sin embargo, si tiene la intención de usarlos con cualquier sistema crítico, asegúrese de que cumplan con los requisitos de alta disponibilidad.
Ejemplo: anotaciones de Grafana
Si trabaja con
Grafana , las
anotaciones son una excelente manera de marcar eventos que han ocurrido con el tiempo en los gráficos. Se pueden agregar no solo manualmente haciendo clic en la GUI, sino también llamando a la
API REST de Grafana :

Para acceder a la API, deberá generar una clave de API. Considere crear un usuario separado con acceso limitado:

Defina dos variables en la configuración del proyecto:
GRAFANA_URL
: URL de la instalación de Grafana (por ejemplo, https://grafana.example.com
);GRAFANA_APIKEY
: clave generada para la API.
Para poder reutilizarlo, coloque el script en el
repositorio con scripts comunes :
Ahora puede agregar su llamada a la configuración de CI con los parámetros necesarios:
deploy: stage: deploy script: - $SCRIPTS_DIR/deploy.sh production - $SCRIPTS_DIR/grafana-annotation.sh "$VERSION deployed to production" deploy-production
Estas llamadas se pueden colocar en el script
deploy.sh
para simplificar la configuración de CI.
Bono: consejos rápidos
GitLab tiene una
excelente documentación sobre todas las palabras clave posibles que se pueden usar para configurar CI. No quiero duplicar su contenido aquí, pero señalaré algunos casos útiles. Haga clic en los encabezados para ver la documentación relacionada.
Al definir patrones para las variables de CI, puede definir ensamblados personalizados para algunas ramas. Esto puede ayudar, por ejemplo, a identificar soluciones push para soluciones urgentes, pero no abusar de ellas:
only: refs: - branches variables: - $CI_COMMIT_REF_NAME =~ /^hotfix/
GitLab tiene muchas
variables predefinidas en cada trabajo de CI: úselas.
Úsalos para evitar la duplicación.
Desde la versión 11.3, también puede usar la
palabra clave extend :
.common_before_script: &common_before_script before_script: - ... - ... deploy: <<: *common_before_script
De forma predeterminada, todos los artefactos recopilados en la tubería se transferirán a todos los trabajos posteriores. Si enumera explícitamente los artefactos de los que dependen los trabajos, puede ahorrar tiempo y espacio en disco:
dependencies: - build
O, por el contrario, omita todo por completo si no se requiere ninguno de ellos:
dependencies: []
Omita la clonación del repositorio si el trabajo no usará estos archivos:
variables: GIT_STRATEGY: none
Eso es todo!
Gracias por leer! Para comentarios y preguntas, contácteme en
Twitter o
Reddit .
Se pueden encontrar más consejos de GitLab en publicaciones anteriores:
PD del traductor
Lea también en nuestro blog: