feat(ci): add backoffice to deploy pipeline + optimize Dockerfile
- Add backoffice paths trigger to deploy workflow - Implement conditional builds (only build changed services) - Optimize Dockerfile with BuildKit cache mounts - Update pnpm to latest version - Remove HEALTHCHECK (not supported by Podman OCI format)
This commit is contained in:
parent
69534f5810
commit
632fc78982
2 changed files with 62 additions and 40 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
name: Deploy Backend (Dev)
|
name: Deploy Stack (Dev)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|
@ -6,11 +6,13 @@ on:
|
||||||
- dev
|
- dev
|
||||||
paths:
|
paths:
|
||||||
- 'backend/**'
|
- 'backend/**'
|
||||||
|
- 'backoffice/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Job 1: Run Backend Tests
|
# Job 1: Testes do Backend (só roda se houver alteração no /backend)
|
||||||
test-backend:
|
test-backend:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
if: contains(github.event.head_commit.modified, 'backend/') || contains(github.event.head_commit.added, 'backend/')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: https://github.com/actions/checkout@v4
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
@ -32,12 +34,14 @@ 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 (only if tests pass)
|
# Job 2: Deploy Inteligente
|
||||||
deploy-backend-dev:
|
deploy-dev:
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: test-backend
|
# O deploy depende dos testes apenas se houver mudanças no backend
|
||||||
|
needs: [test-backend]
|
||||||
|
if: always() && (needs.test-backend.result == 'success' || needs.test-backend.result == 'skipped')
|
||||||
steps:
|
steps:
|
||||||
- name: Executar Deploy via SSH na Apolo (Ambiente Dev)
|
- name: Executar Deploy via SSH na Apolo
|
||||||
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 }}
|
||||||
|
|
@ -45,25 +49,23 @@ jobs:
|
||||||
key: ${{ secrets.SSH_KEY }}
|
key: ${{ secrets.SSH_KEY }}
|
||||||
port: ${{ secrets.PORT || 22 }}
|
port: ${{ secrets.PORT || 22 }}
|
||||||
script: |
|
script: |
|
||||||
# 1. Verifica se o diretório existe, senão cria e faz o clone inicial
|
|
||||||
if [ ! -d "/mnt/data/gohorsejobs" ]; then
|
|
||||||
sudo mkdir -p /mnt/data/gohorsejobs
|
|
||||||
sudo chown $USER:$USER /mnt/data/gohorsejobs
|
|
||||||
git clone https://forgejo-gru.rede5.com.br/rede5/gohorsejobs.git /mnt/data/gohorsejobs
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd /mnt/data/gohorsejobs
|
cd /mnt/data/gohorsejobs
|
||||||
|
|
||||||
# 2. Atualiza o código na branch dev
|
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git checkout dev
|
git checkout dev
|
||||||
git pull origin dev
|
git pull origin dev
|
||||||
|
|
||||||
# 3. Build da imagem com o prefixo localhost/ para evitar erro de short-name resolution
|
# DEPLOY DO BACKEND (Se houver alterações)
|
||||||
podman build -t localhost/gohorsejobs-backend-dev:latest ./backend
|
if git diff --name-only HEAD@{1} HEAD | grep -q "^backend/"; then
|
||||||
|
echo "Detectadas mudanças no Backend. Iniciando Build..."
|
||||||
|
podman build -t localhost/gohorsejobs-backend-dev:latest ./backend
|
||||||
|
sudo systemctl restart gohorsejobs-backend-dev
|
||||||
|
fi
|
||||||
|
|
||||||
|
# DEPLOY DO BACKOFFICE (Se houver alterações)
|
||||||
|
if git diff --name-only HEAD@{1} HEAD | grep -q "^backoffice/"; then
|
||||||
|
echo "Detectadas mudanças no Backoffice. Iniciando Build..."
|
||||||
|
podman build -t localhost/gohorsejobs-backoffice-dev:latest ./backoffice
|
||||||
|
sudo systemctl restart gohorsejobs-backoffice-dev
|
||||||
|
fi
|
||||||
|
|
||||||
# 4. Reinicia o serviço via Systemd (Quadlet)
|
|
||||||
sudo systemctl restart gohorsejobs-backend-dev
|
|
||||||
|
|
||||||
# 5. Limpeza de imagens antigas para economizar espaço na VPS
|
|
||||||
podman image prune -f
|
podman image prune -f
|
||||||
|
|
@ -1,61 +1,81 @@
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# GoHorse Backoffice - Ultra-Optimized Dockerfile with pnpm
|
# GoHorse Backoffice - Optimized Dockerfile with pnpm + BuildKit caching
|
||||||
# Target: < 200MB final image
|
# Target: < 200MB final image
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# Stage 1: Base with pnpm
|
# Stage 1: Base with pnpm (latest stable)
|
||||||
FROM mirror.gcr.io/library/node:20-alpine AS base
|
FROM mirror.gcr.io/library/node:20-alpine AS base
|
||||||
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
|
|
||||||
|
# Enable corepack and activate pnpm
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
# libc6-compat for native module compatibility
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
|
||||||
# Stage 2: Install dependencies
|
# Set pnpm store location for caching
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Stage 2: Install dependencies with BuildKit cache
|
||||||
|
# =============================================================================
|
||||||
FROM base AS deps
|
FROM base AS deps
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json pnpm-lock.yaml ./
|
|
||||||
RUN pnpm install --no-frozen-lockfile
|
|
||||||
|
|
||||||
# Stage 3: Build
|
# Copy only package files first (better layer caching)
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
|
||||||
|
# Use BuildKit cache mount for pnpm store - dramatically speeds up rebuilds
|
||||||
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Stage 3: Build application
|
||||||
|
# =============================================================================
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy dependencies from deps stage
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
# Copy source files
|
||||||
COPY package.json pnpm-lock.yaml ./
|
COPY package.json pnpm-lock.yaml ./
|
||||||
COPY tsconfig*.json nest-cli.json ./
|
COPY tsconfig*.json nest-cli.json ./
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
|
|
||||||
# Build the application
|
# Build the NestJS application
|
||||||
RUN pnpm build
|
RUN pnpm build
|
||||||
|
|
||||||
# Prune dev dependencies for production
|
# Prune dev dependencies for smaller production image
|
||||||
RUN pnpm prune --prod
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm prune --prod
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Stage 4: Production - Minimal runtime
|
# Stage 4: Production - Minimal runtime
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
FROM mirror.gcr.io/library/node:20-alpine AS production
|
FROM mirror.gcr.io/library/node:20-alpine AS production
|
||||||
|
|
||||||
# Security: non-root user
|
# Security: create non-root user
|
||||||
RUN addgroup -g 1001 -S nodejs && \
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
adduser -S nestjs -u 1001 -G nodejs
|
adduser -S nestjs -u 1001 -G nodejs
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy only production artifacts
|
# Copy only production artifacts (with proper ownership)
|
||||||
COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist
|
COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist
|
||||||
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
|
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
|
||||||
COPY --from=builder --chown=nestjs:nodejs /app/package.json ./
|
COPY --from=builder --chown=nestjs:nodejs /app/package.json ./
|
||||||
|
|
||||||
# Environment
|
# Environment configuration
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV BACKOFFICE_PORT=3001
|
ENV BACKOFFICE_PORT=3001
|
||||||
ENV BACKOFFICE_HOST=0.0.0.0
|
ENV BACKOFFICE_HOST=0.0.0.0
|
||||||
|
|
||||||
# Switch to non-root user
|
# Switch to non-root user for security
|
||||||
USER nestjs
|
USER nestjs
|
||||||
|
|
||||||
EXPOSE 3001
|
EXPOSE 3001
|
||||||
|
|
||||||
# Health check
|
# Start application
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
|
|
||||||
CMD node -e "const http = require('http'); http.get('http://localhost:3001/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"
|
|
||||||
|
|
||||||
CMD ["node", "dist/main.js"]
|
CMD ["node", "dist/main.js"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue