Pular para o conteúdo principal

Pipeline de Deploy - Web

Repositório: conceito-sankhya/force-web
Última atualização: 22 de outubro de 2025

Visão Geral

Sistema automatizado de CI/CD para o Web implementado através de GitHub Actions, garantindo build, testes, versionamento e deploy contínuo na AWS Elastic Beanstalk. O pipeline é dividido em duas workflows principais: validação em Pull Requests e deploy em produção.

Workflows Disponíveis

WorkflowArquivoTriggerPropósito
Validação de Buildbuild-check.ymlPull RequestValida que o código compila antes de fazer merge
Build, Release e Deploymain.ymlPush na mainCompila, cria release no GitHub e faz deploy na AWS

Workflow 1: Validação de Build (Pull Request)

Configuração e Triggers

name: Validate Build on Pull Request

on:
pull_request:
branches:
- dev

Quando executa: Toda vez que um Pull Request é aberto ou atualizado com destino à branch dev.

Objetivo: Garantir que o código proposto não quebra o build antes do merge.


Etapas do Processo

1. Setup do Ambiente

StepAçãoDetalhes
Checkout RepositoryClona o repositórioUsa fetch-depth: 1 para clonar apenas o último commit
Set up Node.jsConfigura Node.js versão 22Utiliza cache do npm para acelerar instalações
Cache node_modulesCache de dependências e buildArmazena ~/.npm, node_modules e .next/cache

Estratégia de Cache

key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-
${{ runner.os }}-node-

O cache considera:

  • Sistema operacional do runner
  • Hash do package-lock.json (detecta mudanças em dependências)
  • Hash de todos os arquivos de código (detecta mudanças no código)

2. Instalação de Dependências

npm ci --prefer-offline --no-audit --no-fund

Por que npm ci?

  • ✅ Instalação mais rápida em ambientes CI
  • ✅ Garante instalação exata baseada no package-lock.json
  • ✅ Remove node_modules existente antes de instalar
  • ✅ Flags otimizadas: --prefer-offline, --no-audit, --no-fund

3. Build do Projeto

NODE_ENV=production npm run build

Variáveis de Ambiente:

VariávelValorPropósito
NODE_ENVproductionAtiva otimizações de produção
NEXT_TELEMETRY_DISABLED1Desabilita telemetria do Next.js
NODE_OPTIONS--max-old-space-size=4096Aloca até 4GB de memória para o build

4. Validação do Build

# Verifica se o diretório .next foi criado
if [ ! -d ".next" ]; then
echo "❌ Build failed: .next directory not found"
exit 1
fi

# Verifica se o BUILD_ID foi gerado
if [ ! -f ".next/BUILD_ID" ]; then
echo "❌ Build failed: BUILD_ID not found"
exit 1
fi

echo "✅ Build completed successfully"
echo "📁 Build size:"
du -sh .next/

Validações realizadas:

  • ✅ Diretório .next existe
  • ✅ Arquivo .next/BUILD_ID foi gerado
  • ✅ Exibe tamanho do build

Workflow 2: Build, Release e Deploy (Main)

Configuração e Triggers

name: Build and Deploy ForceWeb

on:
push:
branches:
- main
paths:
- "package.json"

Quando executa: Apenas quando há push na branch main E o arquivo package.json foi modificado.

Estratégia de Deploy

O deploy só acontece quando há mudanças na versão do projeto (alterações no package.json), evitando deploys desnecessários.


Variáveis de Ambiente Globais

env:
NODE_VERSION: "18"
AWS_REGION: "sa-east-1"
APP_NAME: "force-web-env-1"
ENV_NAME: "force-web-env-1"
NODE_OPTIONS: "--max_old_space_size=6144"
VariávelValorUso
NODE_VERSION18Versão do Node.js para build e deploy
AWS_REGIONsa-east-1Região AWS (São Paulo)
APP_NAMEforce-web-env-1Nome da aplicação no Elastic Beanstalk
ENV_NAMEforce-web-env-1Nome do ambiente no Elastic Beanstalk
NODE_OPTIONS--max_old_space_size=6144Aloca até 6GB de memória para o build

Job 1: Build Application

Outputs do Job

outputs:
version: ${{ steps.package_version.outputs.version }}
artifact_name: ${{ steps.package_version.outputs.artifact_name }}

Estes outputs são compartilhados com os jobs release e deploy.


Etapas Detalhadas

1. Setup e Preparação
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Clona histórico completo para tags
2. Verificação do Package Lock
if [ ! -f package-lock.json ]; then
echo "⚠️ package-lock.json not found. Running npm install to generate it..."
npm install --package-lock-only
fi

Garante que o package-lock.json existe, gerando-o se necessário.


