DEV Community

Cover image for GitHub Actions - Elixir
Vitor Leal for Ingresse

Posted on

GitHub Actions - Elixir

O Actions é uma ferramenta integrada aos seus repositórios do GitHub para automatizar os seus workflows de CI/CD (continuous delivery / continuous deploy). Você consegue rodar esses workflows baseado em diversos eventos do GitHub, como um novo push em uma branch a criação de uma nova issue ou uma nova release publicada.

Contexto

Desde que o GitHub lançou a versão beta do Actions, a Ingresse vem a testando. No final do ano passado o Actions saiu da versão beta e a gente decidiu finalmente migrar nossos workflows para lá.

Já que Elixir é a nossa linguagem principal na Ingresse, começamos a migrar primeiro os workflows dos serviços em Elixir para o Actions e aqui tem algumas dicas de como a gente faz.

Básico


Antes de tudo vou apresentar um pouco do básico do GitHub Actions, se você já tem familiaridade pode seguir passar direto essa seção.


O Actions vai ler os arquivos .yml ou .yaml dentro da pasta .github/workflows na raiz do seu projeto.

Primeiro vamos criar a pasta .github com a pasta workflows dentro:

mkdir -p .github/workflows 
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar um arquivo que a gente pode chamar de ci.yml:

touch .github/workflows/ci.yml 
Enter fullscreen mode Exit fullscreen mode

Agora vamos adicionar o seguinte conteúdo nele:

name: Meu Workflow on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 
Enter fullscreen mode Exit fullscreen mode

Vamos aos detalhes do conteúdo desse arquivo.

name

O nome do seu workflow. É um campo opcional.


on

O nome do evento do GitHub que vai iniciar esse workflow.

Pode ser um evento apenas:

# Vai rodar sempre que alguém realizar um push no repositório on: push 
Enter fullscreen mode Exit fullscreen mode

Pode ser uma lista de eventos:

# Vai rodar sempre que alguém realizar um push no repositório # e quando for criado um novo pull request on: [push, pull_request] 
Enter fullscreen mode Exit fullscreen mode

Pode ser customizado por evento:

on: # Vai rodar sempre que um pull request for criado pull_request: # Mas quando estiver apontando para a master branches: - master # Vai rodar sempre que uma release for criada release: # Mas se ela estiver com o status de publicada types: - published 
Enter fullscreen mode Exit fullscreen mode

jobs

Um workflow pode ter um ou mais jobs. Por padrão, múltiplos jobs rodam em paralelo.


jobs.<id-do-job>.run-on

Em que tipo de máquina o job vai ser executado.

Pode ser em um tipo de máquina:

jobs: test: runs-on: ubuntu-latest 
Enter fullscreen mode Exit fullscreen mode

Podem ser em múltiplos tipos de máquinas, incluindo ubuntu, macos e windows:

jobs: test: strategy: matrix: platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} 
Enter fullscreen mode Exit fullscreen mode

jobs.<id-do-job>.steps

Um job pode ter uma ou mais tarefas que vão ser executadas. Uma tarefa pode executar comandos, rodar setups ou rodar outras actions. O próprio GitHub tem uma série de actions publicadas que facilitam muitos trabalhos. Nesse exemplo estamos usando a action actions/checkout na versão v1 para clonar o repositório do projeto.

jobs: test: runs-on: ubuntu-latest steps: # Primeira tarefa a ser executada vai ser clonar o repositório - uses: actions/checkout@v1 
Enter fullscreen mode Exit fullscreen mode

Próximos passos

Bom agora que a gente já sabe um pouco mais sobe a estrutura básica de um workflow do GitHub Actions vamos começar a moldar ele para executar por exemplo uma tarefa de mix format e uma tarefa de mix test em um projeto Elixir.

Para evitar ter que instalar o Elixir no processo de build, vamos utilizar o atributo container para baixar uma imagem Docker já existente.

name: Meu Workflow on: push jobs: test: runs-on: ubuntu-latest container: image: elixir:1.10 steps: - uses: actions/checkout@v1 
Enter fullscreen mode Exit fullscreen mode

jobs.<id-do-job>.container

Em qual imagem Docker vai rodar as tarefas desse job.

jobs: test: container: image: elixir:1.10 
Enter fullscreen mode Exit fullscreen mode

Agora que nosso ambiente já tem Elixir, podemos criar as tarefas para executar o mix format e mix test.

