Commit Graph

40 Commits

Author SHA1 Message Date
soroush.asadi bafbfbcadf ci: fix Trust step crash in sh — replace pipefail with POSIX set -eu
CI/CD / CI · API (dotnet build + test) (push) Failing after 18s
CI/CD / CI · Admin API (dotnet build) (push) Failing after 17s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 36s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Has been skipped
Gitea act runner v0.6.1 ignores `shell: bash` step overrides and always
executes with `sh -e {0}`. The `set -euo pipefail` on line 2 caused sh to
exit immediately with "Illegal option -o pipefail" before any curl/openssl
ran. Replace with POSIX-compatible `set -eu` in both api-build and
admin-api-build trust steps so the diagnostic curl output is finally visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:28:52 +03:30
soroush.asadi 206cd7d3c3 ci: fix Trust step — add shell: bash (act runner defaults to sh, no pipefail)
CI/CD / CI · API (dotnet build + test) (push) Successful in 43s
CI/CD / CI · Admin API (dotnet build) (push) Failing after 2s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m6s
CI/CD / CI · Admin Web (tsc) (push) Successful in 38s
CI/CD / CI · Website (tsc) (push) Successful in 45s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Has been skipped
set -euo pipefail is bash-only; Gitea act runner used sh by default so
the step crashed on line 1 before curl even ran. Adding shell: bash
lets the step actually execute and surface the real AIA/cert output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:17:54 +03:30
soroush.asadi 7b77bb4722 ci: verbose diagnostic Trust step to pinpoint PartialChain cause
CI/CD / CI · API (dotnet build + test) (push) Failing after 3s
CI/CD / CI · Admin API (dotnet build) (push) Failing after 2s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m6s
CI/CD / CI · Admin Web (tsc) (push) Successful in 37s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Has been skipped
Previous attempt used curl -sf which silently swallows failures, so
we never knew if ISRG Root YR was actually fetched. This run:
  • set -euo pipefail  → step fails fast and loudly on any error
  • curl -v            → shows connection result / error in log
  • openssl verify     → confirms cert bundle is good before restore
  • openssl s_client   → shows full chain verify against live mirror

