diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..5e82007 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: [main, dev] + pull_request: + branches: [main, dev] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Lint + run: pnpm lint + + - name: Build + run: pnpm build + + deploy-dev: + if: github.ref == 'refs/heads/dev' + needs: lint + runs-on: ubuntu-latest + steps: + - name: Deploy to Coolify (Dev) + run: | + curl -X POST "${{ secrets.COOLIFY_DEV_WEBHOOK }}" + + deploy-prod: + if: github.ref == 'refs/heads/main' + needs: lint + runs-on: ubuntu-latest + steps: + - name: Deploy to Coolify (Prod) + run: | + curl -X POST "${{ secrets.COOLIFY_PROD_WEBHOOK }}" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 084d5ce..dae73b6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [main, develop] + branches: [main, dev] pull_request: - branches: [main, develop] + branches: [main, dev] jobs: lint: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 7542996..17e36a5 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -42,11 +42,44 @@ npx convex dev This connects to your self-hosted Convex instance. Ensure CLI version matches your backend image version. -## Coolify Deployment (Convex Self-Hosted) +## Architecture Overview -### 1. Deploy Convex Backend +``` +┌─────────────────────────────────────────────────────────────┐ +│ LOCAL DEV │ +│ pnpm dev --webpack → npx convex dev → DEV CONVEX DB │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ FORGEJO / GIT │ +│ main branch ──► PROD DEPLOY │ +│ dev branch ──► DEV DEPLOY │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌───────────────┴───────────────┐ + ▼ ▼ +┌─────────────────────────────┐ ┌─────────────────────────────┐ +│ COOLIFY (PROD) │ │ COOLIFY (DEV) │ +│ Next.js Docker Container │ │ Next.js Docker Container │ +│ (frontend) │ │ (frontend) │ +└─────────────────────────────┘ └─────────────────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────┐ ┌─────────────────────────────┐ +│ CONVEX (PROD DB) │ │ CONVEX (DEV DB) │ +│ Self-hosted on Coolify │ │ Self-hosted on Coolify │ +│ or Convex Cloud │ │ or Convex Cloud │ +└─────────────────────────────┘ └─────────────────────────────┘ +``` -On Coolify, create a new service using this docker-compose: +### Convex Backend + +Convex runs **separately** from the Next.js frontend. You need two instances: +- **Dev**: for local development + dev environment testing +- **Prod**: for production + +On Coolify, create a new service for each Convex backend using the official docker-compose: ```yaml services: @@ -66,7 +99,6 @@ services: CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}' DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}' DATABASE_URL: '${DATABASE_URL:-}' - # ... (see README.md for full config) healthcheck: test: ['CMD-SHELL', 'curl -f http://localhost:3210/version'] interval: 5s @@ -91,7 +123,7 @@ volumes: > **Best practice**: Copy the [official self-hosted config](https://github.com/get-convex/convex-backend/blob/main/self-hosted/docker/docker-compose.yml) and adapt env vars for Coolify. -### 2. Generate Admin Key +### Generate Admin Key SSH into the server and run: @@ -291,11 +323,11 @@ docker run -p 3000:3000 --env-file .env.local my-app ### Docker Compose -Full-stack deployment with Convex backend: +Frontend-only deployment: ```bash -# Start everything (Next.js + Convex backend + Convex dashboard) -docker compose up +# Build and start Next.js app +docker compose up --build ``` Services: @@ -303,8 +335,8 @@ Services: | Service | Port | Description | |---------|------|-------------| | `app` | 3000 | Next.js application | -| `backend` | 3210 | Convex backend API | -| `dashboard` | 6791 | Convex admin dashboard | + +> **Note**: Convex backend runs separately. See [Coolify Deployment](#coolify-deployment) for Convex setup. ### Server Components in Docker @@ -339,17 +371,66 @@ CONVEX_SELF_HOSTED_ADMIN_KEY=your-admin-key ### Coolify Deployment -1. Push code to your Forgejo repo -2. In Coolify, create a new service from your repo -3. Select `docker-compose.yml` as the deployment method -4. Set environment variables in Coolify UI -5. Deploy +#### 1. Setup Two Environments -> **Note**: The `app` service depends on `backend` (Convex). Make sure your Convex backend is accessible from the Coolify server. +Create two services in Coolify: + +| Service | Branch | Convex DB | Domain | +|---------|--------|-----------|--------| +| `my-app-prod` | `main` | Prod | `app.example.com` | +| `my-app-dev` | `dev` | Dev | `dev-app.example.com` | + +#### 2. Configure Webhooks (Auto-Deploy) + +In each Coolify service, copy the **Deploy Webhook URL** and add it to Forgejo Secrets: + +```bash +# Forgejo → Repo Settings → Secrets +COOLIFY_PROD_WEBHOOK=https://coolify.example.com/webhooks/... +COOLIFY_DEV_WEBHOOK=https://coolify.example.com/webhooks/... +``` + +The `.forgejo/workflows/ci.yml` automatically triggers deploy on push: +- `main` branch → Prod webhook +- `dev` branch → Dev webhook + +#### 3. Set Environment Variables + +In each Coolify service, set env vars: + +**Prod**: +```bash +NEXT_PUBLIC_SITE_URL=https://app.example.com +NEXT_PUBLIC_CONVEX_URL=https://convex-prod.example.com +NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-prod.example.com +CONVEX_SELF_HOSTED_URL=https://convex-prod.example.com +CONVEX_SELF_HOSTED_ADMIN_KEY=prod-admin-key +``` + +**Dev**: +```bash +NEXT_PUBLIC_SITE_URL=https://dev-app.example.com +NEXT_PUBLIC_CONVEX_URL=https://convex-dev.example.com +NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-dev.example.com +CONVEX_SELF_HOSTED_URL=https://convex-dev.example.com +CONVEX_SELF_HOSTED_ADMIN_KEY=dev-admin-key +``` + +#### 4. Local Development Connects to Dev + +Your `.env.local` should point to the **dev** Convex: + +```bash +CONVEX_SELF_HOSTED_URL='https://convex-dev.example.com' +CONVEX_SELF_HOSTED_ADMIN_KEY='dev-admin-key' +NEXT_PUBLIC_SITE_URL=http://localhost:3000 +NEXT_PUBLIC_CONVEX_URL=https://convex-dev.example.com +NEXT_PUBLIC_CONVEX_SITE_URL=https://convex-site-dev.example.com +``` ### Health Check -The Next.js app exposes a health endpoint at `/api/health` (add if needed) or you can check if the app is running: +Verify the app is running: ```bash curl http://localhost:3000 diff --git a/docker-compose.yml b/docker-compose.yml index 28b1da0..0530d88 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,4 @@ services: - # Next.js Application app: build: context: . @@ -7,52 +6,9 @@ services: ports: - '${PORT:-3000}:3000' environment: - NODE_ENV: production + NODE_ENV: '${NODE_ENV:-production}' NEXT_PUBLIC_SITE_URL: '${NEXT_PUBLIC_SITE_URL}' NEXT_PUBLIC_CONVEX_URL: '${NEXT_PUBLIC_CONVEX_URL}' NEXT_PUBLIC_CONVEX_SITE_URL: '${NEXT_PUBLIC_CONVEX_SITE_URL}' CONVEX_SELF_HOSTED_URL: '${CONVEX_SELF_HOSTED_URL}' CONVEX_SELF_HOSTED_ADMIN_KEY: '${CONVEX_SELF_HOSTED_ADMIN_KEY}' - depends_on: - - backend - - # Convex Backend - backend: - image: 'ghcr.io/get-convex/convex-backend:latest' - stop_grace_period: 10s - stop_signal: SIGINT - ports: - - '${PORT:-3210}:3210' - - '${SITE_PROXY_PORT:-3211}:3211' - volumes: - - 'data:/convex/data' - environment: - INSTANCE_NAME: '${INSTANCE_NAME}' - INSTANCE_SECRET: '${INSTANCE_SECRET}' - CONVEX_CLOUD_ORIGIN: '${SERVICE_URL_BACKEND}' - CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}' - DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}' - DATABASE_URL: '${DATABASE_URL:-}' - healthcheck: - test: ['CMD-SHELL', 'curl -f http://localhost:3210/version'] - interval: 5s - start_period: 10s - timeout: 5s - retries: 10 - - # Convex Dashboard - dashboard: - image: 'ghcr.io/get-convex/convex-dashboard:latest' - stop_grace_period: 10s - stop_signal: SIGINT - ports: - - '${DASHBOARD_PORT:-6791}:6791' - environment: - PORT: '6791' - NEXT_PUBLIC_DEPLOYMENT_URL: '${SERVICE_URL_BACKEND}' - depends_on: - backend: - condition: service_healthy - -volumes: - data: null