Uso de GitHub CI para proyectos de elixir

En octubre, Github lanzó acciones que le permiten ejecutar CI sin salir de la caja en la que se almacena este código. Es realmente muy conveniente. Tan pronto como alguien envía una solicitud de extracción , o simplemente carga nuevos cambios en el servidor, o algo más especial (se puede encontrar una lista de eventos a los que se pueden ajustar las acciones en la documentación oficial ), comienza el ensamblaje. Las tareas recurrentes programadas ( basadas en cron ) también son compatibles.


Puede crear canales de acción llamados flujos de trabajo . Y todo esto es hermoso y parece un futuro brillante, con la excepción de la documentación.


Me llevó más de una hora descubrir cómo crear un contenedor con servicios de terceros para probar la aplicación. Esto es lo que logré averiguar. Tenga en cuenta que la documentación oficial es francamente incómoda, incompleta y, a menudo, simplemente errónea.


La acción de CI estándar utiliza archivos de configuración con una sintaxis muy similar a la utilizada por CircleCI . Este es solo el viejo YAML , que le permite configurar el sistema operativo de destino, el entorno, los comandos para ejecutar, etc. Las acciones mismas reciben nombres únicos , lo que le permite referirse a otras acciones y depender de ellas.


Además, la configuración le permite especificar servicios . Los servicios deben ejecutarse en algún lugar de la nube, y GH asignará los puertos del contenedor a los puertos que estos servicios exponen, de acuerdo con la configuración. Esta parte está mal cubierta en la documentación oficial, e incluso lo que se describe contiene errores.


Aquí hay un ejemplo de configuración de trabajo para un proyecto de Elixir que requiere los servicios RabbitMQ y Redis para probar.


 name: Tests for My Project on: [push, pull_request] jobs: build: runs-on: ubuntu-latest container: image: elixir:1.9.1-slim services: rabbitmq: image: rabbitmq ports: - 5672:5672 env: RABBITMQ_USER: guest RABBITMQ_PASSWORD: guest RABBITMQ_VHOST: "/" redis: image: redis ports: - 6379:6379 steps: - uses: actions/checkout@v1 - name: Install Dependencies run: | MIX_ENV=ci mix local.rebar --force MIX_ENV=ci mix local.hex --force MIX_ENV=ci mix deps.get - name: Run All Tests run: | MIX_ENV=ci mix test env: RABBITMQ_HOST: rabbitmq RABBITMQ_PORT: ${{ job.services.rabbitmq.ports[5672] }} REDIS_HOST: redis REDIS_PORT: ${{ job.services.redis.ports[6379] }} 

Como puede ver, las pruebas se ejecutarán en Ubuntu usando Elixir v1.9.1. Los servicios se describen bajo los servicios clave, y aquí comienza una historia de detectives pura. El motor de contenedor selecciona aleatoriamente el puerto físico al que se vinculará el puerto de servicio en tiempo de ejecución y se almacena en una variable de shell interna denominada job.services.rabbitmq.ports[5672] . rabbitmq es el nombre del servicio, como se indica en este archivo en la sección de servicios , y 5672 es el puerto de origen. La variable interna tiene la sintaxis $ {{foo}} y se pasa a la variable de entorno RABBITMQ_PORT (el último bloque de configuración, bajo la clave env ). En RABBITMQ_HOST , debe poner el nombre del servicio, como debajo de la clave de servicios . Ahora la aplicación puede leer las variables de entorno como de costumbre y los puertos se desplazarán correctamente.


Así es como leeremos estas variables de entorno del entorno (esta es una configuración para Elixir , para otros idiomas habrá algo muy similar).


 import Config config :my_app, rabbitmq: [ host: System.get_env("RABBITMQ_HOST"), password: "guest", port: String.to_integer(System.get_env("RABBITMQ_PORT", "5672")), username: "guest", virtual_host: "/", x_message_ttl: "4000" ] 

En el archivo del proyecto, creo un entorno especial :ci , para distinguir entre la configuración de las pruebas realizadas en el entorno local y las mismas pruebas realizadas en algún lugar de la nube.


Además, en la tubería de CI , ejecuto dialyzer en mis fuentes. Como se ejecuta en el contenedor, la tarea lleva algo de tiempo, ya que debe reconstruir los plts desde cero cada vez. Es por eso que hago esto una vez al día usando la opción de configuración de schedule .


 name: Dialyzer for My Project on: schedule: - cron: "0 1 * * *" jobs: build: runs-on: ubuntu-latest container: image: elixir:1.9.1-slim steps: - uses: actions/checkout@v1 - name: Install Dependencies run: | MIX_ENV=ci mix local.rebar --force MIX_ENV=ci mix local.hex --force MIX_ENV=ci mix deps.get - name: Run All Tests run: | MIX_ENV=ci mix code_quality 

aquí code_quality es un alias de tarea declarado en mix.exs


 defp aliases do [ code_quality: ["format", "credo --strict", "dialyzer"] ] end 

Aquí, en general, eso es todo lo que necesitamos para una prueba feliz de un proyecto con dependencias externas en el nuevo flujo de trabajo de Github .


Integración continua exitosa!

Source: https://habr.com/ru/post/481846/


All Articles