Preview environments: deploy automático de PRs para review
1. O que são Preview Environments e por que usá-las?
Preview environments (ou ambientes de pré-visualização) são ambientes efêmeros e isolados criados automaticamente a partir de um Pull Request (PR) no Git. Cada branch de feature, ao ter seu PR aberto, gera um ambiente completo onde a aplicação é deployada e pode ser acessada por revisores, testadores e stakeholders.
Os benefícios são diretos:
- Revisão visual: o revisor não precisa baixar o branch e rodar localmente; ele acessa uma URL e vê as mudanças em tempo real.
- Testes integrados: testes de integração e aceitação podem rodar contra o ambiente preview antes do merge.
- Feedback rápido: designers, product managers e QA podem interagir com a funcionalidade sem depender de desenvolvedores.
- Isolamento total: cada preview é independente; falhas em um não afetam outros ambientes nem a produção.
A relação com Git é intrínseca: cada branch de PR vira um ambiente isolado. O commit SHA, a branch e a URL do preview formam um vínculo rastreável dentro do repositório.
2. Estrutura de branches e gatilhos no Git
A estrutura básica de branches para preview environments segue este padrão:
main (ou develop) → branch estável, base para produção
feature/* → branches de funcionalidade, cada uma vira um preview
Os gatilhos no Git que disparam a criação e destruição dos ambientes são eventos do PR:
- push: quando um novo commit é enviado para a branch do PR, o preview é atualizado.
- pull_request (aberto): quando o PR é criado, o preview é gerado.
- pull_request (sincronizado): quando o branch do PR recebe novos commits, o preview é recriado.
- pull_request (reaberto): quando um PR fechado é reaberto, o preview é restaurado.
- pull_request (fechado): quando o PR é mergeado ou fechado sem merge, o preview é destruído.
No GitHub Actions, esses gatilhos são configurados assim:
on:
pull_request:
types: [opened, synchronize, reopened, closed]
3. Configuração do deploy automático com Git e CI/CD
Vamos a um exemplo prático usando GitHub Actions. O workflow abaixo cria um preview environment para cada PR:
name: Deploy Preview
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout do branch do PR
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Build da aplicação
run: |
npm install
npm run build
- name: Deploy para preview
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
BRANCH_NAME=${{ github.head_ref }}
COMMIT_SHA=${{ github.sha }}
URL="https://pr-${PR_NUMBER}.meuapp.com"
echo "Deployando preview para $URL"
# Comando real de deploy (ex: AWS S3, Vercel, Netlify)
./deploy-preview.sh $PR_NUMBER $BRANCH_NAME $COMMIT_SHA
- name: Comentar URL no PR
uses: actions/github-script@v7
with:
script: |
const url = `https://pr-${context.payload.pull_request.number}.meuapp.com`;
github.rest.issues.createComment({
issue_number: context.payload.pull_request.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🔍 Preview disponível em: ${url}`
});
O mapeamento entre commit SHA, branch e URL é essencial para rastreabilidade. Armazene esse mapeamento em um arquivo ou variável de ambiente:
# mapping.txt
pr-42,feature/login,abc123,https://pr-42.meuapp.com
pr-43,feature/logout,def456,https://pr-43.meuapp.com
4. Gerenciamento de ambientes com Git tags e commits
Tags temporárias ajudam a identificar versões do preview. A cada push no PR, a tag é atualizada:
# Criar ou atualizar tag para o preview
git tag -f preview/pr-42 ${{ github.sha }}
git push origin preview/pr-42 --force
Ao fechar o PR, a tag é removida:
# Remover tag do preview
git push origin --delete preview/pr-42
Isso mantém o repositório limpo e permite consultar rapidamente qual commit está em qual preview.
5. Estratégias de nomenclatura e roteamento
A nomenclatura deve ser única e previsível. Exemplos:
pr-42 → preview do PR número 42
feature-login → baseado no nome do branch (substituindo / por -)
Subdomínios dinâmicos são a abordagem mais comum:
https://pr-42.meuapp.com
https://feature-login.meuapp.com
Para registrar URLs automaticamente, use hooks pós-recebe (post-receive) no servidor Git:
#!/bin/bash
# .git/hooks/post-receive
while read oldrev newrev refname
do
if [[ $refname =~ refs/heads/feature/ ]]; then
BRANCH=${refname#refs/heads/}
PR_NUMBER=$(echo $BRANCH | grep -oP 'feature/\K\d+')
URL="https://pr-${PR_NUMBER}.meuapp.com"
echo "Preview URL: $URL"
# Atualiza serviço de DNS ou roteador
fi
done
6. Integração com revisão de código e testes
O link do preview deve aparecer automaticamente no comentário do PR. No GitHub Actions, usamos a API do GitHub:
- name: Comentar preview no PR
uses: actions/github-script@v7
with:
script: |
const url = `https://pr-${context.payload.pull_request.number}.meuapp.com`;
github.rest.issues.createComment({
issue_number: context.payload.pull_request.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🔍 Preview: ${url}\n✅ Testes: ${process.env.TEST_STATUS}`
});
Para bloquear o merge se o preview falhar, configure status checks no repositório Git:
# No GitHub, vá em Settings > Branches > Branch protection rules
# Marque "Require status checks to pass before merging"
# Adicione "preview-deploy" e "preview-tests" como checks obrigatórios
No workflow, o status check é atualizado automaticamente:
- name: Atualizar status check
uses: actions/github-script@v7
with:
script: |
github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'preview-deploy',
head_sha: context.sha,
status: 'completed',
conclusion: 'success' // ou 'failure'
});
7. Limpeza e ciclo de vida dos ambientes
A remoção automática ao mergear ou fechar o PR é crítica para evitar acúmulo de recursos:
name: Cleanup Preview
on:
pull_request:
types: [closed]
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Remover preview
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
echo "Removendo preview do PR #$PR_NUMBER"
# Comando real de remoção (ex: deletar bucket S3, remover subdomínio)
./destroy-preview.sh $PR_NUMBER
- name: Remover tag Git
run: |
git push origin --delete preview/pr-${{ github.event.pull_request.number }} || true
Para ambientes abandonados (PRs esquecidos), implemente expiração por TTL:
# Script de cron que roda diariamente
for PR in $(list_all_previews); do
CREATED_AT=$(get_preview_creation_time $PR)
AGE_DAYS=$(( ( $(date +%s) - $CREATED_AT ) / 86400 ))
if [ $AGE_DAYS -gt 7 ]; then
echo "Removendo preview expirado: $PR"
destroy_preview $PR
fi
done
8. Boas práticas e armadilhas comuns
Evitar dados sensíveis: use variáveis de ambiente separadas para previews, nunca exponha credenciais de produção.
# .env.preview
DATABASE_URL=sqlite:///preview.db
API_KEY=preview-key-123
Gerenciar recursos: limite o número de ambientes simultâneos para evitar custos excessivos.
MAX_PREVIEWS=10
CURRENT_PREVIEWS=$(count_active_previews)
if [ $CURRENT_PREVIEWS -ge $MAX_PREVIEWS ]; then
echo "Limite de previews atingido. Remova um preview existente."
exit 1
fi
Versionamento de configurações: mantenha todos os scripts de deploy no repositório Git, versionados junto com o código.
repo/
├── .github/
│ └── workflows/
│ ├── deploy-preview.yml
│ └── cleanup-preview.yml
├── scripts/
│ ├── deploy-preview.sh
│ ├── destroy-preview.sh
│ └── list-previews.sh
└── .env.preview
Armadilhas comuns:
- Cache de build: sempre faça builds limpos para cada preview, evitando cache de branches anteriores.
- Concorrência: se dois pushes ocorrerem simultaneamente no mesmo PR, o último vence; implemente locks ou filas.
- Recursos compartilhados: prefira bancos de dados efêmeros (ex: SQLite em memória) ou instâncias isoladas por preview.
Referências
- GitHub Docs: Using environments for deployment — Documentação oficial sobre ambientes de deploy no GitHub Actions, incluindo preview environments.
- Netlify Deploy Previews — Tutorial completo sobre preview environments com Netlify, integração com Git e PRs.
- Vercel Preview Deployments — Guia oficial da Vercel para criar previews automáticos a partir de branches e PRs.
- GitLab Review Apps — Documentação do GitLab sobre Review Apps, ambientes efêmeros por branch com CI/CD.
- Atlassian: Pull request preview environments — Artigo técnico sobre boas práticas para preview environments em fluxos Git-based.