Passo a passo: Configurando pipeline CI/CD no GitHub Actions
Configure pipelines completos: build, testes, deploy automático, secrets, matrix builds e deploy em produção com GitHub Actions.
O que é CI/CD e por que usar GitHub Actions
CI (Continuous Integration): automatiza build e testes a cada push/PR. Detecta problemas cedo.
CD (Continuous Deployment): automatiza deploy em produção após testes passarem.
GitHub Actions é a plataforma de CI/CD nativa do GitHub. Vantagens:
- Integrado ao repositório (sem configuração externa)
- Gratuito para repos públicos (2000 minutos/mês para privados)
- Marketplace com milhares de actions prontas
- Suporta Linux, Windows, macOS
Conceitos básicos
Estrutura de um workflow
- Workflow: pipeline automatizado (arquivo YAML em
.github/workflows/) - Job: conjunto de steps que rodam em um runner
- Step: tarefa individual (rodar comando, usar action)
- Runner: máquina virtual que executa os jobs
- Action: comando reutilizável (ex:
actions/checkout@v4)
Triggers (eventos que disparam workflows)
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # todo dia às 2h
workflow_dispatch: # manual via UI
Passo 1: Seu primeiro workflow
Criar arquivo de workflow
Crie .github/workflows/ci.yml no seu repositório:
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build project
run: npm run build
Commit e push. O workflow rodará automaticamente.
Passo 2: Workflow completo para Node.js
name: Node.js CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
file: ./coverage/coverage-final.json
fail_ci_if_error: true
build:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
Passo 3: Workflow para Python
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov flake8
- name: Lint with flake8
run: |
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --max-line-length=127 --statistics
- name: Run tests
run: pytest --cov=./ --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
Passo 4: Workflow para Docker
name: Docker Build and Push
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
Passo 5: Deploy automático (Vercel, Netlify, AWS)
Deploy para Vercel
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
Deploy para AWS S3 + CloudFront
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install and build
run: |
npm ci
npm run build
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Sync to S3
run: |
aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
- name: Invalidate CloudFront
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
Passo 6: Gerenciar secrets
Adicionar secrets no GitHub
- Vá em Settings > Secrets and variables > Actions
- Clique em New repository secret
- Adicione nome e valor (ex:
AWS_ACCESS_KEY_ID)
Usar secrets no workflow
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: |
echo "Deploying with API key"
./deploy.sh
Passo 7: Matrix builds (testar múltiplas versões)
name: Multi-version Test
on: [push]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [18, 20, 22]
exclude:
- os: macos-latest
node-version: 18
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Passo 8: Conditional steps e environments
Steps condicionais
steps:
- name: Run only on main
if: github.ref == 'refs/heads/main'
run: echo "This is main branch"
- name: Run only on PR
if: github.event_name == 'pull_request'
run: echo "This is a PR"
- name: Run only on success
if: success()
run: echo "Previous steps succeeded"
- name: Run even on failure
if: always()
run: echo "This always runs"
Environments (staging, production)
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.myapp.com
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: ./deploy-staging.sh
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.com
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: ./deploy-production.sh
Passo 9: Reutilizar workflows (Composite Actions)
Criar action reutilizável (.github/actions/setup/action.yml)
name: 'Setup Project'
description: 'Install dependencies and cache'
runs:
using: 'composite'
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
shell: bash
run: npm ci
Usar no workflow
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npm test
Passo 10: Monitoramento e debugging
Ver logs detalhados
steps:
- name: Debug info
run: |
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
echo "Actor: ${{ github.actor }}"
echo "SHA: ${{ github.sha }}"
- name: Enable debug logging
run: echo "::debug::This is a debug message"
Adicionar status badge no README

Boas práticas
1. Cache de dependências
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # Acelera installs
2. Fail fast em matrix builds
strategy:
fail-fast: true # Para todos os jobs se um falhar
matrix:
node-version: [18, 20, 22]
3. Timeout para evitar custos
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10 # Cancela após 10min
4. Concurrency (evitar deploys simultâneos)
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
5. CODEOWNERS para aprovar workflows
Crie .github/CODEOWNERS:
.github/workflows/* @seu-time
Troubleshooting comum
Erro: "No space left on device"
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
Erro: "Permission denied" no deploy
Adicione permissões ao job:
jobs:
deploy:
permissions:
contents: write
packages: write
Workflow não dispara
- Verifique se o arquivo está em
.github/workflows/ - Confira indentação YAML (use validador)
- Confirme que o evento (push/PR) corresponde ao trigger
Conclusão
GitHub Actions simplifica CI/CD diretamente no repositório. Comece com workflows básicos (build + test), evolua para matrix builds, adicione deploy automático e monitore com badges. Com pipelines bem configurados, você detecta bugs cedo, garante qualidade e acelera entregas.
FAQ
GitHub Actions é gratuito?
Sim para repos públicos. Repos privados têm 2000 minutos gratuitos por mês (plano free).
Posso rodar workflows localmente?
Sim, use a ferramenta act (github.com/nektos/act) para testar workflows no Docker.
Como fazer rollback automático?
Use environments com protection rules. Se o deploy falhar, dispare outro workflow que faz rollback para versão anterior.
Qual a diferença entre CI e CD?
CI (Continuous Integration) roda build e testes. CD (Continuous Deployment) faz deploy automático em produção.
Como proteger secrets?
Nunca commite secrets no código. Use secrets do GitHub Actions. Para auditoria, ative logs de segurança.