From c54ff859d6551c5745d44273aed55317d851f092 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:49:15 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20feat(zitare):=20add=20Docker=20d?= =?UTF-8?q?eployment=20infrastructure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Dockerfile for zitare-backend (multi-stage build, port 3007) - Add docker-entrypoint.sh for database setup - Add zitare-backend service to docker-compose.macmini.yml - Update matrix-zitare-bot to depend on zitare-backend - Add zitare-backend to CI workflow (change detection + build job) --- .github/workflows/ci.yml | 45 ++++++++++ apps/zitare/apps/backend/Dockerfile | 84 +++++++++++++++++++ apps/zitare/apps/backend/docker-entrypoint.sh | 36 ++++++++ docker-compose.macmini.yml | 31 +++++++ 4 files changed, 196 insertions(+) create mode 100644 apps/zitare/apps/backend/Dockerfile create mode 100644 apps/zitare/apps/backend/docker-entrypoint.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de09b016a..0c7968d6c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,7 @@ jobs: matrix-zitare-bot: ${{ steps.changes.outputs.matrix-zitare-bot }} matrix-clock-bot: ${{ steps.changes.outputs.matrix-clock-bot }} matrix-tts-bot: ${{ steps.changes.outputs.matrix-tts-bot }} + zitare-backend: ${{ steps.changes.outputs.zitare-backend }} any-changes: ${{ steps.changes.outputs.any-changes }} steps: - name: Checkout code @@ -128,6 +129,7 @@ jobs: echo "matrix-zitare-bot=true" >> $GITHUB_OUTPUT echo "matrix-clock-bot=true" >> $GITHUB_OUTPUT echo "matrix-tts-bot=true" >> $GITHUB_OUTPUT + echo "zitare-backend=true" >> $GITHUB_OUTPUT echo "any-changes=true" >> $GITHUB_OUTPUT exit 0 fi @@ -178,6 +180,7 @@ jobs: echo "matrix-zitare-bot=true" >> $GITHUB_OUTPUT echo "matrix-clock-bot=true" >> $GITHUB_OUTPUT echo "matrix-tts-bot=true" >> $GITHUB_OUTPUT + echo "zitare-backend=true" >> $GITHUB_OUTPUT echo "any-changes=true" >> $GITHUB_OUTPUT exit 0 fi @@ -477,6 +480,14 @@ jobs: echo "matrix-tts-bot=false" >> $GITHUB_OUTPUT fi + # zitare-backend + ZITARE_BACKEND_CHANGED=$(check_pattern "apps/zitare/apps/backend/|apps/zitare/packages/") + if [ "$COMMON_CHANGED" == "true" ] || [ "$SHARED_AUTH_CHANGED" == "true" ] || [ "$ZITARE_BACKEND_CHANGED" == "true" ]; then + echo "zitare-backend=true" >> $GITHUB_OUTPUT + else + echo "zitare-backend=false" >> $GITHUB_OUTPUT + fi + # Check if any service needs building if grep -q "=true" $GITHUB_OUTPUT; then echo "any-changes=true" >> $GITHUB_OUTPUT @@ -523,6 +534,7 @@ jobs: echo "| matrix-zitare-bot | ${{ steps.changes.outputs.matrix-zitare-bot }} |" >> $GITHUB_STEP_SUMMARY echo "| matrix-clock-bot | ${{ steps.changes.outputs.matrix-clock-bot }} |" >> $GITHUB_STEP_SUMMARY echo "| matrix-tts-bot | ${{ steps.changes.outputs.matrix-tts-bot }} |" >> $GITHUB_STEP_SUMMARY + echo "| zitare-backend | ${{ steps.changes.outputs.zitare-backend }} |" >> $GITHUB_STEP_SUMMARY # =========================================== # Validation job - runs on PRs @@ -1553,3 +1565,36 @@ jobs: tags: ${{ steps.meta.outputs.tags }} cache-from: type=gha cache-to: type=gha,mode=max + + # =========================================== + # Zitare Backend + # =========================================== + + build-zitare-backend: + name: Build zitare-backend + runs-on: ubuntu-latest + needs: detect-changes + if: needs.detect-changes.outputs.zitare-backend == 'true' + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/metadata-action@v5 + id: meta + with: + images: ghcr.io/${{ github.repository_owner }}/zitare-backend + tags: type=raw,value=latest + - uses: docker/build-push-action@v5 + with: + context: . + file: apps/zitare/apps/backend/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/apps/zitare/apps/backend/Dockerfile b/apps/zitare/apps/backend/Dockerfile new file mode 100644 index 000000000..4c3d20738 --- /dev/null +++ b/apps/zitare/apps/backend/Dockerfile @@ -0,0 +1,84 @@ +# 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 shared packages (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-setup ./packages/shared-nestjs-setup +COPY packages/shared-tsconfig ./packages/shared-tsconfig + +# Copy zitare content package +COPY apps/zitare/packages/content ./apps/zitare/packages/content + +# Copy zitare backend +COPY apps/zitare/apps/backend ./apps/zitare/apps/backend + +# Install dependencies (ignore scripts since generate-env.mjs isn't in Docker context) +RUN 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-setup +RUN pnpm build + +# Build zitare content package +WORKDIR /app/apps/zitare/packages/content +RUN pnpm build + +# Build the backend +WORKDIR /app/apps/zitare/apps/backend +RUN pnpm build + +# 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 + +WORKDIR /app + +# Copy everything from builder (including node_modules) +COPY --from=builder /app/pnpm-workspace.yaml ./ +COPY --from=builder /app/package.json ./ +COPY --from=builder /app/pnpm-lock.yaml ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/packages ./packages +COPY --from=builder /app/apps/zitare ./apps/zitare + +# Copy entrypoint script +COPY apps/zitare/apps/backend/docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +WORKDIR /app/apps/zitare/apps/backend + +# Expose port +EXPOSE 3007 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3007/api/health || exit 1 + +# Run entrypoint script +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["node", "dist/main.js"] diff --git a/apps/zitare/apps/backend/docker-entrypoint.sh b/apps/zitare/apps/backend/docker-entrypoint.sh new file mode 100644 index 000000000..20f7b66f5 --- /dev/null +++ b/apps/zitare/apps/backend/docker-entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/sh +set -e + +echo "=== Zitare Backend Entrypoint ===" + +# Wait for PostgreSQL to be ready +echo "Waiting for PostgreSQL..." +until pg_isready -h ${DB_HOST:-postgres} -p ${DB_PORT:-5432} -U ${DB_USER:-zitare} 2>/dev/null; do + echo "PostgreSQL is unavailable - sleeping" + sleep 2 +done +echo "PostgreSQL is up!" + +cd /app/apps/zitare/apps/backend + +# Run schema push (for development) or migrations (for production) +if [ "$NODE_ENV" = "production" ] && [ -d "src/db/migrations/meta" ]; then + echo "Running database migrations..." + npx tsx src/db/migrate.ts + echo "Migrations completed!" +else + echo "Pushing database schema (development mode)..." + npx drizzle-kit push --force + echo "Schema push completed!" +fi + +# Run seed if seed file exists +if [ -f "src/db/seed.ts" ]; then + echo "Running database seed..." + npx tsx src/db/seed.ts + echo "Seed completed!" +fi + +# Execute the main command +echo "Starting application..." +exec "$@" diff --git a/docker-compose.macmini.yml b/docker-compose.macmini.yml index d8921f15f..7b203cada 100644 --- a/docker-compose.macmini.yml +++ b/docker-compose.macmini.yml @@ -563,6 +563,35 @@ services: retries: 3 start_period: 40s + zitare-backend: + build: + context: . + dockerfile: apps/zitare/apps/backend/Dockerfile + image: zitare-backend:local + container_name: mana-app-zitare-backend + restart: always + depends_on: + mana-auth: + condition: service_healthy + environment: + NODE_ENV: production + PORT: 3007 + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/zitare + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: postgres + MANA_CORE_AUTH_URL: http://mana-auth:3001 + CORS_ORIGINS: https://zitare.mana.how,https://mana.how + ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} + ports: + - "3007:3007" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3007/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + # ============================================ # Tier 4: Matrix Stack (Ports 4000-4099) # ============================================ @@ -874,6 +903,8 @@ services: depends_on: synapse: condition: service_healthy + zitare-backend: + condition: service_healthy environment: NODE_ENV: production PORT: 4017