- Move the pnpm store, apk and .next caches into --mount=type=cache so
dependencies are shared across builds instead of duplicated in fresh
image layers (was the source of unbounded disk growth).
- Replace the deprecated --keep-storage prune flag in ci-deploy.sh with
the working --max-used-space=4g (buildx v0.37 renamed the flag). The
deprecated flag silently did nothing, so the BuildKit cache kept
growing unbounded (was 15.86GB); it is now capped at 4GB after every
deploy.
Runs the full catalog audit (runCatalogAudit) against the live hotel DB with
no repair/sql options — a pure read pass — and cross-checks the emitted
summary against independent DB + asset-dir measurements: row totals, duplicate
classname groups, orphaned catalog references and missing catalog / nitro /
icon counts must match exactly, with zero error events and a final
'batch_complete'.
Guarded by RUN_CATALOG_AUDIT_LIVE=1 so CI never runs it; loads the real .env
because vitest fakes DATABASE_URL.
generate-drizzle-schema.mjs imported 'dotenv/config' but dotenv is not a
dependency, failing knip and crashing 'pnpm db:schema:generate'. Load .env
with Node's built-in process.loadEnvFile like the other scripts do
(scripts/load-env.ts), never overriding vars already set in the shell.
- Create the runtime write targets (/app/storage, /app/public/nitro-assets,
/app/public/swf, /var/www/Gamedata) owned by UID/GID 33 in the runner image
so running without the bound volumes no longer hits ENOENT.
- Bake a HEALTHCHECK into the image so `docker run` (ci-deploy.sh) also reports
Docker-level health; compose can still override it with its own probe.
- Add the dockerfile:1 syntax pragma and ignore non-pnpm lockfiles so a stray
package-lock.json/yarn.lock can never taint the build context.
next.config.ts falls back to `git rev-parse HEAD`, but the build context has
no .git (excluded by .dockerignore), so every CI build printed fatal git
errors and stamped the release as "unknown". Pass the deploy commit sha as a
NEXT_DEPLOYMENT_ID build-arg so git is never invoked and the actual commit
reaches NEXT_PUBLIC_CMS_RELEASE and deploymentId.
The committed lockfile records overrides from pnpm-workspace.yaml. With the
narrower manifest COPY, pnpm install --frozen-lockfile ran without the
workspace file and failed with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH in CI.
Copy package.json, pnpm-lock, pnpm-workspace and .npmrc together so the
override config present in the lockfile is also supplied at install time.
- Use floating node:alpine that tracks the latest supported LTS; pnpm
bootstrap follows package.json's packageManager pin.
- Drop corepack (removed from node:26), install pnpm via npm global.
- Add pnpm fetch + offline install for stable dependency-layer caching.
- Run as non-root nextjs (UID/GID 33 = host www-data) with tini as PID 1
for correct signal handling.
- Open node engines to >=20.9.0 so patches/minors float automatically.
- Add docker-preflight.sh (per-VPS checks incl. --fix) and gate docker-update.sh
so Node major upgrades require explicit review while patches deploy silently.
The site-settings loader kept an in-process map forever after a Redis miss
and promoted DEFAULTS (no logo/theme) to Redis on any DB error, so a build
that started before the DB was reachable stuck the site on the preset logo
and default theme until a manual reload or full restart.
- Redis miss now reloads from the database instead of the stale in-process map
- a DB failure returns defaults only as an in-process last resort and never
writes them to Redis, so the shared cache can't be poisoned by a transient
error at startup
- regression tests: DB re-read on Redis miss after cache expiry, defaults never
promoted to Redis, recovery from transient DB failure
- fix(studio): stop markBatchDone infinite recursion so batches complete
- refactor(api): merge api-response into api and drop the duplicate module
- refactor(media): extract shared media loader and URL validator
- refactor(ui): extract shared LoadingSpinner for site and admin groups
- refactor(dates): consolidate raw date formatting into formatDate util
- refactor(logs): share a single generic log-list loader across tables
- refactor(theme): merge both ColorField components and reuse contrast helpers
- refactor(import): extract shared ImportErrorBanner and SearchInput
- chore(): remove dead theme-editor-tabs after inlining tab components