chore: update deploy workflow and frontend Dockerfile
This commit is contained in:
parent
808ef3524f
commit
1058b7005f
2 changed files with 111 additions and 78 deletions
|
|
@ -9,6 +9,10 @@ on:
|
||||||
- 'backoffice/**'
|
- 'backoffice/**'
|
||||||
- 'frontend/**'
|
- 'frontend/**'
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: rg.fr-par.scw.cloud
|
||||||
|
NAMESPACE: gohorsejobs
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Job 1: Testes do Backend (Padrão GoHorse)
|
# Job 1: Testes do Backend (Padrão GoHorse)
|
||||||
test-backend:
|
test-backend:
|
||||||
|
|
@ -35,14 +39,83 @@ jobs:
|
||||||
go test -v ./internal/services/...
|
go test -v ./internal/services/...
|
||||||
go test -v ./internal/core/usecases/...
|
go test -v ./internal/core/usecases/...
|
||||||
|
|
||||||
# Job 2: Deploy com Proteção de I/O e RAM
|
# Job 2: Build e Push das Imagens para Scaleway Registry
|
||||||
deploy-dev:
|
build-and-push:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [test-backend]
|
needs: [test-backend]
|
||||||
# Executa se o teste passar OU se o teste foi pulado (mudança só no front/backoffice)
|
|
||||||
if: always() && (needs.test-backend.result == 'success' || needs.test-backend.result == 'skipped')
|
if: always() && (needs.test-backend.result == 'success' || needs.test-backend.result == 'skipped')
|
||||||
|
outputs:
|
||||||
|
backend_updated: ${{ steps.check.outputs.backend }}
|
||||||
|
frontend_updated: ${{ steps.check.outputs.frontend }}
|
||||||
|
backoffice_updated: ${{ steps.check.outputs.backoffice }}
|
||||||
steps:
|
steps:
|
||||||
- name: Executar Deploy via SSH na Apolo
|
- name: Checkout code
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- name: Check changed files
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
if git diff --name-only HEAD~1 HEAD | grep -q "^backend/"; then
|
||||||
|
echo "backend=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "backend=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
if git diff --name-only HEAD~1 HEAD | grep -q "^frontend/"; then
|
||||||
|
echo "frontend=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "frontend=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
if git diff --name-only HEAD~1 HEAD | grep -q "^backoffice/"; then
|
||||||
|
echo "backoffice=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "backoffice=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Login to Scaleway Registry
|
||||||
|
run: |
|
||||||
|
echo "${{ secrets.SCW_SECRET_KEY }}" | docker login ${{ env.REGISTRY }} -u nologin --password-stdin
|
||||||
|
|
||||||
|
- name: Build and Push Backend
|
||||||
|
if: steps.check.outputs.backend == 'true'
|
||||||
|
run: |
|
||||||
|
docker build -t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-${{ github.sha }} \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-latest \
|
||||||
|
./backend
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-${{ github.sha }}
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-latest
|
||||||
|
|
||||||
|
- name: Build and Push Frontend
|
||||||
|
if: steps.check.outputs.frontend == 'true'
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
--build-arg NODE_OPTIONS="--max-old-space-size=2048" \
|
||||||
|
--build-arg NEXT_PUBLIC_API_URL="${{ secrets.API_URL }}" \
|
||||||
|
--build-arg NEXT_PUBLIC_BACKOFFICE_URL="${{ secrets.BACKOFFICE_URL }}" \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-${{ github.sha }} \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-latest \
|
||||||
|
./frontend
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-${{ github.sha }}
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-latest
|
||||||
|
|
||||||
|
- name: Build and Push Backoffice
|
||||||
|
if: steps.check.outputs.backoffice == 'true'
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-${{ github.sha }} \
|
||||||
|
-t ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-latest \
|
||||||
|
./backoffice
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-${{ github.sha }}
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-latest
|
||||||
|
|
||||||
|
# Job 3: Deploy no Servidor (Pull das imagens do Scaleway)
|
||||||
|
deploy-dev:
|
||||||
|
runs-on: docker
|
||||||
|
needs: [build-and-push]
|
||||||
|
if: always() && needs.build-and-push.result == 'success'
|
||||||
|
steps:
|
||||||
|
- name: Deploy via SSH
|
||||||
uses: https://github.com/appleboy/ssh-action@v1.0.3
|
uses: https://github.com/appleboy/ssh-action@v1.0.3
|
||||||
with:
|
with:
|
||||||
host: ${{ secrets.HOST }}
|
host: ${{ secrets.HOST }}
|
||||||
|
|
@ -50,59 +123,33 @@ jobs:
|
||||||
key: ${{ secrets.SSH_KEY }}
|
key: ${{ secrets.SSH_KEY }}
|
||||||
port: ${{ secrets.PORT || 22 }}
|
port: ${{ secrets.PORT || 22 }}
|
||||||
script: |
|
script: |
|
||||||
cd /mnt/data/gohorsejobs
|
# Login no Scaleway Registry
|
||||||
git fetch origin
|
echo "${{ secrets.SCW_SECRET_KEY }}" | podman login ${{ env.REGISTRY }} -u nologin --password-stdin
|
||||||
git checkout dev
|
|
||||||
git pull origin dev
|
|
||||||
|
|
||||||
# --- PREPARAÇÃO DO AMBIENTE ---
|
|
||||||
# 1. Cria diretório temporário na RAM para evitar escritas no SSD (vda3)
|
|
||||||
mkdir -p /tmp/podman-build
|
|
||||||
export TMPDIR=/tmp/podman-build
|
|
||||||
|
|
||||||
# 2. Força o kernel a liberar cache e finalizar escritas pendentes para baixar o Load
|
|
||||||
sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
|
|
||||||
|
|
||||||
# --- DEPLOY DO BACKEND ---
|
# --- DEPLOY DO BACKEND ---
|
||||||
if git diff --name-only HEAD@{1} HEAD | grep -q "^backend/"; then
|
if [ "${{ needs.build-and-push.outputs.backend_updated }}" == "true" ]; then
|
||||||
echo "Iniciando Build Backend (CPU: 50%)..."
|
echo "Pulling e reiniciando Backend..."
|
||||||
nice -n 19 ionice -c 3 podman build \
|
podman pull ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-latest
|
||||||
--cpu-quota 50000 \
|
podman tag ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backend:dev-latest localhost/gohorsejobs-backend-dev:latest
|
||||||
--memory 1024m \
|
|
||||||
-t localhost/gohorsejobs-backend-dev:latest ./backend
|
|
||||||
sudo systemctl restart gohorsejobs-backend-dev
|
sudo systemctl restart gohorsejobs-backend-dev
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- DEPLOY DO BACKOFFICE ---
|
# --- DEPLOY DO FRONTEND ---
|
||||||
if git diff --name-only HEAD@{1} HEAD | grep -q "^backoffice/"; then
|
if [ "${{ needs.build-and-push.outputs.frontend_updated }}" == "true" ]; then
|
||||||
echo "Iniciando Build Backoffice (CPU: 30%)..."
|
echo "Pulling e reiniciando Frontend..."
|
||||||
nice -n 19 ionice -c 3 podman build \
|
podman pull ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-latest
|
||||||
--cpu-quota 30000 \
|
podman tag ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/frontend:dev-latest localhost/gohorsejobs-frontend-dev:latest
|
||||||
--memory 2048m \
|
|
||||||
-t localhost/gohorsejobs-backoffice-dev:latest ./backoffice
|
|
||||||
sudo systemctl restart gohorsejobs-backoffice-dev
|
|
||||||
fi
|
|
||||||
|
|
||||||
# --- DEPLOY DO FRONTEND (Foco em sobrevivência do disco) ---
|
|
||||||
if git diff --name-only HEAD@{1} HEAD | grep -q "^frontend/"; then
|
|
||||||
echo "Iniciando Build Frontend (CPU: 20%, RAM: 3G)..."
|
|
||||||
# ionice -c 3 garante que o build não roube I/O do banco de dados
|
|
||||||
# NODE_OPTIONS aumenta a RAM disponível para o build não dar swap
|
|
||||||
# --no-cache garante que o Next.js rebuild com os novos valores de env
|
|
||||||
nice -n 19 ionice -c 3 podman build \
|
|
||||||
--cpu-quota 20000 \
|
|
||||||
--memory 3072m \
|
|
||||||
--no-cache \
|
|
||||||
--build-arg NODE_OPTIONS="--max-old-space-size=2048" \
|
|
||||||
--build-arg NEXT_PUBLIC_API_URL="${{ secrets.API_URL || 'http://backend:8080' }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_BACKOFFICE_URL="${{ secrets.BACKOFFICE_URL || 'http://backoffice:3001' }}" \
|
|
||||||
-t localhost/gohorsejobs-frontend-dev:latest ./frontend
|
|
||||||
sudo systemctl restart gohorsejobs-frontend-dev
|
sudo systemctl restart gohorsejobs-frontend-dev
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- LIMPEZA FINAL ---
|
# --- DEPLOY DO BACKOFFICE ---
|
||||||
echo "Limpando caches e sincronizando disco..."
|
if [ "${{ needs.build-and-push.outputs.backoffice_updated }}" == "true" ]; then
|
||||||
rm -rf /tmp/podman-build/*
|
echo "Pulling e reiniciando Backoffice..."
|
||||||
podman image prune -f
|
podman pull ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-latest
|
||||||
podman builder prune -f
|
podman tag ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/backoffice:dev-latest localhost/gohorsejobs-backoffice-dev:latest
|
||||||
sync
|
sudo systemctl restart gohorsejobs-backoffice-dev
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- LIMPEZA ---
|
||||||
|
echo "Limpando imagens antigas..."
|
||||||
|
podman image prune -f
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# GoHorse Jobs Frontend - Ultra-Optimized Dockerfile with pnpm
|
# GoHorse Jobs Frontend - Ultra-Optimized Dockerfile
|
||||||
# Target: < 150MB final image, minimal disk usage during build
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
|
@ -8,11 +7,7 @@
|
||||||
# Stage 1: Base with pnpm
|
# Stage 1: Base with pnpm
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
FROM mirror.gcr.io/library/node:20-alpine AS base
|
FROM mirror.gcr.io/library/node:20-alpine AS base
|
||||||
|
|
||||||
# Enable corepack and activate pnpm (latest)
|
|
||||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
# Set pnpm store for caching
|
|
||||||
ENV PNPM_HOME="/pnpm"
|
ENV PNPM_HOME="/pnpm"
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
|
||||||
|
|
@ -20,34 +15,27 @@ ENV PATH="$PNPM_HOME:$PATH"
|
||||||
# Stage 2: Dependencies
|
# Stage 2: Dependencies
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
FROM base AS deps
|
FROM base AS deps
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy package files (pnpm will use package-lock.json if no pnpm-lock.yaml)
|
|
||||||
COPY package.json package-lock.json* pnpm-lock.yaml* ./
|
COPY package.json package-lock.json* pnpm-lock.yaml* ./
|
||||||
|
|
||||||
# Install deps with cache mount - dramatically reduces disk usage on rebuilds
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
pnpm import 2>/dev/null || true && \
|
pnpm import 2>/dev/null || true && \
|
||||||
pnpm install --frozen-lockfile || pnpm install
|
pnpm install --frozen-lockfile || pnpm install
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Stage 3: Builder (memory-optimized)
|
# Stage 3: Builder (AQUI ESTAVA O PROBLEMA)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
|
|
||||||
# Reduce memory usage during build
|
|
||||||
ENV NODE_OPTIONS="--max-old-space-size=512"
|
ENV NODE_OPTIONS="--max-old-space-size=512"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy deps from previous stage
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|
||||||
# Copy source files (respects .dockerignore)
|
# CORREÇÃO: Copiando TODAS as configs e pastas necessárias
|
||||||
COPY package.json next.config.* tsconfig.json ./
|
COPY package.json next.config.* tsconfig.json postcss.config.mjs ./
|
||||||
|
# Se tiver outras configs como tailwind.config.ts, adicione aqui ou use COPY . . (com dockerignore bom)
|
||||||
COPY public ./public
|
COPY public ./public
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
|
# Adicionei a pasta messages que apareceu no seu ls
|
||||||
|
COPY messages ./messages
|
||||||
|
|
||||||
# Build arguments
|
# Build arguments
|
||||||
ARG NEXT_PUBLIC_API_URL=http://localhost:8080
|
ARG NEXT_PUBLIC_API_URL=http://localhost:8080
|
||||||
|
|
@ -56,26 +44,24 @@ ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
|
||||||
ENV NEXT_PUBLIC_BACKOFFICE_URL=$NEXT_PUBLIC_BACKOFFICE_URL
|
ENV NEXT_PUBLIC_BACKOFFICE_URL=$NEXT_PUBLIC_BACKOFFICE_URL
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Build and cleanup in same layer
|
|
||||||
RUN pnpm build && \
|
RUN pnpm build && \
|
||||||
rm -rf node_modules/.cache .next/cache
|
rm -rf node_modules/.cache .next/cache
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Stage 4: Production Runner (minimal)
|
# Stage 4: Production Runner
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
FROM mirror.gcr.io/library/node:20-alpine AS runner
|
FROM mirror.gcr.io/library/node:20-alpine AS runner
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Security: non-root user
|
|
||||||
RUN addgroup -g 1001 -S nodejs && \
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
adduser -u 1001 -S nextjs -G nodejs
|
adduser -u 1001 -S nextjs -G nodejs
|
||||||
|
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
NEXT_TELEMETRY_DISABLED=1 \
|
NEXT_TELEMETRY_DISABLED=1 \
|
||||||
PORT=3000
|
PORT=3000 \
|
||||||
|
HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
# Copy ONLY standalone output (smallest possible)
|
# O Docker faz o "cp" que você fez na mão AQUI:
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
@ -84,4 +70,4 @@ USER nextjs
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "server.js"]
|
||||||
Loading…
Reference in a new issue