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) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-26 15:43:23 +02:00
parent 7db881b026
commit bffb5be345
5 changed files with 43 additions and 6 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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