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
Agora vamos criar um arquivo que a gente pode chamar de ci.yml
:
touch .github/workflows/ci.yml
Agora vamos adicionar o seguinte conteúdo nele:
name: Meu Workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
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
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]
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
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
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 }}
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
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
jobs.<id-do-job>.container
Em qual imagem Docker vai rodar as tarefas desse job.
jobs:
test:
container:
image: elixir:1.10
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
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
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] ❵❵
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] ❵❵
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
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"
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
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
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)