Files
soroush.asadi 89d42184a1
CI/CD / CI - API (dotnet build + engine sim) (push) Failing after 1m40s
CI/CD / CI - Web (tsc + next build) (push) Failing after 1m20s
CI/CD / Deploy - local stack (db + server + web) (push) Has been skipped
Add Soroush CI/CD (Gitea + Nexus) + self-host fonts for offline build
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>
2026-06-04 19:09:31 +03:30

86 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 **15001600** 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.)