3. Auditoria de Segurança
npm audit --audit-level=high
  • Verifica vulnerabilidades de segurança nas dependências
  • --audit-level=high: Apenas vulnerabilidades de severidade alta ou crítica
  • continue-on-error: true: Não falha o build, apenas reporta

4. Execução de Testes
if npm run | grep -q "test"; then
npm run test -- --passWithNoTests
else
echo "No tests found, skipping..."
fi
  • Verifica se existe script de teste no package.json
  • Executa testes se disponíveis
  • --passWithNoTests: Não falha se não houver testes
  • continue-on-error: true: Build continua mesmo se testes falharem

5. Build da Aplicação
NODE_ENV=production npm run build

Configurações:

  • NODE_ENV=production: Otimizações de produção
  • NODE_OPTIONS=--max_old_space_size=6144: 6GB de memória

6. Extração da Versão
VERSION=$(jq -r '.version' package.json)
ARTIFACT_NAME="ForceWeb${VERSION}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "artifact_name=${ARTIFACT_NAME}" >> $GITHUB_OUTPUT

Exemplo de saída:

  • Versão: 2.5.3
  • Nome do artefato: ForceWeb2.5.3

7. Criação do Pacote de Deploy
Script Completo de Empacotamento
echo "🗂️ Creating deployment package for Next.js..."

# Listar estrutura atual
echo "📁 Current directory structure:"
ls -la

# Verificar se .next existe (crítico para Next.js)
if [ ! -d ".next" ]; then
echo "❌ ERROR: .next directory not found! Build may have failed."
exit 1
fi

echo "✅ .next directory found with size: $(du -sh .next | cut -f1)"

# Criar ZIP com arquivos necessários
echo "📦 Creating ZIP package..."
zip -r "${{ steps.package_version.outputs.artifact_name }}.zip" \
.platform \
.next \
pages \
public \
styles \
package.json \
package-lock.json \
next.config.js \
tsconfig.json \
-x "node_modules/*" "*.git*" "*.log" ".env*" "coverage/*" "*.test.*"

# Verificar criação do ZIP
if [ -f "${{ steps.package_version.outputs.artifact_name }}.zip" ]; then
echo "✅ ZIP created successfully!"
echo "📊 ZIP size: $(du -sh ${{ steps.package_version.outputs.artifact_name }}.zip | cut -f1)"
echo ""
echo "📋 ZIP contents:"
unzip -l "${{ steps.package_version.outputs.artifact_name }}.zip" | head -30
else
echo "❌ ERROR: Failed to create ZIP file!"
exit 1
fi

Arquivos Incluídos no Pacote

Arquivo/DiretórioDescriçãoObrigatório
.platform/Configurações AWS Elastic Beanstalk✅ Sim
.next/Build otimizado do Next.js✅ Sim
pages/Páginas da aplicação✅ Sim
public/Assets estáticos✅ Sim
styles/Arquivos CSS/SCSS✅ Sim
package.jsonDependências e scripts✅ Sim
package-lock.jsonLock de versões de dependências✅ Sim
next.config.jsConfigurações do Next.js✅ Sim
tsconfig.jsonConfigurações do TypeScript✅ Sim

Arquivos Excluídos

