Files
edr-platform/checkpoint.md
2026-06-30 09:54:59 +00:00

8.7 KiB

Checkpoint

Major Tasks Completed

  1. Docker deployment scaffolded for all 6 apps in the monorepo.
  2. Split API images into app-specific Dockerfiles:
    • apps/edr-freight-api/Dockerfile
    • apps/edr-passenger-api/Dockerfile
  3. Kept shared Vite/nginx image:
    • infrastructure/docker/Dockerfile.web
    • infrastructure/nginx/spa.conf
  4. Updated docker-compose.yaml to run all 6 services (apps only, no Postgres service in compose).
  5. Added/updated deployment scripts:
    • scripts/deploy/create-npmrc.sh
    • scripts/deploy/sync-env-from-server.sh
  6. Added self-hosted GitHub Actions deployment workflow:
    • Consolidated into one file: .github/workflows/deploy.yml
  7. Deployment workflow now:
    • uses a single checkout (prepare job),
    • deploys services via parallel matrix,
    • sets compose project names per branch/environment,
    • passes explicit docker compose --project-name.
  8. Environment sync script now:
    • supports branch slug paths,
    • validates each service env file exists,
    • requires PORT in each env file,
    • exports per-service port vars to GITHUB_ENV.
  9. docker-compose.yaml now reads per-service ports via variables exported from env sync.
  10. Passenger startup flow fixed to run:
    • prisma:generate,
    • prisma:migrate,
    • prisma:seed, before API startup.
  11. Passenger seed TypeScript issues fixed in apps/edr-passenger-api/prisma/seed.ts so it compiles under strict checks.
  12. Added deployment runbook:
    • DEPLOYMENT.md

