mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 12:41:04 +00:00
fix: add docker cache for pnpm installations
This commit is contained in:
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
FROM node:24.15.0-alpine AS base
|
FROM node:24.15.0-alpine AS base
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
# Store pnpm's content-addressable store under PNPM_HOME so the BuildKit
|
||||||
|
# `--mount=type=cache,target=/pnpm/store` cache actually persists deps across builds.
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -14,6 +18,7 @@ FROM base AS installer
|
|||||||
COPY --from=pruner /app/out/json/ .
|
COPY --from=pruner /app/out/json/ .
|
||||||
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
||||||
RUN --mount=type=secret,id=npmrc,target=./.npmrc,required=false \
|
RUN --mount=type=secret,id=npmrc,target=./.npmrc,required=false \
|
||||||
|
--mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile
|
||||||
|
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
@@ -23,7 +28,8 @@ RUN pnpm turbo build --filter="@edr/freight-api..."
|
|||||||
|
|
||||||
FROM base AS deployer
|
FROM base AS deployer
|
||||||
COPY --from=builder /app/ .
|
COPY --from=builder /app/ .
|
||||||
RUN pnpm deploy --filter="@edr/freight-api" --prod --legacy /deploy
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm deploy --filter="@edr/freight-api" --prod --legacy /deploy
|
||||||
|
|
||||||
FROM node:24.15.0-alpine AS runner
|
FROM node:24.15.0-alpine AS runner
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
# `migration` stage, invoked as a one-shot container in CI before deploy.
|
# `migration` stage, invoked as a one-shot container in CI before deploy.
|
||||||
FROM node:24.15.0-alpine AS base
|
FROM node:24.15.0-alpine AS base
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
# Put the pnpm content-addressable store under PNPM_HOME so the BuildKit
|
||||||
|
# `--mount=type=cache,target=/pnpm/store` below actually persists it across
|
||||||
|
# builds. Without this, pnpm stores in ~/.local/share/pnpm/store and the
|
||||||
|
# cache mount is a no-op — deps re-download on every pipeline run.
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
FROM base AS pruner
|
FROM base AS pruner
|
||||||
@@ -22,7 +28,8 @@ RUN pnpm --filter "@edr/passenger-api" exec prisma generate
|
|||||||
RUN pnpm turbo build --filter="@edr/passenger-api..."
|
RUN pnpm turbo build --filter="@edr/passenger-api..."
|
||||||
FROM base AS deployer
|
FROM base AS deployer
|
||||||
COPY --from=builder /app/ .
|
COPY --from=builder /app/ .
|
||||||
RUN pnpm deploy --filter="@edr/passenger-api" --legacy /deploy
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm deploy --filter="@edr/passenger-api" --legacy /deploy
|
||||||
# The generated Prisma client is NOT in the pnpm store (it's an output of
|
# The generated Prisma client is NOT in the pnpm store (it's an output of
|
||||||
# `prisma generate`), so `pnpm deploy` does not copy it into /deploy. Regenerate
|
# `prisma generate`), so `pnpm deploy` does not copy it into /deploy. Regenerate
|
||||||
# it here so the runtime enum values imported from @prisma/client (Currency, …)
|
# it here so the runtime enum values imported from @prisma/client (Currency, …)
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
# Build from monorepo root: docker build -f apps/edr-payment-api/Dockerfile .
|
# Build from monorepo root: docker build -f apps/edr-payment-api/Dockerfile .
|
||||||
FROM node:24.15.0-alpine AS base
|
FROM node:24.15.0-alpine AS base
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
# Store pnpm's content-addressable store under PNPM_HOME so the BuildKit
|
||||||
|
# `--mount=type=cache,target=/pnpm/store` cache actually persists deps across builds.
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
FROM base AS pruner
|
FROM base AS pruner
|
||||||
@@ -11,6 +15,7 @@ FROM base AS installer
|
|||||||
COPY --from=pruner /app/out/json/ .
|
COPY --from=pruner /app/out/json/ .
|
||||||
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
|
||||||
RUN --mount=type=secret,id=npmrc,target=./.npmrc,required=false \
|
RUN --mount=type=secret,id=npmrc,target=./.npmrc,required=false \
|
||||||
|
--mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
COPY --from=installer /app/ .
|
COPY --from=installer /app/ .
|
||||||
@@ -18,7 +23,8 @@ COPY --from=pruner /app/out/full/ .
|
|||||||
RUN pnpm turbo build --filter="@edr/payment-api..."
|
RUN pnpm turbo build --filter="@edr/payment-api..."
|
||||||
FROM base AS deployer
|
FROM base AS deployer
|
||||||
COPY --from=builder /app/ .
|
COPY --from=builder /app/ .
|
||||||
RUN pnpm deploy --filter="@edr/payment-api" --prod --legacy --ignore-scripts /deploy
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm deploy --filter="@edr/payment-api" --prod --legacy --ignore-scripts /deploy
|
||||||
|
|
||||||
# --- Migration image: built in CI, run as a one-shot `docker run --rm --env-file ...`
|
# --- Migration image: built in CI, run as a one-shot `docker run --rm --env-file ...`
|
||||||
# against the real DB, as its own gated step *before* the app image is built/deployed.
|
# against the real DB, as its own gated step *before* the app image is built/deployed.
|
||||||
|
|||||||
@@ -75,6 +75,10 @@
|
|||||||
- `apps/edr-passenger-api/docker-entrypoint.sh`
|
- `apps/edr-passenger-api/docker-entrypoint.sh`
|
||||||
- `apps/edr-passenger-api/prisma/seed.ts`
|
- `apps/edr-passenger-api/prisma/seed.ts`
|
||||||
- `infrastructure/docker/Dockerfile.passenger-web` (NEW)
|
- `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/portal/next.config.js` (MODIFIED)
|
||||||
- `apps/edr-passenger-web/backoffice/next.config.js` (MODIFIED)
|
- `apps/edr-passenger-web/backoffice/next.config.js` (MODIFIED)
|
||||||
- `DEPLOYMENT.md` (MODIFIED)
|
- `DEPLOYMENT.md` (MODIFIED)
|
||||||
@@ -85,6 +89,22 @@
|
|||||||
- `live/page.tsx` — replaced stub with real LiveTrackingPage using `liveApi` (trips, crowd signals, delay/status stats)
|
- `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)
|
- `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)
|
||||||
|
|
||||||
|
20. 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)
|
||||||
|
|
||||||
|
21. 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
|
## Next Actions
|
||||||
|
|
||||||
1. Run full CI on all target branches (`main`, `dev`, `staging`) and verify matrix job behavior.
|
1. Run full CI on all target branches (`main`, `dev`, `staging`) and verify matrix job behavior.
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ ARG NEXT_PUBLIC_API_URL
|
|||||||
|
|
||||||
FROM node:24.15.0-alpine AS base
|
FROM node:24.15.0-alpine AS base
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
# Store pnpm's content-addressable store under PNPM_HOME so the BuildKit
|
||||||
|
# `--mount=type=cache,target=/pnpm/store` cache actually persists deps across builds.
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -45,7 +49,8 @@ RUN pnpm turbo build --filter="${APP_PACKAGE}..."
|
|||||||
FROM base AS deployer
|
FROM base AS deployer
|
||||||
ARG APP_PACKAGE
|
ARG APP_PACKAGE
|
||||||
COPY --from=builder /app/ .
|
COPY --from=builder /app/ .
|
||||||
RUN pnpm deploy --filter="${APP_PACKAGE}" --prod --legacy /deploy
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm deploy --filter="${APP_PACKAGE}" --prod --legacy /deploy
|
||||||
|
|
||||||
FROM node:24.15.0-alpine AS runner
|
FROM node:24.15.0-alpine AS runner
|
||||||
ARG APP_PATH
|
ARG APP_PATH
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ ARG NEXT_PUBLIC_API_URL=http://localhost:4000
|
|||||||
|
|
||||||
FROM node:24.15.0-alpine AS base
|
FROM node:24.15.0-alpine AS base
|
||||||
RUN apk add --no-cache libc6-compat
|
RUN apk add --no-cache libc6-compat
|
||||||
|
# Store pnpm's content-addressable store under PNPM_HOME so the BuildKit
|
||||||
|
# `--mount=type=cache,target=/pnpm/store` cache actually persists deps across builds.
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user