Skip to main content

LOCAL_DEV_SETUP — reporting-service

Sibling: DEPLOYMENT_TOPOLOGY · TESTING_STRATEGY · API_CONTRACTS


1. Prerequisites

  • Node.js 20.x (use volta install node@20).
  • pnpm 9+.
  • Docker 24+ with Compose v2.
  • Google Cloud SDK (gcloud) authenticated to the dev project (read-only roles only).
  • Make (optional but recommended).
  • 8 GB free RAM (Chromium needs headroom).

2. Clone & install

git clone https://github.com/ghasi-tech/ghasi-melmastoon.git
cd ghasi-melmastoon/services/reporting-service
pnpm install
cp .env.example .env.local

.env.local contains only emulator-targeted values (no real GCP secrets). It is git-ignored.


3. Local stack

docker-compose.dev.yml (in this folder) starts:

ServicePortImage
Postgres 165432postgres:16-alpine
Pub/Sub emulator8085gcr.io/google.com/cloudsdktool/cloud-sdk:emulators
GCS emulator (fake-gcs-server)4443fsouza/fake-gcs-server
Redis 76379redis:7-alpine
OTel collector4317, 4318otel/opentelemetry-collector-contrib
SigNoz (optional --profile=obs)3301signoz/signoz
pnpm dev:up # docker compose up -d
pnpm db:migrate # apply migrations to local Postgres
pnpm db:seed:dev # seed templates + 2 demo tenants (tnt_dev_a, tnt_dev_b)
pnpm dev # nest start --watch (api + worker via concurrently)

A clean re-start: pnpm dev:nuke && pnpm dev:up && pnpm db:migrate && pnpm db:seed:dev.


4. Stubbed dependencies

For local dev we stub upstream services rather than pull them in:

  • analytics-serviceMockAnalyticsClient returns canned rows from test/fixtures/analytics-rows/.
  • notification-serviceLoggingNotificationClient writes deliveries to stdout.
  • ai-orchestrator-serviceEchoAIClient returns deterministic placeholder callouts.
  • Regulatory adapters → FakeRegulatoryAdapter returns success after 500 ms (configurable per jurisdiction via .env.local).

To run against real upstream services in dev (rare), set USE_REAL_UPSTREAMS=true and provide service URLs/SA in .env.local.


5. Useful scripts

pnpm test # vitest unit + integration with emulators
pnpm test:domain # domain layer only (fast)
pnpm test:integration # integration suite with Testcontainers
pnpm test:renderer # PDF/XLSX/CSV golden-file suite
pnpm test:contract # event + REST contracts
pnpm lint && pnpm typecheck
pnpm db:make-migration <name> # scaffolds a new SQL migration
pnpm db:reset # drops & recreates local DB
pnpm openapi:generate # writes bin/openapi.yaml
pnpm cli -- run-now --tenant=tnt_dev_a --report=rep_dev_arrivals --formats=pdf,csv

6. Triggering scheduled runs locally

Cloud Scheduler is replaced with a local cron via cron package; pnpm dev:scheduler starts a tiny ticker that hits /internal/scheduler/fire for any active local schedule. You can also fire one manually:

curl -X POST http://localhost:8080/internal/scheduler/fire \
-H 'X-Tenant-Id: tnt_dev_a' \
-H 'X-Schedule-Id: sch_dev_arrivals' \
-H 'Authorization: Bearer dev-only'

Auth in dev mode bypasses real OIDC verification when NODE_ENV=development. Never ship that path: a hardcoded test in CI fails if the bypass branch is reachable in production builds.


7. Inspecting artifacts locally

fake-gcs-server exposes objects under http://localhost:4443/storage/v1/b/<bucket>/o/<object>. The pnpm cli artifacts list helper paginates artifacts for a tenant:

pnpm cli -- artifacts list --tenant=tnt_dev_a --limit=20
pnpm cli -- artifacts open --id=art_… # opens in default app

8. Debugging tips

  • VS Code launch config .vscode/launch.json includes "API: attach", "Worker: attach", "Vitest: current file".
  • Set LOG_LEVEL=debug to dump filter resolution and renderer step timings.
  • Set RENDERER_HEADFUL=true to launch Chromium with a visible window.
  • Pub/Sub emulator UI: gcloud pubsub topics list --project=fake-project --emulator-host=localhost:8085.

9. Common pitfalls

  • Chromium missing fonts → ensure pnpm dev:install-fonts ran (copies Noto + Vazirmatn into the local Chromium cache).
  • OOM during PDF tests → bump Docker memory to 8 GB.
  • RLS test failing locally but passing in CI → you forgot SET app.tenant_id. Use the withTenant() helper in test/support/db.ts.
  • Pub/Sub message stuck → emulator does not auto-ack; ensure your handler returns successfully or call messages ack manually.

Cross-references: TESTING_STRATEGY, API_CONTRACTS.