89d42184a1
Pipeline (.gitea/workflows/ci-cd.yml), all images/packages via Nexus mirror: - CI api-build: dotnet restore/build server/Hokm.slnx + run Hokm.Sim (rules). - CI web-check: npm install + tsc --noEmit + next build (static export). - deploy (self-hosted): pre-deploy pg_dump backup, rollback image tag, build, bring up db -> server -> web with stop+rm+up --no-deps (no force-recreate, no bare compose down), health-wait each, prune. Local stack (docker-compose.yml), ports in 1500-1600 so it coexists with manual dev on 3000/5005: web :1500 (nginx static) -> server :1505 (.NET) -> db :1510 (postgres, named volume + backups). Dockerfiles: server (.NET, NuGet via nuget.docker.config, binds 0.0.0.0, busybox wget healthcheck) + web (Next static export -> nginx, NEXT_PUBLIC_* baked as build args). nginx.conf SPA fallback. Config: server CORS is now config-driven (Cors__Origins) so the deployed web origin is allowed without code edits. deploy/ENV_FILE.example documents the Gitea ENV_FILE secret; DEPLOY.md covers setup/run/LAN-IP/rollback/migrations. Fonts: switch Vazirmatn + Plus Jakarta Sans from next/font/google (build-time Google fetch -> fails on the Iran CI runner) to self-hosted @fontsource-variable packages. Build is offline and ~3x faster; 7 woff2 emitted into out/. Verified locally: dotnet build slnx + Hokm.Sim (300 matches, exit 0); tsc clean; next build clean with self-hosted fonts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
86 lines
3.4 KiB
Markdown
86 lines
3.4 KiB
Markdown
# Deploy — Barg-e Vasat (Soroush CI/CD)
|
||
|
||
CI/CD runs on **Gitea Actions** (`git.soroushasadi.com`) with all packages and
|
||
base images pulled through the **Nexus mirror** (`mirror.soroushasadi.com`).
|
||
Pushing to `main` triggers build → deploy.
|
||
|
||
## Topology
|
||
|
||
| Service | Image | Container | Host port | Notes |
|
||
|---|---|---|---|---|
|
||
| Postgres | `postgres:16-alpine` | `hokm-db` | `1510` | named volume `hokm_db_data` |
|
||
| API (.NET SignalR) | `hokm-server:latest` | `hokm-server` | `1505` → 5005 | EF Core → Postgres |
|
||
| Web (static Next → nginx) | `hokm-web:latest` | `hokm-web` | `1500` → 80 | `NEXT_PUBLIC_*` baked at build |
|
||
|
||
Ports are in **1500–1600** on purpose, so the deployed stack runs alongside a
|
||
manual `npm run dev` (:3000) and `dotnet run` (:5005) without colliding.
|
||
|
||
## Pipeline (`.gitea/workflows/ci-cd.yml`)
|
||
|
||
1. **CI – API**: restore (Nexus NuGet) → `dotnet build server/Hokm.slnx` → run `Hokm.Sim` (engine rules validation).
|
||
2. **CI – Web**: `npm install` (Nexus npm) → `tsc --noEmit` → `next build` (static export).
|
||
3. **Deploy** (`self-hosted`, push to `main` only): backup DB → tag rollback image → build images → bring up `db` (wait healthy) → `server` (stop+rm+up, wait healthy) → `web` (stop+rm+up, wait healthy) → prune.
|
||
|
||
Deploy follows the safety rules: pre-deploy `pg_dump` backup to `/opt/hokm-backups`,
|
||
rollback tag before replace, explicit `stop + rm + up --no-deps` (no
|
||
`--force-recreate`, no bare `docker compose down`).
|
||
|
||
## One-time setup
|
||
|
||
1. **Secret**: fill `deploy/ENV_FILE.example` and paste into the Gitea repo secret
|
||
`ENV_FILE` at `.../HokmPlay/settings/secrets`. At minimum set `JWT_KEY`
|
||
(`openssl rand -hex 32`) and `POSTGRES_PASSWORD`.
|
||
2. **Runner**: an `act_runner` registered with both labels
|
||
(`ubuntu-latest:docker://...` for CI, `self-hosted:host` for deploy) — reused
|
||
from existing Soroush projects.
|
||
3. **Push**: `git push origin main` → watch `.../HokmPlay/actions`.
|
||
|
||
## Reaching the stack
|
||
|
||
- Same machine as the deploy host: open `http://localhost:1500`.
|
||
- Different machine (browser elsewhere): set `NEXT_PUBLIC_SERVER_URL` and
|
||
`CORS_ORIGINS` in `ENV_FILE` to the host **LAN IP** (e.g.
|
||
`http://172.28.144.1:1505` / `http://172.28.144.1:1500`) and push again —
|
||
the API URL is baked into the web bundle at build time. (localhost can be
|
||
hijacked by the VPN; prefer the LAN IP.)
|
||
|
||
## Local test (no Gitea, on your machine)
|
||
|
||
```bash
|
||
cd D:\Projects\hokm
|
||
copy deploy\ENV_FILE.example .env # then edit JWT_KEY / POSTGRES_PASSWORD
|
||
docker compose build server web
|
||
docker compose up -d
|
||
# web → http://localhost:1500 api → http://localhost:1505/
|
||
docker compose logs -f server
|
||
```
|
||
|
||
Tear down (keeps the DB volume):
|
||
```bash
|
||
docker compose stop
|
||
```
|
||
|
||
## Migrations
|
||
|
||
The server auto-applies EF migrations when any exist, else `EnsureCreated()`
|
||
(current state — no migration classes yet, so the Postgres schema is created on
|
||
first boot). When you generate them:
|
||
|
||
```bash
|
||
cd server/src/Hokm.Server
|
||
$env:HOKM_DESIGN_CONN="Host=localhost;Port=1510;Database=hokm;Username=hokm;Password=<pw>"
|
||
dotnet ef migrations add Init
|
||
```
|
||
|
||
Then the next deploy runs `Database.Migrate()` automatically.
|
||
|
||
## Rollback
|
||
|
||
```bash
|
||
docker stop hokm-server && docker rm hokm-server
|
||
docker run -d --name hokm-server --network hokm_default -p 1505:5005 \
|
||
--env-file <(grep -E '^(JWT_|Database__|ConnectionStrings__|Cors__|Zarinpal__)' .env) \
|
||
hokm-server:rollback
|
||
```
|
||
(or just revert the commit and push — CI redeploys the previous code.)
|