diff --git a/.github/workflows/cd-macmini.yml b/.github/workflows/cd-macmini.yml index ae7d9d227..020c66a53 100644 --- a/.github/workflows/cd-macmini.yml +++ b/.github/workflows/cd-macmini.yml @@ -217,6 +217,30 @@ jobs: echo "deploy-all=false" >> $GITHUB_OUTPUT echo "Services to deploy: $SERVICES" + - name: Build shared base image + run: | + cd "${{ env.PROJECT_DIR }}" + SERVICES="${{ steps.services.outputs.services }}" + DEPLOY_ALL="${{ steps.services.outputs.deploy-all }}" + + # Check if any backend service is being deployed + NEEDS_BASE=false + if [ "$DEPLOY_ALL" == "true" ]; then + NEEDS_BASE=true + else + for svc in $SERVICES; do + case "$svc" in *-backend) NEEDS_BASE=true; break ;; esac + done + fi + + if [ "$NEEDS_BASE" == "true" ]; then + echo "=== Building shared NestJS base image ===" + docker build -f docker/Dockerfile.nestjs-base -t nestjs-base:local . 2>&1 | tail -5 + echo "Base image built" + else + echo "No backends to deploy, skipping base image" + fi + - name: Build and deploy services id: build run: | diff --git a/apps/calendar/apps/backend/Dockerfile b/apps/calendar/apps/backend/Dockerfile index b85a15f69..74df283b3 100644 --- a/apps/calendar/apps/backend/Dockerfile +++ b/apps/calendar/apps/backend/Dockerfile @@ -1,61 +1,14 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches -# Copy shared packages (all required dependencies) -COPY packages/credit-operations ./packages/credit-operations -COPY packages/mana-core-nestjs-integration ./packages/mana-core-nestjs-integration -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-tsconfig ./packages/shared-tsconfig - -# Copy calendar packages and backend +# Copy calendar-specific packages and backend COPY apps/calendar/packages ./apps/calendar/packages COPY apps/calendar/apps/backend ./apps/calendar/apps/backend -# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages first (in dependency order) -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-metrics -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - -WORKDIR /app/packages/credit-operations -RUN pnpm build - -WORKDIR /app/packages/mana-core-nestjs-integration -RUN pnpm build - # Build the backend WORKDIR /app/apps/calendar/apps/backend RUN pnpm build @@ -70,9 +23,8 @@ RUN pnpm prune --prod --no-optional 2>/dev/null || true \ # Production stage FROM node:20-alpine AS production -# Install pnpm and postgresql-client for health checks -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ - && apk add --no-cache postgresql-client +# Install postgresql-client for health checks +RUN apk add --no-cache postgresql-client WORKDIR /app diff --git a/apps/chat/apps/backend/Dockerfile b/apps/chat/apps/backend/Dockerfile index 1ae825eda..19d706d45 100644 --- a/apps/chat/apps/backend/Dockerfile +++ b/apps/chat/apps/backend/Dockerfile @@ -1,66 +1,14 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder - -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches - -# Copy shared packages (all required dependencies) -COPY packages/credit-operations ./packages/credit-operations -COPY packages/mana-core-nestjs-integration ./packages/mana-core-nestjs-integration -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-storage ./packages/shared-storage -COPY packages/shared-tsconfig ./packages/shared-tsconfig +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder # Copy chat backend COPY apps/chat/apps/backend ./apps/chat/apps/backend -# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages first (in dependency order) -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-metrics -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - -WORKDIR /app/packages/shared-storage -RUN pnpm build - -WORKDIR /app/packages/credit-operations -RUN pnpm build - -WORKDIR /app/packages/mana-core-nestjs-integration -RUN pnpm build - # Build the backend -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - WORKDIR /app/apps/chat/apps/backend RUN pnpm build @@ -74,9 +22,8 @@ RUN pnpm prune --prod --no-optional 2>/dev/null || true \ # Production stage FROM node:20-alpine AS production -# Install pnpm and postgresql-client for health checks -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ - && apk add --no-cache postgresql-client +# Install postgresql-client for health checks +RUN apk add --no-cache postgresql-client WORKDIR /app @@ -92,9 +39,6 @@ COPY --from=builder /app/apps/chat/apps/backend ./apps/chat/apps/backend COPY apps/chat/apps/backend/docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - WORKDIR /app/apps/chat/apps/backend # Expose port diff --git a/apps/clock/apps/backend/Dockerfile b/apps/clock/apps/backend/Dockerfile index 5f924ab9a..40949b883 100644 --- a/apps/clock/apps/backend/Dockerfile +++ b/apps/clock/apps/backend/Dockerfile @@ -1,55 +1,15 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches - -# Copy shared packages (all required dependencies) -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-tsconfig ./packages/shared-tsconfig - -# Copy clock packages and backend +# Copy clock-specific packages and backend COPY apps/clock/packages ./apps/clock/packages COPY apps/clock/apps/backend ./apps/clock/apps/backend -# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages first (in dependency order) -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-metrics -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - # Build the backend -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - WORKDIR /app/apps/clock/apps/backend RUN pnpm build @@ -63,9 +23,8 @@ RUN pnpm prune --prod --no-optional 2>/dev/null || true \ # Production stage FROM node:20-alpine AS production -# Install pnpm and postgresql-client for health checks -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ - && apk add --no-cache postgresql-client +# Install postgresql-client for health checks +RUN apk add --no-cache postgresql-client WORKDIR /app @@ -81,9 +40,6 @@ COPY --from=builder /app/apps/clock ./apps/clock COPY apps/clock/apps/backend/docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - WORKDIR /app/apps/clock/apps/backend # Expose port diff --git a/apps/contacts/apps/backend/Dockerfile b/apps/contacts/apps/backend/Dockerfile index 463ac9869..947c2a11d 100644 --- a/apps/contacts/apps/backend/Dockerfile +++ b/apps/contacts/apps/backend/Dockerfile @@ -1,56 +1,13 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder - -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches -# Copy shared packages (all required dependencies) -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-storage ./packages/shared-storage -COPY packages/shared-tsconfig ./packages/shared-tsconfig +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder # Copy contacts backend COPY apps/contacts/apps/backend ./apps/contacts/apps/backend -# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages first (in dependency order) -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-metrics -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - -WORKDIR /app/packages/shared-storage -RUN pnpm build - # Build the backend WORKDIR /app/apps/contacts/apps/backend RUN pnpm build @@ -65,9 +22,8 @@ RUN pnpm prune --prod --no-optional 2>/dev/null || true \ # Production stage FROM node:20-alpine AS production -# Install pnpm and postgresql-client for health checks -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ - && apk add --no-cache postgresql-client +# Install postgresql-client for health checks +RUN apk add --no-cache postgresql-client WORKDIR /app diff --git a/apps/mukke/apps/backend/Dockerfile b/apps/mukke/apps/backend/Dockerfile index 0f927e994..1208b670d 100644 --- a/apps/mukke/apps/backend/Dockerfile +++ b/apps/mukke/apps/backend/Dockerfile @@ -1,69 +1,23 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches - -# Copy shared packages -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-storage ./packages/shared-storage -COPY packages/shared-tsconfig ./packages/shared-tsconfig -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup - -# Copy mukke packages +# Copy mukke-specific packages and backend COPY apps/mukke/packages ./apps/mukke/packages COPY apps/mukke/apps/backend ./apps/mukke/apps/backend -# Install dependencies +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-storage -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - # Build the backend - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - WORKDIR /app/apps/mukke/apps/backend RUN pnpm build # Production stage FROM node:20-alpine AS production -# Install pnpm and postgresql-client -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ - && apk add --no-cache postgresql-client +# Install postgresql-client for health checks +RUN apk add --no-cache postgresql-client WORKDIR /app diff --git a/apps/todo/apps/backend/Dockerfile b/apps/todo/apps/backend/Dockerfile index 62a9f2686..2805baa72 100644 --- a/apps/todo/apps/backend/Dockerfile +++ b/apps/todo/apps/backend/Dockerfile @@ -1,61 +1,14 @@ # syntax=docker/dockerfile:1 -# Build stage -FROM node:20-alpine AS builder +# Build stage — inherits pre-built shared packages from nestjs-base +FROM nestjs-base:local AS builder -# Install pnpm -RUN corepack enable && corepack prepare pnpm@9.15.0 --activate - -WORKDIR /app - -# Copy root workspace files -COPY pnpm-workspace.yaml ./ -COPY package.json ./ -COPY pnpm-lock.yaml ./ -COPY patches ./patches -# Copy shared packages (all required dependencies) -COPY packages/credit-operations ./packages/credit-operations -COPY packages/mana-core-nestjs-integration ./packages/mana-core-nestjs-integration -COPY packages/shared-drizzle-config ./packages/shared-drizzle-config -COPY packages/shared-errors ./packages/shared-errors -COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth -COPY packages/shared-nestjs-health ./packages/shared-nestjs-health -COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics -COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup -COPY packages/shared-error-tracking ./packages/shared-error-tracking -COPY packages/shared-tsconfig ./packages/shared-tsconfig - -# Copy todo shared package and backend +# Copy todo-specific packages and backend COPY apps/todo/packages ./apps/todo/packages COPY apps/todo/apps/backend ./apps/todo/apps/backend -# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +# Reinstall to link app-specific dependencies RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts -# Build shared packages first (in dependency order) -WORKDIR /app/packages/shared-errors -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-auth -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-health -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-metrics -RUN pnpm build - -WORKDIR /app/packages/shared-nestjs-setup -RUN pnpm build - -WORKDIR /app/packages/shared-error-tracking -RUN pnpm build - -WORKDIR /app/packages/credit-operations -RUN pnpm build - -WORKDIR /app/packages/mana-core-nestjs-integration -RUN pnpm build - # Build the backend WORKDIR /app/apps/todo/apps/backend RUN pnpm build diff --git a/docker/Dockerfile.nestjs-base b/docker/Dockerfile.nestjs-base new file mode 100644 index 000000000..96631e80c --- /dev/null +++ b/docker/Dockerfile.nestjs-base @@ -0,0 +1,56 @@ +# syntax=docker/dockerfile:1 +# Shared builder base for all NestJS backends +# Contains pre-built shared packages and dependencies +# +# Usage in backend Dockerfiles: +# FROM nestjs-base:local AS builder +# COPY apps/myapp/apps/backend ./apps/myapp/apps/backend +# RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --ignore-scripts +# WORKDIR /app/apps/myapp/apps/backend +# RUN pnpm build + +FROM node:20-alpine + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ +COPY patches ./patches + +# Copy ALL shared packages used by NestJS backends +COPY packages/credit-operations ./packages/credit-operations +COPY packages/mana-core-nestjs-integration ./packages/mana-core-nestjs-integration +COPY packages/manadeck-database ./packages/manadeck-database +COPY packages/shared-drizzle-config ./packages/shared-drizzle-config +COPY packages/shared-errors ./packages/shared-errors +COPY packages/shared-error-tracking ./packages/shared-error-tracking +COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth +COPY packages/shared-nestjs-health ./packages/shared-nestjs-health +COPY packages/shared-nestjs-metrics ./packages/shared-nestjs-metrics +COPY packages/shared-nestjs-setup ./packages/shared-nestjs-setup +COPY packages/shared-storage ./packages/shared-storage +COPY packages/shared-tsconfig ./packages/shared-tsconfig + +# Install dependencies +RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile --ignore-scripts + +# Build all shared packages (in dependency order) +RUN cd packages/shared-errors && pnpm build \ + && cd /app/packages/shared-nestjs-auth && pnpm build \ + && cd /app/packages/shared-nestjs-health && pnpm build \ + && cd /app/packages/shared-nestjs-metrics && pnpm build \ + && cd /app/packages/shared-nestjs-setup && pnpm build \ + && cd /app/packages/shared-error-tracking && pnpm build \ + && cd /app/packages/shared-storage && pnpm build \ + && cd /app/packages/shared-drizzle-config && pnpm build 2>/dev/null || true \ + && cd /app/packages/credit-operations && pnpm build \ + && cd /app/packages/mana-core-nestjs-integration && pnpm build \ + && cd /app/packages/manadeck-database && pnpm build 2>/dev/null || true + +WORKDIR /app