Next.js: CI/CD com GitHub Actions
Última atualização: 2026-08-26
CI/CD é como "piloto automático" para equipes de desenvolvimento — cada commit passa automaticamente por um portão de qualidade, e apenas o código aprovado é implantado no ambiente de produção.
1. O Que Você Vai Aprender
- Projetar um workflow completo do GitHub Actions: Lint → Test → Build → Deploy
- Executar testes simultaneamente no Node.js 18, 20 e 22 usando uma estratégia de matriz paralela
- Implantar automaticamente no Vercel via
vercel-action - Escrever um Dockerfile multi-estágio para construir uma imagem standalone de 358MB
- Gerenciar variáveis de ambiente do GitHub Secrets e implantações de PR Preview
2. Uma História Real de um Gerente Técnico
(1) Ponto Problemático: Implantação manual — ainda olhando para o terminal às 3 da manhã
Bob é o Líder Técnico da equipe TaskFlow, composta por cinco membros que mantêm uma plataforma SaaS com mais de 10.000 usuários. O processo de release toda sexta-feira é assim:
"Alice faz o merge do PR → Notifica Bob → Bob executa testes localmente → Clica manualmente em
vercel deploy --prodapós os testes passarem → Olha para o terminal por 10 minutos → Confirma que a implantação foi bem-sucedida → Envia uma mensagem para a equipe"
Na semana passada, Bob acidentalmente implantou uma versão desatualizada porque esqueceu de puxar o código mais recente antes do npm run build. Cinco minutos depois, os usuários não conseguiam fazer login, e levou mais 15 minutos para reverter as alterações. O atendimento ao cliente recebeu mais de 100 reclamações.
| Pontos Problemáticos | Impacto |
|---|---|
| Implantação Manual | Alta taxa de erro humano (30% dos releases têm problemas) |
| Sem teste de controle de acesso automatizado | Código com falhas ainda pode chegar à produção |
| Incompatibilidade de Ambiente | Executa localmente, mas lança erro em produção |
| Sem PR Preview | Não é possível ver os resultados antes do merge |
(2) Solução com GitHub Actions
Bob projetou três linhas de montagem automatizadas:
# Cada vez que PR → Lint + test + build automáticos
# Merge na main → Build Automatizado + Deploy no Vercel
# Todo dia de madrugada → Build Automatizado da Imagem Docker
(3) Resultados
| Dimensão | Implantação Manual | Automação CI/CD |
|---|---|---|
| Tempo para publicar | 30 minutos | 8 minutos |
| Erro humano | 30% | < 1% |
| Eficiência na Revisão de PR | Apenas Código | Código + URL de Preview |
| Frequência de Implantação | Uma vez por semana | 5 vezes por dia |
3. Fundamentos do GitHub Actions
Actions é a plataforma CI/CD integrada do GitHub que usa arquivos YAML para definir workflows.
graph LR
A[git push] --> B[GitHub Actions]
B --> C[Eventos Gatilho]
C --> D[Jobs Paralelos/Seriados]
D --> E[Steps Etapas]
E --> F[Componentes do Actions Market]
style B fill:#cce5ff
style D fill:#d4edda
| Conceito | Descrição | Exemplo |
|---|---|---|
| Workflow | Um arquivo YAML = Um processo de automação | .github/workflows/test.yml |
| Event | Evento que aciona o workflow | push, pull_request, schedule |
| Job | Um conjunto de etapas (que podem ser paralelas ou dependentes) | lint → test → deploy |
| Step | Um único comando ou Action | npm run lint, actions/checkout |
| Runner | Ambiente de Execução | ubuntu-latest, windows-latest |
(1) Estrutura do Arquivo de Workflow
# .github/workflows/ci.yml
name: Pipeline CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm run lint
test:
needs: [lint]
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['18', '20', '22']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
- run: npm run test:coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: .next/
4. test.yml: Testes em Matriz Paralela
graph TB
A[Git Push / PR] --> B[lint]
B --> C[test 18.x]
B --> D[test 20.x]
B --> E[test 22.x]
C --> F[build]
D --> F
E --> F
F --> G[Upload de Artefatos de Build]
style A fill:#cce5ff
style C fill:#d4edda
style D fill:#d4edda
style E fill:#d4edda
(1) test.yml Completo
# .github/workflows/test.yml
name: Suíte de Testes
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
name: Verificação Lint
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Instalar dependências
run: npm ci
- name: Verificação de tipo TypeScript
run: npx tsc --noEmit
- name: Verificação ESLint
run: npm run lint
- name: Verificação Prettier
run: npx prettier --check "src/**/*.{ts,tsx}"
unit-and-integration:
name: Testes Unitários e de Integração
needs: [lint]
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
node-version: ['18', '20', '22']
fail-fast: false
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: testdb
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Instalar dependências
run: npm ci
- name: Gerar cliente Prisma
run: npx prisma generate
- name: Executar migrações do banco de dados
run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Executar testes unitários
run: npm run test
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Executar testes de integração
run: npm run test:integration
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
- name: Fazer upload da cobertura
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
name: codecov-node-${{ matrix.node-version }}
e2e:
name: Testes E2E
needs: [lint]
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Instalar dependências
run: npm ci
- name: Instalar navegadores Playwright
run: npx playwright install --with-deps chromium
- name: Executar testes E2E
run: npx playwright test --project=chromium
env:
TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
build:
name: Verificação de Build
needs: [unit-and-integration]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: next-build
path: .next/
retention-days: 1
▶ Exemplo: Resultados do Teste em Matriz Paralela
# Saída do Console do GitHub Actions
Job: unit-and-integration (node-version: 18.x) ✓ 3m 12s
Job: unit-and-integration (node-version: 20.x) ✓ 2m 58s
Job: unit-and-integration (node-version: 22.x) ✓ 3m 05s
Resumo:
✓ lint (1 job) 0m 45s
✓ unit-and-integration (3 jobs) 3m 12s
✓ e2e (1 job) 4m 30s
✓ build (1 job) 1m 20s
5. deploy.yml: Implantação automática no Vercel
| Ambiente de Implantação | Condições de Gatilho | Destino |
|---|---|---|
| Preview | Criar/Atualizar PR | Implantar no Branch de Preview |
| Produção | Merge na main | Atualização do ambiente de produção |
| Staging | Tag de release | Validação pré-release |
(1) Configuração de Deploy no Vercel
# .github/workflows/deploy.yml
name: Implantar no Vercel
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
deploy-preview:
name: Implantar Preview
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Instalar Vercel CLI
run: npm install --global vercel@latest
- name: Puxar Ambiente Vercel
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
- name: Construir Artefatos do Projeto
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Implantar no Vercel Preview
run: |
vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} > deployment-url.txt
echo "PREVIEW_URL=$(cat deployment-url.txt)" >> $GITHUB_ENV
- name: Comentar URL de Preview no PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
🚀 **Implantação de Preview Pronta**
| Ambiente | URL |
|:-----------|:----|
| Preview | ${{ env.PREVIEW_URL }} |
| Branch | ${{ github.head_ref }} |
_Este comentário é atualizado automaticamente a cada push._
deploy-production:
name: Implantar Produção
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [deploy-preview]
runs-on: ubuntu-latest
timeout-minutes: 15
environment: production
steps:
- uses: actions/checkout@v4
- name: Instalar Vercel CLI
run: npm install --global vercel@latest
- name: Puxar Ambiente Vercel
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Construir Artefatos do Projeto
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Implantar no Vercel Produção
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Notificar sucesso da implantação
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "✅ Implantação em produção concluída: ${{ github.repository }}@${{ github.sha }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
6. Build de Imagem Docker (Multi-estágio, 358 MB)
Para implantações self-hosted, você precisa construir automaticamente imagens Docker no CI.
(1) Dockerfile Multi-estágio
# Dockerfile — Build de imagem standalone Next.js 16
# Fase 1: Instalação de Dependências (Usando Camada de Cache)
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production && \
npm cache clean --force
# Fase 2: Build (Gerar artefatos .next)
FROM node:20-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# Fase 3: Execução (Imagem minimizada ~358MB)
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=build /app/public ./public
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
(2) Action de Build Docker
# .github/workflows/docker.yml
name: Docker Build & Push
on:
push:
tags: ['v*']
schedule:
- cron: '0 2 * * 0' # Domingo de madrugada às 2h
jobs:
docker:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Configurar QEMU
uses: docker/setup-qemu-action@v3
- name: Configurar Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Fazer login no GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=short
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- name: Build e 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
▶ Exemplo: Saída do build da imagem Docker
# Log de Build
#1 [deps 1/1] RUN npm ci --only=production
#1 DONE 15.2s
#2 [build 1/4] COPY --from=deps /app/node_modules ./node_modules
#2 DONE 0.1s
#3 [build 2/4] COPY . .
#3 DONE 0.3s
#4 [build 3/4] RUN npm run build
#4 DONE 28.5s
#5 [runner 1/6] COPY --from=build /app/public ./public
#5 DONE 0.1s
#6 Exportando camadas
#6 DONE 3.2s
# Análise do Tamanho da Imagem
ghcr.io/myorg/taskflow:latest 358 MB
7. Variáveis de Ambiente e Gerenciamento de Secrets
graph TB
A[GitHub Secrets] --> B[Ambiente de Execução Actions]
B --> C[Vercel Token]
B --> D[URL do Banco de Dados]
B --> E[Chaves de API]
B --> F[Slack Webhook]
C --> G[Implantar no Vercel]
D --> H[Executar Teste]
E --> I[Injeção Durante a Construção]
F --> J[Aviso de Implantação]
style A fill:#cce5ff
style B fill:#d4edda
| Nome da Variável de Ambiente | Propósito | Origem |
|---|---|---|
VERCEL_TOKEN |
Autenticação da API Vercel | GitHub Secrets |
VERCEL_ORG_ID |
ID da Equipe Vercel | Painel Vercel |
VERCEL_PROJECT_ID |
ID do Projeto Vercel | Painel Vercel |
DATABASE_URL |
Conexão com Banco de Dados | GitHub Secrets |
CODECOV_TOKEN |
Upload de Cobertura | Site Codecov |
SLACK_WEBHOOK_URL |
Aviso de Implantação | Configuração do App Slack |
(1) Configurar GitHub Secrets
# Em GitHub Repository → Settings → Secrets and variables → Actions → Add
gh secret set VERCEL_TOKEN --body "seu-vercel-token"
gh secret set DATABASE_URL --body "postgresql://user:pass@host:5432/db"
gh secret set SLACK_WEBHOOK_URL --body "https://hooks.slack.com/services/..."
(2) Estratégia de Isolamento de Ambiente
# Sobrescrita de Variáveis em Diferentes Ambientes
jobs:
test:
env:
DATABASE_URL: postgresql://test:test@localhost:5432/testdb
NODE_ENV: test
deploy-preview:
environment: preview
env:
DATABASE_URL: ${{ secrets.PREVIEW_DATABASE_URL }}
NEXT_PUBLIC_API_URL: ${{ vars.PREVIEW_API_URL }}
deploy-production:
environment: production
env:
DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
NEXT_PUBLIC_API_URL: https://api.taskflow.io
8. Workflow de Implantação de PR Preview
PR Preview permite que desenvolvedores visualizem os efeitos de suas alterações antes do merge.
graph TB
A[Desenvolvedor Cria PR] --> B[Actions Aciona deploy-preview]
B --> C[Vercel Cria Implantação de Preview]
C --> D[Gerar URL de preview]
D --> E[Bot Comenta no PR Adiciona um link]
E --> F[O revisor faz Upload de Preview para verificação]
F -->|Aprovação| G[Merge na main]
G --> H[Actions Aciona deploy-production]
style A fill:#cce5ff
style F fill:#fff3cd
style H fill:#d4edda
▶ Exemplo: Workflow Completo de PR Preview + Limpeza
Saída:
Salve a configuração YAML acima no caminho de arquivo especificado. As configurações entrarão em vigor na próxima reinicialização do servidor.
# .github/workflows/preview.yml
name: PR Preview
on:
pull_request:
types: [opened, synchronize, closed]
jobs:
preview:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Implantar no Vercel Preview
id: deploy
run: |
npx vercel --token=${{ secrets.VERCEL_TOKEN }} \
--scope=${{ secrets.VERCEL_ORG_ID }} \
--confirm > preview-url.txt
echo "url=$(cat preview-url.txt)" >> $GITHUB_OUTPUT
- name: Comentar URL
uses: actions/github-script@v7
with:
script: |
const url = '${{ steps.deploy.outputs.url }}'
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `🚀 **Preview implantado**\n\n${url}\n\n_Commit: ${context.sha}_`
})
cleanup:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- name: Remover Vercel Preview
run: |
npx vercel remove \
taskflow-git-${GITHUB_HEAD_REF//\//-} \
--token=${{ secrets.VERCEL_TOKEN }} \
--yes --scope=${{ secrets.VERCEL_ORG_ID }} || true
Saída:
Seções: name, on, jobs.
9. Exemplo Completo: Pipeline CI/CD Completo do TaskFlow
# .github/workflows/full-pipeline.yml
# ============================================
# Linha de Montagem CI/CD Completa do TaskFlow
# ============================================
name: Pipeline Completo TaskFlow
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
release:
types: [published]
env:
NODE_VERSION: '20'
PNPM_VERSION: '9'
jobs:
# === Fase 1: Controle de Acesso de Qualidade ===
quality-gate:
name: Portão de Qualidade
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Verificação TypeScript
run: pnpm typecheck
- name: ESLint + Prettier
run: pnpm lint && pnpm format:check
- name: Testes unitários com cobertura
run: pnpm test:coverage
- name: Upload de cobertura
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
# === Fase 2: Testes de Integração ===
integration:
name: Testes de Integração
needs: [quality-gate]
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: taskflow
POSTGRES_PASSWORD: taskflow
POSTGRES_DB: taskflow_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: npx prisma generate
- run: npx prisma migrate deploy
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
- name: Testes de integração
run: pnpm test:integration
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
- name: Testes E2E
run: npx playwright install --with-deps chromium && pnpm test:e2e
env:
DATABASE_URL: postgresql://taskflow:taskflow@localhost:5432/taskflow_test
# === Fase 3: Build ===
build:
name: Construir Aplicação
needs: [integration]
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
- name: Construir imagem Docker
if: github.event_name == 'push'
uses: docker/build-push-action@v5
with:
context: .
load: true
tags: taskflow:ci-${{ github.sha }}
- name: Salvar saídas de build
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: |
.next/
public/
package.json
# === Fase 4: Implantação ===
deploy:
name: Implantar
needs: [build]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Implantar no Vercel
run: |
npx vercel deploy --prod \
--token=${{ secrets.VERCEL_TOKEN }} \
--scope=${{ secrets.VERCEL_ORG_ID }}
- name: Notificar Slack
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "✅ TaskFlow implantado em produção\nCommit: ${{ github.sha }}\nPor: ${{ github.actor }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Executar Lighthouse CI
run: npx lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_TOKEN }}
❓ Perguntas Frequentes
P: A cota gratuita do GitHub Actions é suficiente? R: O plano GitHub Free oferece 2.000 minutos por mês de tempo de execução do Actions (ilimitado para repositórios públicos). Um pipeline CI típico do Next.js leva cerca de 8–12 minutos por execução, então 2.000 minutos podem suportar aproximadamente 200 execuções por mês. Se precisar de mais, o GitHub Team oferece 3.000 minutos por mês, ou você pode configurar e auto-hospedar seus próprios runners.
P: Por que é necessário realizar testes em matriz em várias versões do Node.js? R: Seus usuários podem estar executando sua aplicação em várias versões do Node (Vercel usa 18.x, enquanto Docker pode usar 20.x ou 22.x). Testes em matriz garantem que seu código funcione corretamente em todas as versões suportadas do Node. O Next.js 16 suporta oficialmente Node 18.17 e posteriores; testar as três versões LTS mais recentes é a melhor prática.
P: Qual é melhor,
vercel-actionou a Vercel CLI? R:vercel-action(amondnet/vercel-action) encapsula operações comuns da CLI, mas as atualizações podem ser atrasadas. Recomendamos usar a Vercel CLI (npm install -g vercel) diretamente; usarrun: vercel deploy --prod --token=...no Actions oferece maior flexibilidade e garante que você tenha a versão mais recente.
P: Como posso proteger secrets contra vazamento? R: (1) Use GitHub Encrypted Secrets em vez de armazená-los em texto plano no YAML; (2) Desabilite a injeção automática de secrets para pull requests de forks (Settings → Actions → Fork pull request workflows); (3) Rotacione secrets regularmente; (4) Use
actions/secrets-scanningpara detectar commits acidentais.
P: Qual é a diferença entre PR Preview e o Preview padrão do Vercel? R: O Vercel cria automaticamente uma Implantação de Preview para cada PR (integrado com Git), mas você precisa fazer login no Painel Vercel para ver a URL. Ao implantar manualmente via GitHub Actions e comentar a URL no PR, os membros da equipe podem clicar para acessar diretamente da página do PR, o que proporciona uma experiência melhor.
P: Como posso otimizar um pipeline CI lento? R: (1) Use
actions/cachepara fazer cache denode_modulese.next/cache; (2) Execute jobs independentes em paralelo; (3) Usefail-fast: falsepara evitar que uma falha em uma única versão cause o cancelamento de todo o pipeline; (4) Use pnpm em vez de npm (para instalação mais rápida); (5) Auto-hospede um runner (se o repositório for grande).
📖 Resumo
- Workflows do GitHub Actions consistem em uma estrutura de três níveis: Event → Jobs → Steps. Os arquivos YAML estão localizados em
.github/workflows/. strategy.matriximplementa testes paralelos para Node 18/20/22 para verificar compatibilidade em várias versões LTS simultaneamente- O comando
vercel deploy --prodpode ser integrado ao Actions para habilitar implantação automatizada; PR Preview é acessível via URL de comentário doactions/github-script - Um build Docker multi-estágio (deps → build → runner) mantém o tamanho da imagem em ~358MB;
output: 'standalone'é um pré-requisito. - GitHub Secrets armazenam variáveis sensíveis de forma segura, e o campo
environmentpermite isolamento de ambiente para desenvolvimento, preview e produção - Três Estratégias Principais para Otimização de CI: Cache de Dependências, Paralelização de Jobs e Uso de pnpm em Vez de npm
📝 Exercícios
-
Problema Básico (⭐): Crie um
.github/workflows/ci.ymlque contenha três jobs seriais — Lint, Test e Build — e acione-o sempre quepushfizer a transição paramain. -
Exercício Avançado (⭐⭐): Configure um pipeline completo de implantação automatizada no Vercel para seu projeto: (1) Configure
VERCEL_TOKENno GitHub Secrets; (2) Escrevadeploy.ymlpara implementar PR Preview e implantação em produção; (3) Verifique se a URL de Preview aparece nos comentários do PR. -
Desafio (⭐⭐⭐): Implemente um pipeline CI/CD multi-ambiente (dev → staging → production): (1) Cada ambiente tem seu próprio banco de dados e secrets; (2) O branch dev é automaticamente implantado no ambiente dev; (3) O branch main é automaticamente implantado no staging; (4) A implantação em produção requer aprovação manual; (5) Notifique um canal Slack via webhook após uma implantação bem-sucedida.