From 284920544b301b3ef0a800c9438fef669f3169dc Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Wed, 27 May 2026 23:53:49 +0330 Subject: [PATCH] ci: add missing admin-api and admin-web to full CI/CD pipeline CI now covers all 6 services: - api-build: Meezi.API dotnet build + test - admin-api-build: Meezi.Admin.API dotnet build (was missing) - dashboard-check: web/dashboard tsc - admin-web-check: web/admin tsc (was missing) - website-check: web/website tsc (was missing) - finder-check: web/finder tsc Deploy now builds and starts all 8 containers: - Main: postgres, redis, api, web, website, finder - Admin: admin-api, admin-web (via docker-compose.admin.yml overlay) - Health checks for both meezi-api and meezi-admin-api Co-Authored-By: Claude Sonnet 4.5 --- .gitea/workflows/ci-cd.yml | 166 +++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 44 deletions(-) diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index 364379b..2893334 100644 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -15,8 +15,10 @@ concurrency: # CI — runs on every push AND every PR # ───────────────────────────────────────────────────────────────────────────── jobs: + + # ── Main API ──────────────────────────────────────────────────────────────── api-build: - name: "CI · API (dotnet build)" + name: "CI · API (dotnet build + test)" runs-on: self-hosted steps: - uses: actions/checkout@v4 @@ -26,16 +28,34 @@ jobs: with: dotnet-version: "10.0.x" - - name: Restore dependencies - run: dotnet restore + - name: Restore + run: dotnet restore src/Meezi.API/Meezi.API.csproj - - name: Build (Release) - run: dotnet build --no-restore -c Release + - name: Build + run: dotnet build src/Meezi.API/Meezi.API.csproj --no-restore -c Release - - name: Run tests + - name: Test run: dotnet test --no-build -c Release --logger "console;verbosity=minimal" - # ── Dashboard typecheck ──────────────────────────────────────────────────── + # ── Admin API ─────────────────────────────────────────────────────────────── + admin-api-build: + name: "CI · Admin API (dotnet build)" + runs-on: self-hosted + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET 10 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "10.0.x" + + - name: Restore + run: dotnet restore src/Meezi.Admin.API/Meezi.Admin.API.csproj + + - name: Build + run: dotnet build src/Meezi.Admin.API/Meezi.Admin.API.csproj --no-restore -c Release + + # ── Dashboard ─────────────────────────────────────────────────────────────── dashboard-check: name: "CI · Dashboard (tsc)" runs-on: self-hosted @@ -44,20 +64,49 @@ jobs: working-directory: web/dashboard steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 with: node-version: "20" - - - name: Install dependencies - run: npm install --legacy-peer-deps --ignore-scripts - - - name: TypeScript check - run: npx tsc --noEmit + - run: npm install --legacy-peer-deps --ignore-scripts + - run: npx tsc --noEmit env: NEXT_PUBLIC_API_URL: http://localhost:5080 - # ── Finder typecheck ─────────────────────────────────────────────────────── + # ── Admin Web ─────────────────────────────────────────────────────────────── + admin-web-check: + name: "CI · Admin Web (tsc)" + runs-on: self-hosted + defaults: + run: + working-directory: web/admin + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: npm install --legacy-peer-deps --ignore-scripts + - run: npx tsc --noEmit + env: + NEXT_PUBLIC_ADMIN_API_URL: http://localhost:5081 + + # ── Website ───────────────────────────────────────────────────────────────── + website-check: + name: "CI · Website (tsc)" + runs-on: self-hosted + defaults: + run: + working-directory: web/website + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + - run: npm install --legacy-peer-deps --ignore-scripts + - run: npx tsc --noEmit + env: + MEEZI_API_URL: http://localhost:5080 + + # ── Finder ────────────────────────────────────────────────────────────────── finder-check: name: "CI · Finder (tsc)" runs-on: self-hosted @@ -66,77 +115,106 @@ jobs: working-directory: web/finder steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 with: node-version: "20" - - - name: Install dependencies - run: npm install --legacy-peer-deps --ignore-scripts - - - name: TypeScript check - run: npx tsc --noEmit + - run: npm install --legacy-peer-deps --ignore-scripts + - run: npx tsc --noEmit env: NEXT_PUBLIC_API_URL: http://localhost:5080 # ───────────────────────────────────────────────────────────────────────────── -# DEPLOY — only on push to main, only if all CI jobs pass +# DEPLOY — only on push to main, only if ALL CI jobs pass # ───────────────────────────────────────────────────────────────────────────── deploy: - name: "Deploy · docker compose" + name: "Deploy · all services" runs-on: self-hosted - needs: [api-build, dashboard-check, finder-check] - # Skip deploy on PRs — only run when pushing directly to main + needs: + - api-build + - admin-api-build + - dashboard-check + - admin-web-check + - website-check + - finder-check if: github.event_name == 'push' && github.ref == 'refs/heads/main' - timeout-minutes: 30 + timeout-minutes: 40 steps: - uses: actions/checkout@v4 - # Write .env from a single Gitea secret called ENV_FILE - # How to set it: Gitea repo → Settings → Secrets → Add secret + # Write .env from Gitea secret + # Set it at: Gitea repo → Settings → Secrets → Actions → Add Secret # Name: ENV_FILE - # Value: paste your entire .env file content + # Value: your full .env file content - name: Write .env run: printf '%s' "$ENV_FILE" > .env env: ENV_FILE: ${{ secrets.ENV_FILE }} - # Build all service images in parallel using BuildKit - - name: Build Docker images + # ── Build main services ───────────────────────────────────────────────── + - name: Build main images (api, web, website, finder) run: | docker compose build --parallel api web website finder env: DOCKER_BUILDKIT: 1 COMPOSE_DOCKER_CLI_BUILD: 1 - # Rolling restart — postgres/redis stay untouched if already healthy - - name: Start / restart services + # ── Build admin services (separate compose file) ──────────────────────── + - name: Build admin images (admin-api, admin-web) + run: | + docker compose \ + -f docker-compose.yml \ + -f docker-compose.admin.yml \ + build --parallel admin-api admin-web + env: + DOCKER_BUILDKIT: 1 + COMPOSE_DOCKER_CLI_BUILD: 1 + + # ── Start / restart main services ─────────────────────────────────────── + - name: Start main services run: | docker compose up -d \ --remove-orphans \ --no-deps \ postgres redis api web website finder - # Poll until API container reports healthy (max 2 min) - - name: Wait for API to become healthy + # ── Start / restart admin services ────────────────────────────────────── + - name: Start admin services run: | - echo "Waiting for meezi-api to become healthy..." + docker compose \ + -f docker-compose.yml \ + -f docker-compose.admin.yml \ + up -d \ + --no-deps \ + admin-api admin-web + + # ── Health checks ──────────────────────────────────────────────────────── + - name: Wait for main API healthy + run: | + echo "Waiting for meezi-api..." for i in $(seq 1 24); do STATUS=$(docker inspect --format='{{.State.Health.Status}}' meezi-api 2>/dev/null || echo "missing") echo " [$i/24] $STATUS" - [ "$STATUS" = "healthy" ] && echo "✅ Healthy" && exit 0 + [ "$STATUS" = "healthy" ] && echo "✅ meezi-api healthy" && break + [ "$i" = "24" ] && echo "❌ meezi-api timeout" && docker compose logs --tail=40 api && exit 1 sleep 5 done - echo "❌ API did not become healthy — last 50 log lines:" - docker compose logs --tail=50 api - exit 1 - - name: Show running containers + - name: Wait for admin API healthy + run: | + echo "Waiting for meezi-admin-api..." + for i in $(seq 1 24); do + STATUS=$(docker inspect --format='{{.State.Health.Status}}' meezi-admin-api 2>/dev/null || echo "missing") + echo " [$i/24] $STATUS" + [ "$STATUS" = "healthy" ] && echo "✅ meezi-admin-api healthy" && break + [ "$i" = "24" ] && echo "❌ meezi-admin-api timeout" && docker compose -f docker-compose.yml -f docker-compose.admin.yml logs --tail=40 admin-api && exit 1 + sleep 5 + done + + - name: Show all running containers if: always() - run: docker compose ps + run: docker compose -f docker-compose.yml -f docker-compose.admin.yml ps - # Remove dangling images to keep disk clean - name: Prune old images if: success() run: docker image prune -f