From 24a59c6e931ea168f9a3577a98531efaf0e84041 Mon Sep 17 00:00:00 2001 From: Linus Olofsson Date: Fri, 6 Nov 2026 05:18:14 +0100 Subject: [PATCH] Portfolio sync: a photo that fails no longer stops the others; sharp accepts pixel-shift and 15000 px squares Seen on the first run on Cleura 2026-11-06: 13 photos tagged since 2026-09-29 were never synced. portfolio-sync.mjs sets exit code 1 when one photo fails (DSC00342_PSMS16-square.jpg: "Input image exceeds pixel limit", sharp's default 268 MP) and set -e then stopped before commit/push - on Nurem as well. Now the photos that worked are committed and built, the run still ends with exit 1 so systemd shows it, and sharp's limit is 1 000 MP (JPEGs shrink while decoding; the container gets 3 GB). Co-Authored-By: Claude Opus 5.5 --- deploy/cleura/portfolio-sync.sh | 11 +++++++++-- scripts/portfolio-sync.mjs | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/deploy/cleura/portfolio-sync.sh b/deploy/cleura/portfolio-sync.sh index 8c68b5c..0e4e2e9 100644 --- a/deploy/cleura/portfolio-sync.sh +++ b/deploy/cleura/portfolio-sync.sh @@ -54,10 +54,13 @@ git -C "$DIR" checkout -q -B main origin/main git -C "$DIR" reset -q --hard origin/main echo "[sync] scripts/portfolio-sync.mjs" -docker run --rm --memory 2g --cpus 2 --network bridge \ +# portfolio-sync.mjs exits 1 when a single photo fails but still writes the others; those are committed below, and the +# run ends with exit 1 so systemd shows that something needs a look (journalctl -u portfolio-sync). +SYNC_RC=0 +docker run --rm --memory 3g --cpus 2 --network bridge \ -e IMMICH_URL -e IMMICH_API_KEY -e PORTFOLIO_TAG_ID \ -v "$DIR":/app --mount type=tmpfs,destination=/app/.git -w /app "$NODE" \ - sh -c 'npm install --no-audit --no-fund --loglevel=error >/dev/null && node scripts/portfolio-sync.mjs' + sh -c 'npm install --no-audit --no-fund --loglevel=error >/dev/null && node scripts/portfolio-sync.mjs' || SYNC_RC=$? if git -C "$DIR" status --porcelain -- src/assets/images/portfolio | grep -q .; then git -C "$DIR" add -A src/assets/images/portfolio @@ -69,3 +72,7 @@ if git -C "$DIR" status --porcelain -- src/assets/images/portfolio | grep -q .; else echo "[sync] no changes" fi +if [ "$SYNC_RC" != 0 ]; then + echo "[sync] WARNING: portfolio-sync.mjs exited $SYNC_RC - some photos failed (see the lines with '!' above)" + exit "$SYNC_RC" +fi diff --git a/scripts/portfolio-sync.mjs b/scripts/portfolio-sync.mjs index b7ee02f..8810c43 100644 --- a/scripts/portfolio-sync.mjs +++ b/scripts/portfolio-sync.mjs @@ -77,7 +77,9 @@ function destName(asset) { async function downloadAndResize(asset, destPath) { const res = await api("GET", `/assets/${asset.id}/original`); const buf = Buffer.from(await res.arrayBuffer()); - await sharp(buf) + // Pixel shift and the 15000 px Instagram squares can exceed sharp's default limit (268 MP). JPEGs are shrunk while + // they are decoded, so memory stays low; the sync container still has a memory cap. + await sharp(buf, { limitInputPixels: 1_000_000_000 }) .rotate() // respektera EXIF-orientering .resize(MAX_DIM, MAX_DIM, { fit: "inside", withoutEnlargement: true }) .withMetadata() // BEVARA EXIF (kritiskt för portfolions datum/kamera)