diff --git a/.github/workflows/cd-staging-tagged.yml b/.github/workflows/cd-staging-tagged.yml index 72a267e8a..4185dc065 100644 --- a/.github/workflows/cd-staging-tagged.yml +++ b/.github/workflows/cd-staging-tagged.yml @@ -21,6 +21,7 @@ on: - zitare - presi - mana-core-auth + - todo apps: description: 'Apps to deploy (comma-separated: backend,web,landing or "all")' required: true @@ -104,6 +105,7 @@ jobs: PROJECT_APPS[zitare]="backend,web" PROJECT_APPS[presi]="backend,web" PROJECT_APPS[mana-core-auth]="service" + PROJECT_APPS[todo]="backend,web" # Expand "all" to available apps if [ "$APPS" == "all" ]; then @@ -153,6 +155,7 @@ jobs: manadeck) PORT="3009" ;; zitare) PORT="3007" ;; presi) PORT="3008" ;; + todo) PORT="3018" ;; esac HEALTH_PATH="/api/health" ;; @@ -289,7 +292,7 @@ jobs: docker compose up -d --no-deps --force-recreate \$SERVICE_NAME else echo "Service \$SERVICE_NAME not found in compose, starting..." - docker compose up -d \$SERVICE_NAME + docker compose up -d --force-recreate \$SERVICE_NAME fi # Wait for startup diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 6ffe6f93c..63de27e42 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -9,6 +9,7 @@ on: push: branches: - main + - dev workflow_dispatch: concurrency: @@ -26,6 +27,8 @@ jobs: - { name: 'mana-core-auth', path: 'services/mana-core-auth', port: '3001' } - { name: 'chat-backend', path: 'apps/chat/apps/backend', port: '3002' } - { name: 'chat-web', path: 'apps/chat/apps/web', port: '3000' } + - { name: 'todo-backend', path: 'apps/todo/apps/backend', port: '3018' } + - { name: 'todo-web', path: 'apps/todo/apps/web', port: '5188' } fail-fast: false steps: - name: Checkout code diff --git a/apps/todo/apps/backend/Dockerfile b/apps/todo/apps/backend/Dockerfile new file mode 100644 index 000000000..96274c974 --- /dev/null +++ b/apps/todo/apps/backend/Dockerfile @@ -0,0 +1,71 @@ +# 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 (todo-backend uses shared-nestjs-auth) +COPY packages/shared-errors ./packages/shared-errors +COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth + +# Copy todo shared package and backend +COPY apps/todo/packages/shared ./apps/todo/packages/shared +COPY apps/todo/apps/backend ./apps/todo/apps/backend + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages first +WORKDIR /app/packages/shared-errors +RUN pnpm build + +WORKDIR /app/packages/shared-nestjs-auth +RUN pnpm build + +WORKDIR /app/apps/todo/packages/shared +RUN pnpm build + +# Build the backend +WORKDIR /app/apps/todo/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/todo ./apps/todo + +# Copy entrypoint script +COPY apps/todo/apps/backend/docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +WORKDIR /app/apps/todo/apps/backend + +# Expose port +EXPOSE 3018 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3018/api/health || exit 1 + +# Run entrypoint script +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["node", "dist/main.js"] diff --git a/apps/todo/apps/backend/docker-entrypoint.sh b/apps/todo/apps/backend/docker-entrypoint.sh new file mode 100644 index 000000000..29843bdc9 --- /dev/null +++ b/apps/todo/apps/backend/docker-entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e + +echo "Starting Todo Backend..." +echo "Environment: ${NODE_ENV:-development}" +echo "Port: ${PORT:-3018}" + +exec "$@" diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 509561d3e..74180881f 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -159,6 +159,68 @@ services: max-size: "10m" max-file: "3" + todo-backend: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/todo-backend:${TODO_BACKEND_VERSION:-latest} + container_name: todo-backend-staging + restart: unless-stopped + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 3018 + DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@postgres:5432/todo + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + ports: + - "3018:3018" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3018/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + todo-web: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/todo-web:${TODO_WEB_VERSION:-latest} + container_name: todo-web-staging + restart: unless-stopped + depends_on: + todo-backend: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 5188 + # Server-side URLs (Docker internal network) + PUBLIC_BACKEND_URL: http://todo-backend:3018 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + # Client-side URLs (browser access via public IP) + PUBLIC_BACKEND_URL_CLIENT: http://46.224.108.214:3018 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: http://46.224.108.214:3001 + ports: + - "5188:5188" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5188/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + # ============================================ # Networks # ============================================