Passenger Web Migration to Next.js

  1. Passenger web apps migrated from Vite/SPA to Next.js:
    • Updated apps/edr-passenger-web/portal/next.config.js and apps/edr-passenger-web/backoffice/next.config.js:
      • Removed output: 'export' to enable server mode
      • Preserved transpilePackages for @edr/* shared packages
  2. Created dedicated Next.js Dockerfile:
    • infrastructure/docker/Dockerfile.passenger-web
    • Uses Node.js server (not nginx) for better Next.js support
    • Builds with turbo, runs npx next start in the final stage
    • Accepts build args: APP_PACKAGE, APP_PATH, NEXT_PUBLIC_API_URL
  3. Updated docker-compose.yaml:
    • passenger-portal and passenger-backoffice now use infrastructure/docker/Dockerfile.passenger-web
    • Port mappings are fully dynamic: both host and container ports use ${PASSENGER_PORTAL_PORT} / ${PASSENGER_BACKOFFICE_PORT}, driven by PORT in the service env file
    • NEXT_PUBLIC_API_URL build arg sourced directly from the service env file (no separate build env file needed)
  4. Updated DEPLOYMENT.md to reflect all of the above.

Port Mapping Fix (Latest)

  1. Fixed passenger web port mapping mismatch (0.0.0.0:8003->5184/tcp):
    • Container port was hardcoded (5174/5184); host port came from PORT in the env file via the sync script
    • Both sides of the mapping now use ${PASSENGER_PORTAL_PORT:-5174} / ${PASSENGER_BACKOFFICE_PORT:-5184}
    • Removed hardcoded PORT build arg from docker-compose.yaml (runtime env_file supplies it to Next.js)

NEXT_PUBLIC_API_URL Build-Time Fix (Latest)

  1. Fixed passenger web apps using localhost:4000 instead of the configured API URL:
    • Root cause: NEXT_PUBLIC_* vars are baked into the JS bundle at build time; setting them in the runtime env_file has no effect
    • sync-env-from-server.sh now extracts any NEXT_PUBLIC_* vars from the service .env and writes them to GITHUB_ENV before the build step
    • docker-compose.yaml build arg renamed from PASSENGER_NEXT_PUBLIC_API_URL to NEXT_PUBLIC_API_URL to match the key used in the service env files directly

Key Files to Review

  • .github/workflows/deploy.yml
  • docker-compose.yaml
  • scripts/deploy/sync-env-from-server.sh
  • scripts/deploy/create-npmrc.sh
  • apps/edr-passenger-api/docker-entrypoint.sh
  • apps/edr-passenger-api/prisma/seed.ts
  • infrastructure/docker/Dockerfile.passenger-web (NEW)
  • apps/edr-freight-api/Dockerfile (MODIFIED — pnpm store cache)
  • apps/edr-passenger-api/Dockerfile (MODIFIED — prisma generate in /deploy + pnpm store cache)
  • apps/edr-payment-api/Dockerfile (MODIFIED — pnpm store cache)
  • infrastructure/docker/Dockerfile.web (MODIFIED — pnpm store cache)
  • apps/edr-passenger-web/portal/next.config.js (MODIFIED)
  • apps/edr-passenger-web/backoffice/next.config.js (MODIFIED)
  • DEPLOYMENT.md (MODIFIED)

Backoffice Pages — Completion

  1. All backoffice pages are now fully implemented and connected to the API:
    • live/page.tsx — replaced stub with real LiveTrackingPage using liveApi (trips, crowd signals, delay/status stats)
    • notifications/page.tsx — replaced hardcoded mock + broken Table import with real page using notificationsApi (templates list, send form, notification history tab)

Prisma Client Missing After pnpm deploy (Latest)

  1. Fixed passenger API crash in Docker (TypeError: Cannot convert undefined or null to object at class-validator IsEnum, triggered by dist/modules/fare-engine/currency.dto.js):
    • Root cause: currency.dto.ts imports the Currency enum (a runtime value) from @prisma/client. The generated Prisma client is an output of prisma generate, not a package in the pnpm store, so pnpm deploy did not copy it into /deploy. At runtime Currency resolved to undefined@IsEnum(undefined)Object.entries(undefined) throws at module load.
    • Prisma 6 + pnpm writes the client to node_modules/.pnpm/@prisma+client@.../node_modules/.prisma/client, not root node_modules/.prisma. The old cp rescue in the Dockerfile guarded on [ -d node_modules/.prisma ] (root) which never existed → silently skipped.
    • Fix in apps/edr-passenger-api/Dockerfile: replaced the broken cp with RUN cd /deploy && npm run prisma:generate after pnpm deploy, regenerating the client into the exact runtime-resolve path (/deploy/node_modules/.prisma/client). Safe because deploy has no --prod flag (so the prisma CLI ships) and package.json declares the schema path.
    • Affected 16 passenger-api files importing from @prisma/client; currency.dto.js just loaded first. payment-api unaffected (TypeORM, no Prisma).

pnpm Store Build Cache Fix (Latest)

  1. Fixed Docker builds re-downloading all dependencies every pipeline run:
    • Root cause: install steps used --mount=type=cache,id=pnpm,target=/pnpm/store, but nothing set pnpm's store-dir to /pnpm/store. Default store (~/.local/share/pnpm/store) was never under the mount → BuildKit cached an empty dir → full re-download each build. The two web Dockerfiles had the mount but it was dead; the two API Dockerfiles (freight, payment) had no mount at all.
    • Fix: added ENV PNPM_HOME="/pnpm" (+ PATH) to the base stage of all 5 Dockerfiles so the store resolves to /pnpm/store, matching the mount. Added the cache mount to every pnpm install and pnpm deploy step that lacked it.
    • Files: apps/edr-freight-api/Dockerfile, apps/edr-passenger-api/Dockerfile, apps/edr-payment-api/Dockerfile, infrastructure/docker/Dockerfile.web, infrastructure/docker/Dockerfile.passenger-web.
    • Caveat: BuildKit cache mounts live on the runner host; persists only while the same self-hosted runner/builder is reused and not pruned (docker builder prune wipes it).

Next Actions

  1. Run full CI on all target branches (main, dev, staging) and verify matrix job behavior.
  2. Validate server env directory layout matches script expectations:
    • /home/<deploy_user>/environment/edr/<branch-slug>/<project>/...
  3. Confirm each service env file includes valid PORT and service-specific runtime vars.
  4. Verify branch-specific compose project names produce isolated containers/networks/volumes on runner.
  5. Smoke test all 6 deployed services behind real environment URLs.

Open Risks / Notes

  1. Passenger seed runs on every container start; confirm this is desired for production-like environments.
  2. Prisma warns about package.json#prisma deprecation (Prisma 7 migration pending).
  3. Matrix parallelism increases runner load; ensure self-hosted runner capacity is sufficient.
  4. Port collisions are prevented by env-driven mapping, but bad env values can still cause runtime conflicts.
  5. Passenger web uses Next.js server mode (not static export):
    • Requires Node.js at runtime (previously could use pure static hosting)
    • NEXT_PUBLIC_API_URL must be set in the service env file (passenger-portal.env / passenger-backoffice.env) — the sync script forwards it to the build automatically
    • Each portal/backoffice instance runs its own Node.js process (watch container memory usage)
  6. Freight web still uses Vite+nginx (different from passenger web) — maintain both Dockerfiles separately