CI/CD desmistificado: automatizando testes e deploys com GitHub Actions

1. O que é CI/CD e por que automatizar?

Integração Contínua (CI) e Entrega Contínua (CD) são práticas fundamentais no desenvolvimento moderno de software. CI consiste em integrar alterações de código em um repositório compartilhado várias vezes ao dia, executando testes automatizados para validar cada mudança. CD vai além, automatizando o processo de deploy para ambientes de produção ou staging após a aprovação dos testes.

Os benefícios práticos são significativos. A redução de erros manuais ocorre porque tarefas repetitivas como build, teste e deploy são executadas por scripts, eliminando a inconsistência humana. O feedback rápido permite que desenvolvedores identifiquem problemas minutos após um commit, não dias depois. Deploys confiáveis garantem que apenas código testado chegue à produção.

Diferente de ferramentas tradicionais como Jenkins (que requer servidores dedicados) ou GitLab CI (que precisa de runners próprios), o GitHub Actions é nativo da plataforma GitHub. Isso elimina a necessidade de infraestrutura externa, integra-se perfeitamente com pull requests e oferece 2000 minutos gratuitos por mês para contas pessoais.

2. Primeiros passos com GitHub Actions

Um workflow no GitHub Actions é composto por:

  • Eventos: gatilhos que iniciam o workflow (push, pull_request, schedule)
  • Jobs: unidades de trabalho executadas em runners (máquinas virtuais)
  • Steps: comandos individuais dentro de um job
  • Runners: servidores que executam os jobs (ubuntu-latest, windows-latest, macos-latest)

Para criar seu primeiro workflow, crie o diretório .github/workflows/ no repositório e adicione um arquivo YAML. Exemplo básico:

name: CI Básico
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Saudacao
        run: echo "Workflow iniciado com sucesso!"

Os gatilhos comuns incluem: push (qualquer commit), pull_request (abertura/sincronização de PR), schedule (execução agendada via cron) e workflow_dispatch (execução manual pela interface).

3. Automatizando testes com CI

A configuração de jobs de teste varia conforme a linguagem. Exemplo para Node.js:

name: Testes Node.js
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16, 18, 20]
    steps:
      - uses: actions/checkout@v4
      - name: Usar Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      - run: npm ci
      - run: npm test

Para Python, a matriz permite testar em diferentes versões e sistemas operacionais:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        python-version: ['3.9', '3.10', '3.11']
    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install pytest
      - run: pytest

Serviços externos como bancos de dados podem ser configurados via services:

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: senha_teste
        ports:
          - 5432:5432
    steps:
      - uses: actions/checkout@v4
      - run: npm test

4. Estratégias de deploy automatizado (CD)

O deploy contínuo envia automaticamente para produção após testes bem-sucedidos. O deploy manual com aprovação usa ambientes (environments) que exigem revisão humana antes de prosseguir.

Exemplo de deploy para GitHub Pages:

name: Deploy para GitHub Pages
on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: npm ci && npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: './dist'
      - name: Deploy
        id: deployment
        uses: actions/deploy-pages@v4

Para deploy via SSH em servidor próprio:

- name: Deploy via SSH
  uses: easingthemes/ssh-deploy@v4
  with:
    ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
    remote-host: ${{ secrets.REMOTE_HOST }}
    remote-user: ${{ secrets.REMOTE_USER }}
    source: './dist/'
    target: '/var/www/html/'

Segredos (secrets) são configurados em Settings > Secrets and variables > Actions do repositório.

5. Otimização de workflows e boas práticas

Reutilização de código com actions reutilizáveis:

# .github/actions/setup-node/action.yml
name: 'Setup Node'
description: 'Configura Node.js com cache'
inputs:
  node-version:
    required: true
runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'
    - run: npm ci
      shell: bash

Cache de dependências acelera execuções:

- uses: actions/cache@v3
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Tratamento de falhas com notificações:

- name: Notificar falha
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: '{"text":"Workflow falhou em ${{ github.repository }}"}'
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

6. Monitoramento e manutenção contínua

Os logs de execução são acessíveis na aba "Actions" do repositório. Artefatos (arquivos gerados durante o workflow) podem ser baixados via interface. O status de execução aparece nos commits e pull requests.

Alertas podem ser configurados para Slack, Discord ou e-mail. Exemplo com Discord:

- name: Notificar Discord
  if: failure()
  uses: Ilshidur/action-discord@master
  with:
    args: 'Workflow falhou em {{ EVENT_PAYLOAD.repository.full_name }}'
  env:
    DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}

Manter actions de terceiros atualizadas é crucial. Use o Dependabot para atualizar automaticamente:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: 'github-actions'
    directory: '/'
    schedule:
      interval: 'weekly'

7. CI/CD no contexto do desenvolvimento 100% na nuvem

O GitHub Actions integra-se nativamente com GitHub Codespaces. Ao abrir um codespace, o ambiente de desenvolvimento já está configurado com as mesmas ferramentas do CI. O Gitpod também oferece integração, permitindo testar workflows antes do push.

Para testar workflows localmente, use a ferramenta act:

# Instalação
curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

# Executar workflow localmente
act push

O fluxo completo na nuvem funciona assim: desenvolvedor faz commit no GitHub Codespaces ou Gitpod → gatilho do workflow → testes automáticos → deploy para produção. Tudo sem sair do navegador.

Referências