Skip to content

Releases: epheterson/immich-apple-silicon

Immich Accelerator v1.4.7

Choose a tag to compare

@github-actions github-actions released this 17 Apr 16:01
84f2320

Fixes

  • Homebrew formula failed to install on every release since v1.4.4 (#31). The CI workflow that generates the formula used a bash heredoc containing backticks and em-dashes. Backticks triggered command substitution on the runner, em-dashes got mangled through the locale. Brew's Ruby installer rejected the resulting invalid UTF-8. Replaced with plain ASCII.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.6

Choose a tag to compare

@github-actions github-actions released this 17 Apr 02:24
3f306dc

Fixes

  • ML service silently failed to start after brew upgrade (#29). Config stored a versioned Cellar path for ml_dir which gets deleted on upgrade. cmd_start and cmd_watch now auto-resolve ml_dir via the stable /opt/homebrew/opt/ symlink on every run. Warns loudly when the ML venv is missing instead of silently skipping.
  • Dashboard showed "Idle" while Immich was processing (#28). The /api/jobs call had a 2s timeout that caused intermittent failures under load, and errors were silently swallowed. Dashboard now shows the actual error when the API is unreachable, displays queue counts matching Immich's admin panel, and bumps the timeout to 5s.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.5

Choose a tag to compare

@github-actions github-actions released this 15 Apr 16:34
d637549

Fixes

  • Database backups were silently 0 bytes (#24). Immich pipes pg_dump through gzip --rsyncable, which Apple's BSD gzip doesn't support. pg_dump_shim.js now reroutes those calls to Homebrew's GNU gzip (or strips the flag as fallback). The formula now depends_on "gzip" so fresh installs get GNU gzip automatically.
  • Watchdog could kill unrelated processes. _kill_stale_processes matched any command line containing the substring immich. Replaced with precise patterns for the canonical worker (node … dist/main.js) and ML service (python -m src.main) launch shapes.

Test infrastructure

  • Isolated E2E Immich stack (scripts/e2e-stack.yml + e2e-stack.sh). Dedicated postgres / redis / api-only Immich server on port-shifted loopback addresses with throwaway state. The VM harness now requires this stack and refuses to run against prod Immich.
  • Real-data backup integration test that runs pg_dump | gzip --rsyncable through the shim against the isolated Postgres and asserts the output is a valid non-empty pg_dump.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.4

Choose a tag to compare

@github-actions github-actions released this 15 Apr 07:21
09d4f1b

Fixes

  • Homebrew formula pulled node 25, breaking sharp on every fresh install: v1.4.x shipped with depends_on "node" in the generated formula. Homebrew's default node formula tracks mainline (currently 25.x), but Immich 2.7.x pins engines.node = 24.14.1 and sharp@0.34.5's native addons fail to load on node 25 with a NODE_MODULE_VERSION mismatch. Every fresh brew install immich-accelerator + immich-accelerator start hit an opaque worker crash at require('sharp') mid-Nest-bootstrap that looked like an Immich bug. Fix: pin depends_on "node@22" in the formula template and teach find_node() to look under /opt/homebrew/opt/node@22/bin/node (keg-only — no /opt/homebrew/bin symlink).
  • find_node() accepted unsupported node majors silently: previously it returned the first node binary it found, regardless of version. Now filters to SUPPORTED_NODE_MAJORS = (22, 24) and installs node@22 if nothing compatible is present.
  • _rebuild_sharp() swallowed rebuild failures: logged log.error and returned, letting the worker start and crash later with an unrelated-looking stack. Now raises RuntimeError with the rebuild stderr tail and a remediation pointing at brew install node@22.

Upgrade resilience (catches future drift)

  • Node preflight in start: every immich-accelerator start now re-resolves node via find_node(), updates config["node"] if the path changed, and compares against Immich's engines.node parsed from package.json. Catches the brew upgrade drift pattern where node silently jumps majors and breaks sharp, with a clear "install node@22" error before the worker ever spawns.
  • Sharp load preflight in start: spawns node -e "require('sharp')" against the server dir. If it fails, auto-attempts a rebuild and retries. If the retry still fails, hard-errors with remediation. This turns "opaque worker crash 10+ seconds into Nest bootstrap" into a 1-second clearly-labeled check.

Test coverage

  • tests/test_fresh_install.py::TestNodeVersionPreflight — 11 new unit tests covering _node_major_version, find_node version filtering, _check_node_engines_compat with real stubbed node binaries, _verify_sharp_loads error reporting, and a static check that the CI-generated Homebrew formula pins node@22.
  • scripts/e2e-fresh-install.sh step 1b — asserts find_node() on a real VM returns a node in SUPPORTED_NODE_MAJORS. Would have caught the v1.4.x regression on the first E2E run.
  • scripts/e2e-fresh-install.sh step 3b — runs the full sharp preflight (_check_node_engines_compat + _verify_sharp_loads) against the extracted Immich server in the VM.
  • scripts/e2e-fresh-install.sh steps 9–16 — real execution coverage: start ML in STUB_MODE, hit /ping + /health + /predict for actual JSON render (catches any ORJSONResponse regression), run immich-accelerator ml-test against the stub, verify the NODE_OPTIONS pg_dump shim actually loads in a real node process, start the real worker and wait for the Immich Microservices is running Nest-bootstrap marker, run the dashboard against the live worker and confirm worker.alive=true, verify the status subcommand reports the running PID, verify stop cleanly terminates + is idempotent, verify a second start after stop reaches Nest bootstrap again.
  • scripts/e2e-bootstrap-vm.sh — installs node@22 instead of Homebrew-default node, sets up the /build synthetic firmlink via dual /etc/synthetic.d/ + /etc/synthetic.conf entries (some macOS VM images only honor the legacy location), reboots the VM to activate the firmlink, and verifies /build resolves post-reboot before saving the base snapshot. pip install now retries 3× on VM DNS flakes.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.3

Choose a tag to compare

@github-actions github-actions released this 15 Apr 02:43
fb70da0

Fixes

  • NODE_OPTIONS shim path broken in v1.4.2 (#24 follow-up): The v1.4.2 commit that "polished" the pg_dump shim wrapping wrapped the path in single quotes, thinking Node would unquote them. Node doesn't — it splits NODE_OPTIONS on whitespace and takes the literal characters. The quotes became part of the filename and every worker start failed with Cannot find module ''/opt/homebrew/Cellar/…/pg_dump_shim.js''. Fix: wrap the path in double quotes, which is the only form Node's NODE_OPTIONS tokenizer honors universally (single quotes and backslash escapes both fail — both verified empirically against Node 25.2). Verified end-to-end against a real v1.4.2 brew install on an M4 Mac — shim loads, pg_dump (PostgreSQL) 18.3 runs.
  • ORJSONResponse crash in ML service (#20 tail): The v1.3.4 commit dropped orjson from ml/requirements.txt with an incorrect commit message claiming "not imported by our code." main.py imports ORJSONResponse from fastapi.responses and uses it in 3 places, and FastAPI's ORJSONResponse.render() asserts orjson is not None at render time — every /predict request crashed with AssertionError: orjson must be installed to use ORJSONResponse. Fix: swap to stdlib-backed JSONResponse, keeping the orjson drop (which was correct — its wheel broke Homebrew's dylib fixup). Verified end-to-end: ml-test passes 4/4 on real CLIP + OCR requests with no orjson in the venv.

Regression guards (test coverage the v1.4.2 VM E2E didn't have)

  • Static check: ml/src uses ORJSONResponse only if ml/requirements.txt pins orjson — would have caught the v1.3.4 half-fix instantly.
  • Real-node integration: generate the exact NODE_OPTIONS string cmd_start builds, spawn node --require against a sentinel shim, assert it loads. Would have caught the v1.4.2 quoting bug before merge.
  • Static check: cmd_start's shim-path escaping uses backslash form, not shell quoting.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.2

Choose a tag to compare

@github-actions github-actions released this 14 Apr 02:42
934a963

Fixes

  • Path-mismatch probe false positive (#19 follow-up): The v1.4.1 split-setup probe queried /api/libraries as its primary signal, but that endpoint only returns external libraries in Immich 2.7+ — the upload library (where web-UI uploads land) is implicit at IMMICH_MEDIA_LOCATION and doesn't appear there. Result: any install with an external library plus a correctly-set upload_mount got blocked at immich-accelerator start with a false "path mismatch" error. The probe now parses an upload-library asset's originalPath (filtering libraryId: null) and skips external-library assets entirely. If no upload assets exist yet, the check is skipped — nothing to compare against.
  • External library path validation: The probe now also checks every external library's importPath against the Mac filesystem. Missing paths produce a non-fatal warning per library with the library name and guidance to mount or synthetic-link them. Upload-library mismatch remains fatal (thumbnails WILL 404), external-library inaccessibility is advisory (worker can still process uploads + any libraries whose paths do resolve).
  • pg_dump ENOENT on database backup (#24): Immich's DatabaseBackupService hardcodes /usr/lib/postgresql/${version}/bin/pg_dump in its dist, and on macOS that path doesn't exist, so the native microservices worker fails every backup cycle with ENOENT. /usr/lib/ is SIP-protected and there's no env-var escape hatch in Immich's code. Fix: a tiny Node runtime shim (immich_accelerator/hooks/pg_dump_shim.js) that monkey-patches child_process.spawn/spawnSync/execFile to rewrite the Linux postgres client path to /opt/homebrew/opt/libpq/bin/ at call time. The shim is preloaded via NODE_OPTIONS=--require … when we launch the worker. Immich's JS source on disk is never touched — the same interposition pattern we already use for the ffmpeg wrapper, applied at the Node module layer. Verified end-to-end on a real Mac with node + libpq 18.3.

Docs

  • Split deployment clarity: Reworked the Split deployment section of the README to lead with the one requirement everyone needs to get right — both machines see the same files at the same absolute paths via a shared filesystem (NFS/SMB). There is no HTTP transport of thumbnails between hosts; the worker reads/writes directly to disk. Surfaced because a v1.4.1 user interpreted "match paths" as string matching. Also dropped the long-stale v0.x and v1.2.x migration sections.

Test infrastructure

  • VM bootstrap script: Fixed three edge cases that kept the tart-based E2E harness from running cleanly — trap composition bug that left stale VMs behind, stdin-race on heredoc-over-ssh that silently dropped pip install commands, and brew update network flakiness aborting bootstrap. The harness is now proven end-to-end against live Immich.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.1

Choose a tag to compare

@github-actions github-actions released this 12 Apr 23:00
7b781ab

Fresh-install fixes

  • Dashboard ModuleNotFoundError (#17): Homebrew formula wrapper now runs the CLI under the ML venv's Python instead of stock python@3.11. The dashboard's lazy fastapi/uvicorn imports now resolve on any fresh Mac — previously they only worked if the user happened to have the packages installed globally. Also added a brew test block that force-loads dashboard.create_app so this class of bug gets caught at audit time, not in the wild.
  • Missing corePlugin on OCI download (#18): Re-fix of a regression from the v1.3.3 fix. The layer loop had a size_mb < 1 early-break shortcut that fired before examining the current layer — stranding the tiny corePlugin COPY layer. Replaced with a version-aware break (_has_everything) that requires corePlugin/manifest.json for Immich 2.7+. Verified end-to-end against a live ghcr.io pull.

Test coverage

  • Added tests/test_fresh_install.py — unit tests for the layer-break logic, a static check that fastapi/uvicorn stay pinned in ml/requirements.txt, an AST check that dashboard.py has no top-level third-party imports, and a slow integration test that builds a pristine venv and confirms create_app works with only fastapi+uvicorn installed.
  • CI now runs on macOS 14 (Apple Silicon) in addition to Ubuntu. The fresh-install-macos job catches "works on my machine" bugs before shipping.

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it

Immich Accelerator v1.4.0

Choose a tag to compare

@github-actions github-actions released this 09 Apr 15:13
2fa6051
  • libpq as Homebrew dependency: psql now installed automatically via depends_on "libpq" in the formula — works for both new installs and upgrades, not just setup.
  • Published GitHub releases: Releases are now published automatically (not draft).

Upgrade

brew upgrade immich-accelerator
immich-accelerator setup   # if first time or new features require it