Files
meezi/.gitea/workflows/ci-cd.yml
T
2026-05-27 23:55:26 +03:30

221 lines
8.8 KiB
YAML

name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
# Only one deploy at a time; a newer push cancels an in-progress one
concurrency:
group: meezi-cicd-${{ github.ref }}
cancel-in-progress: true
# ─────────────────────────────────────────────────────────────────────────────
# CI — runs on every push AND every PR
# ─────────────────────────────────────────────────────────────────────────────
jobs:
# ── Main API ────────────────────────────────────────────────────────────────
api-build:
name: "CI · API (dotnet build + test)"
runs-on: ubuntu-latest
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.API/Meezi.API.csproj
- name: Build
run: dotnet build src/Meezi.API/Meezi.API.csproj --no-restore -c Release
- name: Test
run: dotnet test --no-build -c Release --logger "console;verbosity=minimal"
# ── Admin API ───────────────────────────────────────────────────────────────
admin-api-build:
name: "CI · Admin API (dotnet build)"
runs-on: ubuntu-latest
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: ubuntu-latest
defaults:
run:
working-directory: web/dashboard
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_API_URL: http://localhost:5080
# ── Admin Web ───────────────────────────────────────────────────────────────
admin-web-check:
name: "CI · Admin Web (tsc)"
runs-on: ubuntu-latest
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: ubuntu-latest
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: ubuntu-latest
defaults:
run:
working-directory: web/finder
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_API_URL: http://localhost:5080
# ─────────────────────────────────────────────────────────────────────────────
# DEPLOY — only on push to main, only if ALL CI jobs pass
# ─────────────────────────────────────────────────────────────────────────────
deploy:
name: "Deploy · all services"
runs-on: ubuntu-latest
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: 40
steps:
- uses: actions/checkout@v4
# Write .env from Gitea secret
# Set it at: Gitea repo → Settings → Secrets → Actions → Add Secret
# Name: ENV_FILE
# Value: your full .env file content
- name: Write .env
run: printf '%s' "$ENV_FILE" > .env
env:
ENV_FILE: ${{ secrets.ENV_FILE }}
# ── 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
# ── 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
# ── Start / restart admin services ──────────────────────────────────────
- name: Start admin services
run: |
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 "✅ meezi-api healthy" && break
[ "$i" = "24" ] && echo "❌ meezi-api timeout" && docker compose logs --tail=40 api && exit 1
sleep 5
done
- 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 -f docker-compose.yml -f docker-compose.admin.yml ps
- name: Prune old images
if: success()
run: docker image prune -f