name: Meu Workflow on: push jobs: test: runs-on: ubuntu-latest container: image: elixir:1.10 steps: - uses: actions/checkout@v1 - name: Formatar run: mix format --check-formatted - name: Instalar as dependências run: mix deps.get - name: Testar run: mix test 
Enter fullscreen mode Exit fullscreen mode

Pronto já temos um workflow que clona nosso repositório, verifica se nosso código está formatado de acordo com as configurações do projeto, instala as dependências e roda nossos testes.


Utilizando serviços

O cenário anterior funciona perfeitamente para quando a gente tem um lib escrita em Elixir, mas para casos que a gente esteja trabalhando em um projeto com Phoenix por exemplo, a gente vai precisar provavelmente conectar em um banco de dados para poder executar alguns testes.

Nesse momento a gente consegue utilizar os services para criar containers de um banco de dados Postgres, por exemplo, para que os nossos jobs possam ter onde se conectar.

jobs.<id-do-job>.services

services: postgres: image: postgres # Mapeia a porta 5432 no container Docker para a porta 5432 no container do Postgres ports: - 5432:5432 # Configura os dados de acesso ao banco de teste env: POSTGRES_USER: usuario POSTGRES_PASSWORD: senha POSTGRES_DB: banco 
Enter fullscreen mode Exit fullscreen mode

Agora que o nosso workflow vai criar o banco de dados pra gente poder conectar, tem um detalhe que temos que alterar nas nossas tarefas que vão rodar para conectar nesse banco. No caso, a nossa tarefa mix test tem que receber uma variável de ambiente para poder conectar corretamente no banco criado pelo Actions.

- name: Testar run: mix test env: POSTGRES_HOST: postgres POSTGRES_PORT: $❴❴ job.services.postgres.ports[5672] ❵❵ 
Enter fullscreen mode Exit fullscreen mode

O exemplo completo fica assim:

name: Meu Workflow on: push jobs: test: runs-on: ubuntu-latest container: image: elixir:1.10 services: postgres: image: postgres ports: - 5432:5432 env: POSTGRES_USER: usuario POSTGRES_PASSWORD: senha POSTGRES_DB: banco steps: - uses: actions/checkout@v1 - name: Formatar run: mix format --check-formatted - name: Instalar as dependências run: mix deps.get - name: Testar run: mix test env: POSTGRES_HOST: postgres POSTGRES_PORT: $❴❴ job.services.postgres.ports[5432] ❵❵ 
Enter fullscreen mode Exit fullscreen mode

Agora basta alterar as configurações da nosso ambiente de teste para receber utilizar as variáveis de ambiente:

import Config config :meu_app, Meu.Repo, adapter: Ecto.Adapters.Postgres, username: "usuario", password: "senha", database: "banco", port: String.to_integer(System.get_env("POSTGRES_PORT", "5432")) hostname: System.get_env("POSTGRES_HOST"), pool: Ecto.Adapters.SQL.Sandbox 
Enter fullscreen mode Exit fullscreen mode

Docker Compose

Se você já utiliza Docker Compose nos seus projetos você não precisa criar os services no arquivo do Actions e pode criar esses serviços direto no seu arquivo do Docker Compose de teste.

Exemplo do arquivo docker-compose-test.yml:

version: "3.3" services: meu_servico: build: . depends_on: - meu_postgres ports: - "4000:4000" environment: - MIX_ENV=test command: mix phx.server postgres: image: postgres container_name: meu_postgres environment: - POSTGRES_DB=banco - POSTGRES_USER=usuario - POSTGRES_PASSWORD=senha ports: - "5433:5432" 
Enter fullscreen mode Exit fullscreen mode

Para rodar os testes com o Docker Compose, o ideal é mudar a imagem que roda no Actions para uma imagem que tenha já tenha o compose instalado.

jobs: container: image: docker/compose 
Enter fullscreen mode Exit fullscreen mode

O exemplo completo fica assim:

name: Meu Workflow on: push jobs: test: runs-on: ubuntu-latest container: image: docker/compose steps: - uses: actions/checkout@v1 - name: Formatar run: docker-compose -f docker-compose-test.yml run meu_servico mix format --check-formatted - name: Testar run: docker-compose -f docker-compose-test.yml run meu_servico mix test 
Enter fullscreen mode Exit fullscreen mode

Espero que tenha ajudado vocês a entender um pouco melhor como rodar projetos Elixir no GitHub Actions.

Até a próxima!

Top comments (0)