If the AIA URL (http://yr.i.lencr.org/) is unreachable from the
runner, the step will fail HERE rather than silently at dotnet restore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:09:18 +03:30
soroush.asadi 1db8a8f08c fix(ci): fetch ISRG Root YR root cert at build time + belt-and-suspenders
CI/CD / CI · API (dotnet build + test) (push) Failing after 3m35s
CI/CD / CI · Admin API (dotnet build) (push) Failing after 6m23s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m6s
CI/CD / CI · Admin Web (tsc) (push) Successful in 37s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Has been skipped
The prior Trust step added only the YR2 intermediate to the OS trust
store. dotnet's X.509 chain builder requires a self-signed ROOT as the
trust anchor (it does not enable OpenSSL's X509_V_FLAG_PARTIAL_CHAIN),
so intermediate-only still caused PartialChain.

New approach (two jobs: api-build, admin-api-build):
  1. curl http://yr.i.lencr.org/ (plain HTTP AIA) → ISRG Root YR DER
     → convert to PEM → add to /usr/local/share/ca-certificates/
  2. cp YR2 intermediate (docker/nexus-mirror-ca.crt) → same dir
  3. update-ca-certificates  (OS method)
  4. cat both certs >> /etc/ssl/certs/ca-certificates.crt
     (belt-and-suspenders: directly appends to the OpenSSL bundle
      dotnet reads on Linux, works even if step 3 is a no-op)

If the AIA fetch fails (network block) step 4 still appends the
intermediate, which may work if dotnet ever enables partial chains.
Fetch failure is non-fatal (echo warning + continue).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 07:34:52 +03:30
soroush.asadi 9a27858125 ci: trust Nexus mirror CA in backend dotnet restore (fixes skipped deploys)
The mirror's Let's Encrypt cert renewed under the new ISRG Root YR root,
which isn't in the dotnet SDK image's trust store. `dotnet restore` validates
TLS and fails (NU1301 / unable to get local issuer certificate), so both
backend CI jobs fail and the deploy is skipped. The npm jobs are unaffected
because they already pass --strict-ssl=false.

Pin the mirror's intermediate (CN=YR2, CA:TRUE, valid to Sept 2028) and add it
as a trust anchor before restore in:
- CI api-build + admin-api-build jobs (.gitea/workflows/ci-cd.yml)
- docker/api/Dockerfile + docker/admin-api/Dockerfile (deploy image builds)

Also set NUGET_CERT_REVOCATION_MODE=offline in the CI restore steps to avoid
CRL/OCSP fetches to lencr.org (filtered from Iran).

Permanent fix is server-side (re-chain to ISRG Root X1 or update trust stores);
this unblocks CI/deploys without depending on that.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 23:22:57 +03:30
soroush.asadi dc07eb9594 ci: prune dangling images after successful deploy
CI/CD / CI · API (dotnet build + test) (push) Successful in 58s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 1m1s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Successful in 23s
Removes <none>-tagged images left over from previous builds.
Only affects untagged images (dangling=true) — never touches other
projects' named images (soroushasadi-site, drsousan, etc.).
Also logs disk usage after prune.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 15:35:18 +03:30
soroush.asadi c3ca39ed15 fix(ci): staged deploy with crash detection and full diagnostics
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m4s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 35s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 54s
CI/CD / Deploy · all services (push) Successful in 22s
- Start api alone first; web/admin-api each wait for their own step
  so a health-check wait never blocks unrelated services
- Detect crash-loops via RestartCount > 1 (restart:unless-stopped hides
  the exited state behind rapid restarts — count is reliable)
- Dump up to 120 lines of api logs immediately on crash/timeout
- Log infra network state (json) in attach step + failure dump so we
  can see exactly which aliases are registered on meezi_default
- admin-api and admin-web are now started in separate steps, same pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:44:52 +03:30
soroush.asadi dac59cd180 fix(ci): use --alias when connecting infra to meezi_default network
CI/CD / CI · API (dotnet build + test) (push) Successful in 44s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 47s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Successful in 1m36s
Without --alias, meezi-db joins meezi_default but is only reachable
as "meezi-db". The API uses Host=postgres — DNS lookup fails after
~5s, migration throws, container crashes.

Fix: disconnect first, then reconnect with service-name aliases
so "postgres" and "redis" resolve correctly on meezi_default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:36:03 +03:30
soroush.asadi c3ea07d6e4 fix(ci): attach infra containers to meezi_default network before deploy
CI/CD / CI · API (dotnet build + test) (push) Successful in 40s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 36s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m2s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Failing after 10s
postgres/redis were created before the compose project name was locked
to "meezi", so they're on a different Docker network. New app containers
join meezi_default — the API crashes immediately because it can't reach
Host=postgres.

Fix: create meezi_default if needed, then docker network connect
meezi-db and meezi-redis to it before starting the app containers.

Also dump API and admin-api logs on failure to make future failures
easier to diagnose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 08:39:35 +03:30
soroush.asadi 9f002433c7 fix(ci): explicitly stop old app containers before redeploy
CI/CD / CI · API (dotnet build + test) (push) Successful in 39s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 31s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m3s
CI/CD / CI · Admin Web (tsc) (push) Successful in 34s
CI/CD / CI · Website (tsc) (push) Successful in 43s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Failing after 7s
Existing containers lack compose project labels so Compose cannot claim
them — it tries to CREATE alongside them and hits a name conflict.

Fix: stop + rm only the 6 meezi app containers by name before compose up.
Postgres, redis, and all other projects are never touched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 08:08:19 +03:30
soroush.asadi 631cac8c3c fix(ci): never touch postgres/redis in deploy — app containers only
CI/CD / CI · API (dotnet build + test) (push) Successful in 54s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 45s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m3s
CI/CD / CI · Admin Web (tsc) (push) Has been cancelled
CI/CD / CI · Website (tsc) (push) Has been cancelled
CI/CD / CI · Koja (tsc) (push) Has been cancelled
CI/CD / Deploy · all services (push) Has been cancelled
The meezi-redis container was created before the name:meezi label existed
in docker-compose.yml, so Compose doesn't recognise it as its own project
container and tries to CREATE a new one, causing the name conflict.

Real fix: postgres and redis are persistent infrastructure — CI should
never restart them. Remove them from all deploy steps entirely.
Only api, web, website, koja, admin-api, admin-web are cycled on deploy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 07:56:16 +03:30
soroush.asadi 1a6a0dc495 fix(ci): split infra vs app services to prevent redis name conflict
CI/CD / CI · API (dotnet build + test) (push) Successful in 43s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 31s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m4s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 49s
CI/CD / Deploy · all services (push) Failing after 10s
docker compose up without --no-recreate tries to recreate postgres/redis
when it detects a config change or finds a stopped container, which causes
"container name already in use" when the container is still running.

Fix: infrastructure (postgres, redis) uses --no-recreate so a healthy
container is never touched. App services (api, web, website, koja,
admin-api, admin-web) use --force-recreate so freshly-built images are
always applied.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 07:47:07 +03:30
soroush.asadi ae5896d440 fix: credentials lost on refresh + admin UI improvements + CI safe deploy
CI/CD / CI · API (dotnet build + test) (push) Successful in 39s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 30s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m2s
CI/CD / CI · Admin Web (tsc) (push) Failing after 35s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 48s
CI/CD / Deploy · all services (push) Has been skipped
- dashboard layout: wait for Zustand _hasHydrated before redirecting to /login
  (was redirecting on first render before localStorage was read)
- admin shell: same fix using new _hasHydrated on admin auth store
- admin-auth.store: add _hasHydrated + onRehydrateStorage to mirror merchant store
- AdminPlansScreen: replace direct cache mutation with per-plan PlanCard component
  that owns its own useState — fixes other plans disappearing after save
- AdminSettingsScreen: detect boolean values and render iOS-style Toggle switches
- AdminIntegrationsScreen: replace all <input type=checkbox> with Toggle switches;
  replace OpenAI model text input with <select> dropdown (gpt-4o-mini/4o/4-turbo/4/3.5)
- blog editor: fix form never syncing existing post data into state (editing was broken);
  all fields now use local form state, save uses form directly
- blog links: fix broken relative hrefs (website/blog/new → /admin/website/blog/new)
  and back button using proper Link components
- ci-cd: remove image prune step entirely — never removes containers or images

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:56:16 +03:30
soroush.asadi aec5b21f98 fix: lock compose project name to 'meezi', scope image prune to meezi only
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m40s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 1m22s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m0s
CI/CD / CI · Admin Web (tsc) (push) Successful in 33s
CI/CD / CI · Website (tsc) (push) Successful in 43s
CI/CD / CI · Koja (tsc) (push) Successful in 47s
CI/CD / Deploy · all services (push) Failing after 2s
Prevents runner workspace collisions with other projects (DrSousan etc.)
causing containers to be treated as orphans and stopped on deploy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 23:45:07 +03:30
soroush.asadi a9222590ac CI CD 3
CI/CD / CI · API (dotnet build + test) (push) Successful in 41s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 34s
CI/CD / CI · Admin Web (tsc) (push) Successful in 35s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m44s
CI/CD / CI · Website (tsc) (push) Successful in 5m27s
CI/CD / CI · Koja (tsc) (push) Successful in 4m16s
CI/CD / Deploy · all services (push) Failing after 1m19s
2026-05-31 11:36:48 +03:30
soroush.asadi aec68eff34 CI CD 2 2026-05-31 11:31:05 +03:30
soroush.asadi 345ae0a4b5 first commit
CI/CD / CI · Admin API (dotnet build) (push) Successful in 41s
CI/CD / CI · Admin Web (tsc) (push) Failing after 5s
CI/CD / CI · Website (tsc) (push) Failing after 4s
CI/CD / CI · Koja (tsc) (push) Failing after 5s
CI/CD / CI · API (dotnet build + test) (push) Successful in 1m13s
CI/CD / CI · Dashboard (tsc) (push) Failing after 2m32s
CI/CD / Deploy · all services (push) Has been skipped
2026-05-31 11:06:24 +03:30
soroush.asadi 51e422272d bugfix : remove orphan 2026-05-30 09:42:32 +03:30
soroush.asadi 8ca2cae988 Pull Docker images from Nexus connector port 8087
The Docker daemon reaches the Nexus Docker group over the dedicated
connector port 8087 (its registry mirror), not the main 8081 HTTP port,
which caused HTTPS-to-HTTP pull failures in CI. Repoint all image refs to
171.22.25.73:8087 at the connector root; npm and NuGet stay on 8081.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 05:17:21 +03:30
soroush.asadi e8cd6d3282 Route all package mirrors through local Nexus
Point Docker, NuGet, and npm pulls at the Nexus group repos on
171.22.25.73:8081 for both CI/CD and local builds, so the pipeline and
developers no longer depend on Docker Hub, MCR, nuget.org, or npmjs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 00:28:07 +03:30
soroush.asadi 289c808257 Rename public discovery app from "finder" to "koja"
Rebrand the public café-discovery app: directories web/finder→web/koja and
docker/finder→docker/koja, plus all service wiring (docker-compose, Caddy
subdomain koja.meezi.ir, env vars KOJA_PORT / NEXT_PUBLIC_KOJA_URL, CI
workflows) and the app's display name (Koja / کجا).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:02:22 +03:30
soroush.asadi aa4612e06b fix: use Liara mirrors directly for images with Nexus OCI proxy issues
- aspnet:10.0, postgres:16-alpine, redis:7-alpine all fail on first
  fetch through Nexus proxy (OCI manifest format bug in Nexus)
- Change DOTNET_ASPNET_IMAGE default to mcr-mirror.liara.ir directly
- Change postgres/redis service images to docker-mirror.liara.ir
- CI service containers (api-build job) also use Liara directly
- All images parameterized so ENV_FILE can override for any registry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 22:08:07 +03:30
soroush.asadi 25154f9dd9 fix(ci): set PATH in deploy job so docker binary is found
act runner (host mode) inherits a minimal PATH from the process
environment — docker is not found even though it is installed.
Explicitly include all standard locations plus /snap/bin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 19:28:15 +03:30
soroush.asadi cb80afaf42 fix(ci): replace actions/checkout@v4 in deploy job with shell git
Node.js is not in PATH on the self-hosted:host runner, so JS actions
(actions/checkout@v4) fail with "cannot find node". Use the same shell
git init/fetch/checkout pattern used in all other jobs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 18:57:58 +03:30
Soroush.Asadi f717c02467 Merge branch 'main' of https://github.com/codesoroush/Meezi 2026-05-28 18:34:56 +03:30
soroush.asadi 539165b6bb fix(ci): replace python3 with cat heredoc; sync local registry IPs
python3 is not in PATH inside dotnet/sdk:10.0 container — replace the
"Write NuGet config" step with a cat heredoc which works in any container.

Also syncs GitHub with the Gitea-side changes:
  - All images pulled from local Nexus mirrors (no internet round-trip)
      171.22.25.73:5000 → docker-hub-proxy (node, postgres, redis)
      171.22.25.73:5002 → mcr-proxy        (dotnet/sdk)
  - npm steps already on npm-group (Liara + Runflare fallback)
  - docker-compose.mirror.yml: expose port 5002 for mcr-proxy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 18:34:06 +03:30
Soroush.Asadi 37afa965e7 ci : workflow updated 12 2026-05-28 18:08:49 +03:30
soroush.asadi 720bab457e feat(mirror): add Liara npm/PyPI/Ubuntu APT mirrors to Nexus
Adds mirrors/nexus/add-liara-mirrors.sh that provisions:
  - npm-liara-proxy  → https://package-mirror.liara.ir/repository/npm/
  - npm-group        → npm-liara-proxy + npm-proxy (Liara first, Runflare fallback)
  - pypi-liara-proxy → https://package-mirror.liara.ir/repository/pypi/
  - pypi-group       → pypi-liara-proxy + pypi-proxy
  - ubuntu-proxy     → http://linux-mirror.liara.ir/repository/ubuntu/
  - ubuntu-security-proxy → http://linux-mirror.liara.ir/repository/ubuntu-security/

Also updates CI npm install steps to use npm-group instead of npm-proxy
so all four Node.js jobs benefit from the Liara-first, Runflare-fallback
group from day one.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:35:01 +03:30
soroush.asadi f825c72ca2 perf(ci): replace apk add git with Gitea archive API for Node.js jobs
apk add git downloads from dl-cdn.alpinelinux.org (Fastly CDN) which is
slow/blocked in Iran — caused 6m+ checkout times.

New approach: wget the repo tarball from Gitea's archive API endpoint.
wget + tar (busybox) are already in node:20-alpine — no package install.
Gitea is on the same machine as the runner = download is instant.

GET /api/v1/repos/{owner}/{repo}/archive/{sha}.tar.gz
Authorization: Bearer {token}

dotnet/sdk jobs unchanged — Debian base has git pre-installed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:12:49 +03:30
soroush.asadi ca17cffee6 fix(ci): write NuGet config inline to allow HTTP source (NU1302)
NuGet 10 blocks HTTP sources by default. allowInsecureConnections=true
must be set in a config file — the --source CLI flag doesn't support it.

Write the config to /tmp/nuget.ci.config inline in the step so there is
no dependency on any file existing in the workspace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:55:19 +03:30
soroush.asadi 32d9900e07 fix(ci): use --source flag instead of --configfile for NuGet restore
--configfile nuget.mirror.config fails when the file isn't present in
the workspace (e.g. when Gitea is behind GitHub on commits).

--source inline URL is simpler, self-contained, and replaces all
configured sources — no extra file dependency in CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:39:36 +03:30
soroush.asadi 61e44c63ab refactor(mirror): replace 3 services with single Nexus Repository Manager
Consolidates BaGet + Verdaccio + registry:2 into one Sonatype Nexus OSS
instance with a REST API provisioning script.

docker-compose.mirror.yml: single nexus service, ports 8081 (UI/NuGet/npm)
  and 8083 (Docker Hub pull-through proxy)
mirrors/nexus/provision.sh: idempotent setup — changes admin password,
  enables anonymous access, creates nuget-proxy / npm-proxy / docker-hub-proxy
nuget.mirror.config: updated source URL to Nexus NuGet proxy endpoint
ci-cd.yml: updated npm --registry to Nexus npm proxy endpoint

Run once on server: docker compose -f docker-compose.mirror.yml up -d
  then: ./mirrors/nexus/provision.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:35:55 +03:30
soroush.asadi 6f85cfe4d3 feat(infra): add local pull-through mirrors for NuGet, npm, Docker Hub
docker-compose.mirror.yml:
  - BaGet  (port 5101) → proxies nuget.org
  - Verdaccio (port 4873) → proxies npmjs.com
  - registry:2 (port 5100) → proxies Docker Hub

nuget.mirror.config: points dotnet restore at http://mirror:5101
mirrors/verdaccio/config.yaml: open reads, upstream npmjs fallback

CI workflow:
  - All container jobs: --add-host=mirror:host-gateway
  - dotnet restore --configfile nuget.mirror.config
  - npm install --registry http://mirror:4873

First run: packages fetched from upstream through the VPS.
All subsequent runs: served from local disk, no CDN needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:31:12 +03:30
soroush.asadi c452df8988 fix(ci): add --add-host=gitea:host-gateway to all container jobs
github.server_url returns 'http://gitea:3000' (Gitea ROOT_URL using Docker
service name). CI job containers run on an isolated network and can't resolve
the 'gitea' hostname.

host-gateway maps to the Docker bridge IP (172.17.0.1). Gitea publishes
port 3000 on all interfaces, so http://gitea:3000 becomes reachable inside
every job container via the bridge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:59:45 +03:30
soroush.asadi 8ddb427edd fix(ci): replace actions/checkout with shell git for container jobs
actions/checkout@v4 is a JS action executed inside the job container:
- dotnet/sdk:10.0 has no Node.js  → exit 127
- node:20-alpine  has no git      → checkout fails

Fix: manual git clone via shell using http.extraheader for token auth.
Token never appears in process list or git log. deploy job (self-hosted:host)
keeps actions/checkout — the act_runner image has both node and git.

Also removes defaults.run.working-directory from Node.js jobs (the checkout
step must start in workspace root, not web/<app>).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:46:34 +03:30
soroush.asadi 6c868f5f30 fix(ci): use docker:// runner mode with pre-built SDK images
Switch CI jobs to container: image: overrides so jobs run inside official
SDK containers (dotnet/sdk:10.0, node:20-alpine) instead of the bare
runner container. This bypasses blocked CDN downloads for dotnet/node.

Deploy job stays on self-hosted:host where Docker CLI is available.
Update workflow comments to explain the required runner label config:
  ubuntu-latest:docker://node:20-alpine (CI jobs)
  self-hosted:host (deploy)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:27:49 +03:30
soroush.asadi dcddcf77d6 Fix Gitea CI stuck at setup-dotnet/setup-node due to blocked CDNs
Root cause: actions/setup-dotnet@v4 downloads .NET from
download.visualstudio.microsoft.com and actions/setup-node@v4 downloads
Node from nodejs.org — both CDNs are blocked from Iran so jobs hang at 0s.

Fix:
- All .NET jobs: add container: mcr.microsoft.com/dotnet/sdk:10.0
  so .NET is already inside the image — no download needed.
  Remove actions/setup-dotnet step entirely.
- All Node.js jobs: add container: node:20-alpine
  so Node/npm are already inside the image — no download needed.
  Remove actions/setup-node step entirely.
- api-build: add postgres + redis service containers + env vars so
  dotnet test can actually connect to a database (was silently failing).
- deploy job: change back to runs-on: self-hosted
  ubuntu-latest containers don't have Docker CLI — docker compose
  commands would fail immediately. Deploy MUST run on the server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:08:42 +03:30
soroush.asadi 9ed305e5bd ci: change all runners from self-hosted to ubuntu-latest 2026-05-27 23:55:26 +03:30
soroush.asadi 284920544b 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 <noreply@anthropic.com>
2026-05-27 23:53:49 +03:30
soroush.asadi 64b488ac89 ci: add Gitea Actions workflow (CI + self-hosted deploy)
.gitea/workflows/ci-cd.yml:
- Triggers on push to main and PRs
- CI jobs: dotnet build/test, dashboard tsc, finder tsc (all self-hosted)
- Deploy job: only on push to main, needs all CI jobs to pass
  - Writes .env from ENV_FILE secret (set in Gitea repo settings)
  - docker compose build --parallel with BuildKit
  - Rolling restart (postgres/redis untouched)
  - Health-check poll: waits up to 2min for meezi-api healthy
  - Auto-prunes old images on success

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 23:21:29 +03:30