GitHub Actions CI/CD: Criando Workflows de Build, Teste e Deploy do Zero
Aprenda a configurar o GitHub Actions para integração e entrega contínua. Abrange triggers, jobs, matrizes, secrets, caching, Docker e exemplos reais de workflows.
O GitHub Actions transforma cada push, pull request e merge em um pipeline automatizado — executando testes, gerando artefatos, verificando vulnerabilidades e fazendo deploy em produção. É a plataforma de CI/CD que vive direto dentro do seu repositório, sem nenhuma infraestrutura para gerenciar.
Como o GitHub Actions funciona
Cada workflow é um arquivo YAML dentro de .github/workflows/. Quando um evento de trigger é disparado, o GitHub sobe uma máquina virtual nova, executa os seus jobs e reporta os resultados — tudo em questão de segundos.
Push para main
↓
Workflow disparado
↓
Job: Build & Test (ubuntu-latest)
├── Passo 1: Checkout do código
├── Passo 2: Instalar Node.js
├── Passo 3: npm ci
├── Passo 4: npm test
└── Passo 5: npm run build
↓
✅ Todas as verificações passaram
Seu primeiro workflow
Crie .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
É só isso. A partir de agora, cada push para main e cada PR executará sua suíte de testes automaticamente.
Triggers: quando os workflows são executados
Eventos de código
on:
push:
branches: [main, develop]
paths: ['src/**', 'package.json'] # Só executa quando esses arquivos mudam
pull_request:
types: [opened, synchronize]
Agendado (cron)
on:
schedule:
- cron: '0 6 * * 1' # Toda segunda-feira às 6:00 UTC
Acionamento manual
on:
workflow_dispatch:
inputs:
environment:
description: 'Destino do deploy'
required: true
type: choice
options: [staging, production]
Isso adiciona um botão "Run workflow" na interface do GitHub onde você pode selecionar parâmetros.
Workflows reutilizáveis
on:
workflow_call:
inputs:
node-version:
type: string
default: '20'
Chame-o a partir de outro workflow com uses: ./.github/workflows/reusable.yml.
Jobs e steps
Jobs em paralelo
Por padrão, os jobs são executados em paralelo:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
build:
runs-on: ubuntu-latest
needs: [lint, test] # Aguarda os dois passarem
steps:
- uses: actions/checkout@v4
- run: npm run build
Estratégia de matriz — teste em múltiplas versões
Execute o mesmo job em diversas configurações:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Isso cria 6 jobs paralelos (3 versões × 2 sistemas operacionais).
Secrets e variáveis de ambiente
Usando secrets
Armazene valores sensíveis em Settings → Secrets and variables → Actions:
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
Os secrets são ocultados nos logs e nunca são expostos em forks.
Variáveis de ambiente
# Nível do workflow
env:
NODE_ENV: production
jobs:
build:
# Nível do job
env:
CI: true
steps:
- name: Build
# Nível do step
env:
VITE_API_URL: https://api.example.com
run: npm run build
Caching para builds mais rápidos
Sem caching, cada execução baixa todas as dependências do zero. O caching reduz o tempo de build em 50-80%:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # Caching nativo de npm
# Ou caching manual para outras ferramentas
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
Artefatos: compartilhando dados entre jobs
Faça upload dos resultados de build em um job e baixe em outro:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: dist
- run: ./deploy.sh
Exemplos reais de workflows
Build e push de Docker
name: Docker
on:
push:
tags: ['v*']
permissions:
packages: write
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
Deploy para Cloudflare Pages
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci && npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: pages deploy dist --project-name=my-site
Release com changelog
name: Release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Gerar changelog
run: |
git log $(git describe --tags --abbrev=0 HEAD^)..HEAD \
--pretty=format:"- %s" > CHANGELOG.md
- uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
generate_release_notes: true
Execução condicional
Controle quando steps e jobs são executados:
steps:
- name: Deploy para produção
if: github.ref == 'refs/heads/main'
run: ./deploy-prod.sh
- name: Deploy para staging
if: github.event_name == 'pull_request'
run: ./deploy-staging.sh
- name: Notificar em caso de falha
if: failure()
run: curl -X POST ${{ secrets.SLACK_WEBHOOK }} -d '{"text":"Build falhou!"}'
Boas práticas de segurança
1. Fixe as versões das actions por SHA
# ❌ Tag mutável — pode ser comprometida
- uses: actions/checkout@v4
# ✅ Fixado ao SHA exato do commit
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
2. Use permissões mínimas necessárias
permissions:
contents: read # Apenas o necessário
packages: write
3. Nunca exiba secrets com echo
# ❌ NUNCA faça isso
- run: echo ${{ secrets.API_KEY }}
# ✅ Use variáveis de ambiente
- env:
API_KEY: ${{ secrets.API_KEY }}
run: ./script-that-uses-api-key.sh
4. Limite permissões para PRs de forks
on:
pull_request_target: # Executa no contexto da branch base
types: [opened, synchronize]
Depurando workflows com falha
- Verifique os logs — Clique em qualquer step com falha para ver a saída completa
- Ative logs de depuração — Defina o secret
ACTIONS_STEP_DEBUGcomotrue - Use
actlocalmente — Execute workflows na sua máquina com nektos/act - Acesse o runner via SSH — Use
mxschmitt/action-tmatepara depuração interativa
Crie workflows visualmente
Não quer escrever YAML na mão? Use nosso GitHub Actions Generator para criar workflows visualmente com templates para Node.js, Python, Docker, deploys e muito mais — e baixe um YAML pronto para produção.
Conclusão
O GitHub Actions oferece CI/CD que vive dentro do seu repositório:
- Comece simples — Um arquivo de workflow com build + test
- Adicione caching — Reduza o tempo de build com
actions/cacheou caching nativo da linguagem - Use matriz — Teste em múltiplas versões e sistemas operacionais
- Proteja os secrets — Nunca os deixe hardcoded, use sempre secrets criptografados
- Automatize tudo — Releases, deploys, verificações de segurança, tarefas agendadas
O melhor pipeline de CI/CD é aquele que roda a cada commit sem que você precise pensar nisso. Configure uma vez e deixe o GitHub cuidar do resto.