-x "node_modules/*" "*.git*" "*.log" ".env*" "coverage/*" "*.test.*"
  • node_modules/*: Dependências serão instaladas no servidor
  • *.git*: Arquivos do Git
  • *.log: Arquivos de log
  • .env*: Variáveis de ambiente sensíveis
  • coverage/*: Relatórios de cobertura de testes
  • *.test.*: Arquivos de teste

8. Upload do Artefato
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.package_version.outputs.artifact_name }}
path: ${{ steps.package_version.outputs.artifact_name }}.zip
retention-days: 30
compression-level: 6

Configurações:

  • retention-days: 30: Artefato fica disponível por 30 dias
  • compression-level: 6: Nível médio de compressão (balanço entre tamanho e velocidade)

Job 2: Create GitHub Release

Dependências: Requer que o job build seja concluído com sucesso.

needs: build

Etapas do Release

1. Download do Artefato
- name: Download Build Artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.artifact_name }}
path: .

Baixa o artefato criado no job anterior.


2. Criação do Release no GitHub
- name: Create GitHub Release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: V${{ needs.build.outputs.version }}
name: ForceWeb V${{ needs.build.outputs.version }}
files: ${{ needs.build.outputs.artifact_name }}.zip
draft: false
prerelease: false
generate_release_notes: true

Estrutura do Release

Tag: V2.5.3 (exemplo)

Título: ForceWeb V2.5.3

Corpo da Release:

## 🚀 ForceWeb Release V2.5.3

**Branch:** `main`
**Commit:** abc123def456...
**Build Date:** 2025-10-22T14:30:00Z

### Changes

feat: Implementação de nova funcionalidade X

### Build Info

- ✅ Built with Node.js 18
- ✅ Memory allocation: --max_old_space_size=6144
- ✅ Target Region: sa-east-1
- 📦 Artifact: ForceWeb2.5.3.zip

---

_Auto-generated from main branch_

Anexos:

  • ForceWeb2.5.3.zip (pacote completo de deploy)

Job 3: Deploy to AWS

Dependências: Requer que os jobs build e release sejam concluídos.

needs: [build, release]

Etapas do Deploy

1. Download e Verificação do Artefato
echo "📦 Downloaded artifact: ForceWeb2.5.3.zip"
ls -la ForceWeb2.5.3.zip
echo "Size: $(du -h ForceWeb2.5.3.zip | cut -f1)"

2. Deploy no AWS Elastic Beanstalk
- name: Deploy to AWS Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v22
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY }}
aws_secret_key: ${{ secrets.AWS_SECRET_KEY }}
application_name: ${{ env.APP_NAME }}
environment_name: ${{ env.ENV_NAME }}
version_label: ${{ needs.build.outputs.version }}_${{ github.run_number }}
region: ${{ env.AWS_REGION }}
deployment_package: ${{ needs.build.outputs.artifact_name }}.zip
wait_for_deployment: true
wait_for_environment_recovery: 300
use_existing_version_if_available: false

Parâmetros de Deploy

ParâmetroValor/FonteDescrição
aws_access_keysecrets.AWS_ACCESS_KEYChave de acesso AWS (configurada nos secrets)
aws_secret_keysecrets.AWS_SECRET_KEYChave secreta AWS (configurada nos secrets)
application_nameforce-web-env-1Nome da aplicação no Elastic Beanstalk
environment_nameforce-web-env-1Nome do ambiente a ser atualizado
version_label2.5.3_123 (versão + número do run)Identificador único da versão
regionsa-east-1Região AWS (São Paulo)
deployment_packageForceWeb2.5.3.zipCaminho do pacote de deploy
wait_for_deploymenttrueAguarda conclusão do deploy antes de finalizar
wait_for_environment_recovery300Aguarda até 5 minutos pela recuperação do ambiente
use_existing_version_if_availablefalseSempre cria nova versão, mesmo se já existir

3. Notificações de Deploy

Em caso de sucesso:

echo "🎉 ForceWeb Deployment Successful!"
echo "Version: 2.5.3"
echo "Environment: force-web-env-1"
echo "Region: sa-east-1"
echo "Version Label: 2.5.3_123"

Em caso de falha:

echo "❌ ForceWeb Deployment Failed!"
echo "Please check the logs above for details."
echo "Version attempted: 2.5.3"
exit 1

Job 4: Finally (Cleanup e Status)

Dependências: Executa sempre, independente do resultado dos outros jobs.

needs: [build, release, deploy]
if: always()
echo "Build status: success"
echo "Release status: success"
echo "Deploy status: success"

Secrets Necessários

Configure os seguintes secrets no GitHub (Settings → Secrets and variables → Actions):

SecretDescriçãoOnde obter
AWS_ACCESS_KEYChave de acesso da AWSAWS IAM Console
AWS_SECRET_KEYChave secreta da AWSAWS IAM Console
GITHUB_TOKENToken de acesso ao GitHubFornecido automaticamente pelo GitHub
Segurança

Nunca commite credenciais no código. Sempre use GitHub Secrets para armazenar informações sensíveis.


Fluxograma do Pipeline


Troubleshooting

Build Falha: ".next directory not found"

Problema: O diretório .next não foi criado após o build.

Soluções:

  1. Verifique se há erros de compilação no código
  2. Confirme que o comando npm run build está correto no package.json
  3. Verifique se há problemas de memória (aumentar NODE_OPTIONS)

Deploy Falha: "Version already exists"

Problema: Tentativa de deploy com versão já existente no Elastic Beanstalk.

Soluções:

  1. Incremente a versão no package.json
  2. Verifique se use_existing_version_if_available: false está configurado
  3. Delete a versão antiga manualmente no console AWS (se necessário)

Erro: "AWS credentials not found"

Problema: Secrets da AWS não estão configurados corretamente.

Soluções:

  1. Verifique se AWS_ACCESS_KEY e AWS_SECRET_KEY estão nos Secrets do GitHub
  2. Confirme que as credenciais têm permissões adequadas no IAM
  3. Teste as credenciais localmente com AWS CLI

Pull Request Check Falha

Problema: Validação de build falha em PR.

Soluções:

  1. Execute npm run build localmente para reproduzir o erro
  2. Verifique logs da action para identificar o erro específico
  3. Confirme que todas as dependências estão no package.json
  4. Limpe cache e tente novamente

Referências