From bffb5be3455586fe8b6435aaaba11faf8ddc58e1 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 26 May 2026 15:43:23 +0200 Subject: [PATCH] build(web): supply Verdaccio npm auth to SvelteKit builds via BuildKit secret The sveltekit-base build (and the mana-web / manavoxel-web app builds on top of it) run `pnpm install` with no .npmrc in the build context, so private @mana/* packages resolved against registry.npmjs.org and 404'd (e.g. @mana/shared-icons@1.0.0, which only lives on npm.mana.how). It had been coasting on a warm pnpm cache; once sveltekit-base:local was gone the rebuild hard-failed. Mount the host ~/.npmrc (registry map + resolved _authToken) as a BuildKit secret at /root/.npmrc in all three pnpm-install steps. Token never lands in an image layer. build-app.sh passes it via --secret for the base build; docker compose build reads it from the top-level secrets: entry. Unblocks every managarten web rebuild (incl. the pending umami-removal). Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/mana/apps/web/Dockerfile | 3 ++- apps/manavoxel/apps/web/Dockerfile | 3 ++- docker-compose.macmini.yml | 14 ++++++++++++++ docker/Dockerfile.sveltekit-base | 9 +++++++-- scripts/mac-mini/build-app.sh | 20 ++++++++++++++++++-- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/apps/mana/apps/web/Dockerfile b/apps/mana/apps/web/Dockerfile index e76c3bca6..8b6ed69c9 100644 --- a/apps/mana/apps/web/Dockerfile +++ b/apps/mana/apps/web/Dockerfile @@ -21,7 +21,8 @@ COPY packages/cards-core ./packages/cards-core COPY packages/shared-crypto ./packages/shared-crypto COPY packages/website-blocks ./packages/website-blocks -RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ +RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \ + --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ pnpm install --no-frozen-lockfile --ignore-scripts WORKDIR /app/apps/mana/apps/web diff --git a/apps/manavoxel/apps/web/Dockerfile b/apps/manavoxel/apps/web/Dockerfile index 08f959fee..46ed7b29e 100644 --- a/apps/manavoxel/apps/web/Dockerfile +++ b/apps/manavoxel/apps/web/Dockerfile @@ -12,7 +12,8 @@ ENV PUBLIC_SYNC_SERVER_URL=$PUBLIC_SYNC_SERVER_URL COPY apps/manavoxel/packages/shared ./apps/manavoxel/packages/shared COPY apps/manavoxel/apps/web ./apps/manavoxel/apps/web -RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ +RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \ + --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ pnpm install --no-frozen-lockfile --ignore-scripts WORKDIR /app/apps/manavoxel/apps/web diff --git a/docker-compose.macmini.yml b/docker-compose.macmini.yml index bca29d9ce..e5f99b245 100644 --- a/docker-compose.macmini.yml +++ b/docker-compose.macmini.yml @@ -63,6 +63,8 @@ services: build: context: . dockerfile: apps/mana/apps/web/Dockerfile + secrets: + - npmrc args: PUBLIC_SYNC_SERVER_URL: wss://sync.mana.how image: mana-web:local @@ -178,6 +180,8 @@ services: build: context: . dockerfile: apps/manavoxel/apps/web/Dockerfile + secrets: + - npmrc image: manavoxel-web:local container_name: mana-app-manavoxel-web restart: always @@ -320,3 +324,13 @@ services: # ~/projects/mana/services/mana-news-pool/, eigene DB `mana_news_pool`). # mana-api/news/routes.ts proxied auf MANA_NEWS_POOL_URL. +# Build-time secrets (BuildKit). Not mounted into running containers. +secrets: + # Verdaccio (@mana:registry=npm.mana.how) auth for private @mana/* + # packages during web-app builds. Sourced from the build host's + # ~/.npmrc (registry mapping + resolved _authToken). Mounted via + # --mount=type=secret in the SvelteKit Dockerfiles, so the token + # never lands in an image layer. See docs/MAC_MINI_SERVER.md. + npmrc: + file: ${HOME}/.npmrc + diff --git a/docker/Dockerfile.sveltekit-base b/docker/Dockerfile.sveltekit-base index 0e27dfd57..5dd0dba8e 100644 --- a/docker/Dockerfile.sveltekit-base +++ b/docker/Dockerfile.sveltekit-base @@ -71,8 +71,13 @@ COPY packages/shared-llm ./packages/shared-llm COPY packages/shared-ai ./packages/shared-ai COPY packages/cards-core ./packages/cards-core -# Install dependencies (shared packages only - app deps added later) -RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ +# Install dependencies (shared packages only - app deps added later). +# The npmrc secret carries the Verdaccio (@mana:registry=npm.mana.how) +# auth token so private @mana/* packages resolve — without it pnpm falls +# back to registry.npmjs.org and 404s on e.g. @mana/shared-icons. Mounted +# as a BuildKit secret so the token never lands in an image layer. +RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \ + --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ pnpm install --no-frozen-lockfile --ignore-scripts # Ensure all @mana workspace packages are linked in node_modules diff --git a/scripts/mac-mini/build-app.sh b/scripts/mac-mini/build-app.sh index d7374d275..402477455 100755 --- a/scripts/mac-mini/build-app.sh +++ b/scripts/mac-mini/build-app.sh @@ -25,6 +25,22 @@ DOCKER="${DOCKER_CMD:-/usr/local/bin/docker}" # 2026-04-23; this flag keeps it that way. COMPOSE_ARGS=(-f "$COMPOSE_FILE" --env-file "$ENV_FILE") +# BuildKit is required for the --mount=type=secret in the SvelteKit +# Dockerfiles (Verdaccio @mana token). `docker compose build` (v2) enables +# it by default and reads the secret from the compose top-level `secrets:`; +# the classic `docker build` for the base image needs it set explicitly. +export DOCKER_BUILDKIT=1 + +# Source for the `npmrc` build secret: registry mapping + resolved +# Verdaccio _authToken so private @mana/* packages resolve during the base +# image build. Without it pnpm falls back to registry.npmjs.org and 404s on +# e.g. @mana/shared-icons. Defaults to the build host's ~/.npmrc. +NPMRC_SECRET="${NPMRC_SECRET:-$HOME/.npmrc}" +if [ ! -f "$NPMRC_SECRET" ]; then + echo "WARN: npmrc secret not found at $NPMRC_SECRET — @mana/* auth will" \ + "fail during the sveltekit-base build (set NPMRC_SECRET)." >&2 +fi + # Minimum free memory (in MB) needed for a Docker build BUILD_MEM_THRESHOLD_MB=3000 @@ -116,7 +132,7 @@ stop_monitoring_now() { build_base_images() { echo "=== Building sveltekit-base image ===" - $DOCKER build -f "$PROJECT_ROOT/docker/Dockerfile.sveltekit-base" -t sveltekit-base:local "$PROJECT_ROOT" + $DOCKER build --secret id=npmrc,src="$NPMRC_SECRET" -f "$PROJECT_ROOT/docker/Dockerfile.sveltekit-base" -t sveltekit-base:local "$PROJECT_ROOT" echo "sveltekit-base:local built." echo "" } @@ -187,7 +203,7 @@ build_services() { echo "=== Rebuilding sveltekit-base (stale: newer commit touches packages/) ===" echo " Triggering commit: $last_commit" fi - $DOCKER build -f "$PROJECT_ROOT/docker/Dockerfile.sveltekit-base" -t sveltekit-base:local "$PROJECT_ROOT" + $DOCKER build --secret id=npmrc,src="$NPMRC_SECRET" -f "$PROJECT_ROOT/docker/Dockerfile.sveltekit-base" -t sveltekit-base:local "$PROJECT_ROOT" echo "" fi break