nsg / immich-distribution

Experimental Immich distribution inside a snap
MIT License
25 stars 0 forks source link

Bump v1.95.0 #155

Closed github-actions[bot] closed 7 months ago

github-actions[bot] commented 7 months ago

This PR bumps the version from v1.94.1 to v1.95.0. Please review the changes and merge this PR if everything looks good.

Upstream release notes

Monitored upstream files

diff --git a/server/src/infra/migrations/1688392120838-AddLibraryTable.ts b/server/src/infra/migrations/1688392120838-AddLibraryTable.ts
index 53a6f780b..4d394adaf 100644
--- a/server/src/infra/migrations/1688392120838-AddLibraryTable.ts
+++ b/server/src/infra/migrations/1688392120838-AddLibraryTable.ts
@@ -24,7 +24,8 @@ export class AddLibraries1688392120838 implements MigrationInterface {
     );

     // Create default library for each user and assign all assets to it
-    const userIds: string[] = (await queryRunner.query(`SELECT id FROM "users"`)).map((user: any) => user.id);
+    const users = await queryRunner.query(`SELECT id FROM "users"`);
+    const userIds: string[] = users.map((user: any) => user.id);

     for (const userId of userIds) {
       await queryRunner.query(
diff --git a/server/src/infra/migrations/1700713871511-UsePgVectors.ts b/server/src/infra/migrations/1700713871511-UsePgVectors.ts
index 9f8a72cff..008d5eadc 100644
--- a/server/src/infra/migrations/1700713871511-UsePgVectors.ts
+++ b/server/src/infra/migrations/1700713871511-UsePgVectors.ts
@@ -1,11 +1,13 @@
 import { getCLIPModelInfo } from '@app/domain/smart-info/smart-info.constant';
 import { MigrationInterface, QueryRunner } from 'typeorm';
+import { vectorExt } from '@app/infra/database.config';

 export class UsePgVectors1700713871511 implements MigrationInterface {
   name = 'UsePgVectors1700713871511';

   public async up(queryRunner: QueryRunner): Promise<void> {
-    await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS vectors`);
+    await queryRunner.query(`SET search_path TO "$user", public, vectors`);
+    await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS ${vectorExt}`);
     const faceDimQuery = await queryRunner.query(`
         SELECT CARDINALITY(embedding::real[]) as dimsize
         FROM asset_faces
@@ -14,7 +16,7 @@ export class UsePgVectors1700713871511 implements MigrationInterface {

     const clipModelNameQuery = await queryRunner.query(`SELECT value FROM system_config WHERE key = 'machineLearning.clip.modelName'`);
     const clipModelName: string = clipModelNameQuery?.[0]?.['value'] ?? 'ViT-B-32__openai';
-    const clipDimSize = getCLIPModelInfo(clipModelName.replace(/"/g, '')).dimSize;
+    const clipDimSize = getCLIPModelInfo(clipModelName.replaceAll('"', '')).dimSize;

     await queryRunner.query(`
         ALTER TABLE asset_faces 
diff --git a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts
index 7a1a1144d..c3716cc19 100644
--- a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts
+++ b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts
@@ -1,16 +1,20 @@
 import { MigrationInterface, QueryRunner } from 'typeorm';
+import { vectorExt } from '../database.config';
+import { DatabaseExtension } from '@app/domain/repositories/database.repository';

 export class AddCLIPEmbeddingIndex1700713994428 implements MigrationInterface {
   name = 'AddCLIPEmbeddingIndex1700713994428';

   public async up(queryRunner: QueryRunner): Promise<void> {
+    if (vectorExt === DatabaseExtension.VECTORS) {
+      await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
+    }
+    await queryRunner.query(`SET search_path TO "$user", public, vectors`);
+
     await queryRunner.query(`
       CREATE INDEX IF NOT EXISTS clip_index ON smart_search
-      USING vectors (embedding cosine_ops) WITH (options = $$
-      [indexing.hnsw]
-      m = 16
-      ef_construction = 300
-      $$);`);
+      USING hnsw (embedding vector_cosine_ops)
+      WITH (ef_construction = 300, m = 16)`);
   }

   public async down(queryRunner: QueryRunner): Promise<void> {
diff --git a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts
index 0ac7b0cd4..066303530 100644
--- a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts
+++ b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts
@@ -1,16 +1,20 @@
 import { MigrationInterface, QueryRunner } from 'typeorm';
+import { vectorExt } from '../database.config';
+import { DatabaseExtension } from '@app/domain/repositories/database.repository';

 export class AddFaceEmbeddingIndex1700714033632 implements MigrationInterface {
   name = 'AddFaceEmbeddingIndex1700714033632';

   public async up(queryRunner: QueryRunner): Promise<void> {
+    if (vectorExt === DatabaseExtension.VECTORS) {
+      await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
+    }
+    await queryRunner.query(`SET search_path TO "$user", public, vectors`);
+
     await queryRunner.query(`
       CREATE INDEX IF NOT EXISTS face_index ON asset_faces
-      USING vectors (embedding cosine_ops) WITH (options = $$
-      [indexing.hnsw]
-      m = 16
-      ef_construction = 300
-      $$);`);
+      USING hnsw (embedding vector_cosine_ops)
+      WITH (ef_construction = 300, m = 16)`);
   }

   public async down(queryRunner: QueryRunner): Promise<void> {
diff --git a/server/src/infra/migrations/1707000751533-AddVectorsToSearchPath.ts b/server/src/infra/migrations/1707000751533-AddVectorsToSearchPath.ts
new file mode 100644
index 000000000..e83e4b4fb
--- /dev/null
+++ b/server/src/infra/migrations/1707000751533-AddVectorsToSearchPath.ts
@@ -0,0 +1,14 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class AddVectorsToSearchPath1707000751533 implements MigrationInterface {
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    const res = await queryRunner.query(`SELECT current_database() as db`);
+    const databaseName = res[0]['db'];
+    await queryRunner.query(`ALTER DATABASE ${databaseName} SET search_path TO "$user", public, vectors`);
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    const databaseName = await queryRunner.query(`SELECT current_database()`);
+    await queryRunner.query(`ALTER DATABASE ${databaseName} SET search_path TO "$user", public`);
+  }
+}
diff --git a/server/src/infra/migrations/1708227417898-AddFileCreatedAtIndex.ts b/server/src/infra/migrations/1708227417898-AddFileCreatedAtIndex.ts
new file mode 100644
index 000000000..f7ca40cd4
--- /dev/null
+++ b/server/src/infra/migrations/1708227417898-AddFileCreatedAtIndex.ts
@@ -0,0 +1,12 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class AddFileCreatedAtIndex1708227417898 implements MigrationInterface {
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`CREATE INDEX idx_asset_file_created_at ON assets ("fileCreatedAt")`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`DROP INDEX idx_asset_file_created_at`);
+    }
+}
diff --git a/server/Dockerfile b/server/Dockerfile
index 4c9b92d5b..9a7fc31fa 100644
--- a/server/Dockerfile
+++ b/server/Dockerfile
@@ -1,5 +1,5 @@
 # dev build
-FROM ghcr.io/immich-app/base-server-dev:20240130@sha256:a11ac5c56f0ccce1f218954c07c43caadf489557252ba5b9ca1c5977aaa25999 as dev
+FROM ghcr.io/immich-app/base-server-dev:20240213@sha256:16646a37bae065b51e68cb2ba7a63027b29504d43a30644625382afbe326114a as dev

 RUN apt-get install --no-install-recommends -yqq tini
 WORKDIR /usr/src/app
@@ -24,7 +24,7 @@ RUN npm prune --omit=dev --omit=optional
 COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img

 # web build
-FROM node:iron-alpine3.18 as web
+FROM node:iron-alpine3.18@sha256:a02826c7340c37a29179152723190bcc3044f933c925f3c2d78abb20f794de3f as web

 WORKDIR /usr/src/open-api/typescript-sdk
 COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
@@ -40,7 +40,7 @@ RUN npm run build

 # prod build
-FROM ghcr.io/immich-app/base-server-prod:20240130@sha256:ce23a32154540b906df3c971766bcd991561c60331794e0ebb780947ac48113f
+FROM ghcr.io/immich-app/base-server-prod:20240213@sha256:61d159d069c5b522f16de9733fb79feb0e82c0b099d16f026196f344d12a1e5e

 WORKDIR /usr/src/app
 ENV NODE_ENV=production \
@@ -59,4 +59,4 @@ COPY LICENSE /LICENSE
 ENV PATH="${PATH}:/usr/src/app/bin"
 VOLUME /usr/src/app/upload
 EXPOSE 3001
-ENTRYPOINT ["tini", "--", "/bin/sh"]
+ENTRYPOINT ["tini", "--", "/bin/bash"]
diff --git a/server/start-server.sh b/server/start-server.sh
index acbbb82b9..7ef959f63 100755
--- a/server/start-server.sh
+++ b/server/start-server.sh
@@ -1,2 +1,3 @@
-#!/usr/bin/env sh
+#!/usr/bin/env bash
+
 ./start.sh immich
diff --git a/server/start-microservices.sh b/server/start-microservices.sh
index efdafaac0..c9e2cb42f 100755
--- a/server/start-microservices.sh
+++ b/server/start-microservices.sh
@@ -1,2 +1,3 @@
-#!/usr/bin/env sh
+#!/usr/bin/env bash
+
 ./start.sh microservices

Error, web/README.md do not exists

diff --git a/web/Dockerfile b/web/Dockerfile
index 16ce7ac97..27d206e92 100644
--- a/web/Dockerfile
+++ b/web/Dockerfile
@@ -1,5 +1,6 @@
-FROM node:iron-alpine3.18
+FROM node:iron-alpine3.18@sha256:a02826c7340c37a29179152723190bcc3044f933c925f3c2d78abb20f794de3f

+RUN apk add --no-cache tini
 USER node
 WORKDIR /usr/src/app
 COPY --chown=node:node package*.json ./
@@ -8,3 +9,4 @@ COPY --chown=node:node . .
 ENV CHOKIDAR_USEPOLLING=true
 EXPOSE 24678
 EXPOSE 3000
+ENTRYPOINT ["/sbin/tini", "--", "/bin/sh"]
diff --git a/web/src/lib/components/shared-components/version-announcement-box.svelte b/web/src/lib/components/shared-components/version-announcement-box.svelte
index b2c535cd6..1c58a3728 100644
--- a/web/src/lib/components/shared-components/version-announcement-box.svelte
+++ b/web/src/lib/components/shared-components/version-announcement-box.svelte
@@ -1,18 +1,18 @@
 <script lang="ts">
-  import type { ServerVersionResponseDto } from '@api';
   import { websocketStore } from '$lib/stores/websocket';
+  import type { ServerVersionResponseDto } from '@immich/sdk';
   import Button from '../elements/buttons/button.svelte';
   import FullScreenModal from './full-screen-modal.svelte';

   let showModal = false;

-  const { onRelease } = websocketStore;
+  const { release } = websocketStore;

   const semverToName = ({ major, minor, patch }: ServerVersionResponseDto) => `v${major}.${minor}.${patch}`;

-  $: releaseVersion = $onRelease && semverToName($onRelease.releaseVersion);
-  $: serverVersion = $onRelease && semverToName($onRelease.serverVersion);
-  $: $onRelease?.isAvailable && handleRelease();
+  $: releaseVersion = $release && semverToName($release.releaseVersion);
+  $: serverVersion = $release && semverToName($release.serverVersion);
+  $: $release?.isAvailable && handleRelease();

   const onAcknowledge = () => {
     localStorage.setItem('appVersion', releaseVersion);
@@ -26,8 +26,8 @@
       }

       showModal = true;
-    } catch (err) {
-      console.error('Error [VersionAnnouncementBox]:', err);
+    } catch (error) {
+      console.error('Error [VersionAnnouncementBox]:', error);
     }
   };
 </script>
diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile
index 5b6cc9b6d..d317a5298 100644
--- a/machine-learning/Dockerfile
+++ b/machine-learning/Dockerfile
@@ -1,6 +1,6 @@
 ARG DEVICE=cpu

-FROM python:3.11-bookworm@sha256:8d773321add21be41f1f891b43177a41aaae0d1b83f3638872ec84636179594a as builder-cpu
+FROM python:3.11-bookworm@sha256:8e697181d24bd77cc4251fdd37e4cdd6d725c5de2ed63b9bc8db77357400c5e2 as builder-cpu

 FROM openvino/ubuntu22_runtime:2023.1.0@sha256:002842a9005ba01543b7169ff6f14ecbec82287f09c4d1dd37717f0a8e8754a7 as builder-openvino
 USER root
@@ -34,7 +34,7 @@ RUN python3 -m venv /opt/venv
 COPY poetry.lock pyproject.toml ./
 RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev

-FROM python:3.11-slim-bookworm@sha256:d11b9bd5e49ea7401753d78f4d3b56f3aec952b85b49bcae88981f0452818e0b as prod-cpu
+FROM python:3.11-slim-bookworm@sha256:ce81dc539f0aedc9114cae640f8352fad83d37461c24a3615b01f081d0c0583a as prod-cpu

 FROM openvino/ubuntu22_runtime:2023.1.0@sha256:002842a9005ba01543b7169ff6f14ecbec82287f09c4d1dd37717f0a8e8754a7 as prod-openvino
 USER root
@@ -52,7 +52,8 @@ ENV LD_LIBRARY_PATH=/opt/armnn
 RUN apt-get update && apt-get install -y --no-install-recommends ocl-icd-libopencl1 mesa-opencl-icd && \
     rm -rf /var/lib/apt/lists/* && \
     mkdir --parents /etc/OpenCL/vendors && \
-    echo "/usr/lib/libmali.so" > /etc/OpenCL/vendors/mali.icd
+    echo "/usr/lib/libmali.so" > /etc/OpenCL/vendors/mali.icd && \
+    mkdir /opt/armnn

 COPY --from=builder-armnn \
       /opt/armnn/libarmnn.so.?? \
diff --git a/machine-learning/start.sh b/machine-learning/start.sh
index d522f1143..082bf205c 100755
--- a/machine-learning/start.sh
+++ b/machine-learning/start.sh
@@ -1,6 +1,7 @@
 #!/usr/bin/env sh

-export LD_PRELOAD="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2"
+lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2"
+export LD_PRELOAD="$lib_path"
 export LD_BIND_NOW=1

 : "${MACHINE_LEARNING_HOST:=0.0.0.0}"
@@ -10,8 +11,8 @@ export LD_BIND_NOW=1

 gunicorn app.main:app \
    -k app.config.CustomUvicornWorker \
-   -w $MACHINE_LEARNING_WORKERS \
-   -b $MACHINE_LEARNING_HOST:$MACHINE_LEARNING_PORT \
-   -t $MACHINE_LEARNING_WORKER_TIMEOUT \
+   -w "$MACHINE_LEARNING_WORKERS" \
+   -b "$MACHINE_LEARNING_HOST":"$MACHINE_LEARNING_PORT" \
+   -t "$MACHINE_LEARNING_WORKER_TIMEOUT" \
    --log-config-json log_conf.json \
    --graceful-timeout 0
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index c824e17ea..f1d16f7e6 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -60,14 +60,12 @@ services:

   redis:
     container_name: immich_redis
-    image: redis:6.2-alpine@sha256:afb290a0a0d0b2bd7537b62ebff1eb84d045c757c1c31ca2ca48c79536c0de82
+    image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5
     restart: always

   database:
     container_name: immich_postgres
-    image: tensorchord/pgvecto-rs:pg14-v0.1.11@sha256:0335a1a22f8c5dd1b697f14f079934f5152eaaa216c09b61e293be285491f8ee
-    env_file:
-      - .env
+    image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0
     environment:
       POSTGRES_PASSWORD: ${DB_PASSWORD}
       POSTGRES_USER: ${DB_USERNAME}
diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md
index 09fadbf70..48d7219d1 100644
--- a/docs/docs/install/environment-variables.md
+++ b/docs/docs/install/environment-variables.md
@@ -61,13 +61,16 @@ These environment variables are used by the `docker-compose.yml` file and do **N
 ## Database

 | Variable                            | Description                                                   |   Default    | Services              |
-| :------------ | :---------------- | :---------: | :-------------------- |
+| :---------------------------------- | :------------------------------------------------------------ | :----------: | :-------------------- |
 | `DB_URL`                            | Database URL                                                  |              | server, microservices |
 | `DB_HOSTNAME`                       | Database Host                                                 | `localhost`  | server, microservices |
 | `DB_PORT`                           | Database Port                                                 |    `5432`    | server, microservices |
 | `DB_USERNAME`                       | Database User                                                 |  `postgres`  | server, microservices |
 | `DB_PASSWORD`                       | Database Password                                             |  `postgres`  | server, microservices |
 | `DB_DATABASE`                       | Database Name                                                 |   `immich`   | server, microservices |
+| `DB_VECTOR_EXTENSION`<sup>\*1</sup> | Database Vector Extension (one of [`pgvector`, `pgvecto.rs`]) | `pgvecto.rs` | server, microservices |
+
+\*1: This setting cannot be changed after the server has successfully started up

 :::info
diff --git a/docs/docs/features/command-line-interface.md b/docs/docs/features/command-line-interface.md
index ee7ca1c22..360b3c372 100644
--- a/docs/docs/features/command-line-interface.md
+++ b/docs/docs/features/command-line-interface.md
@@ -15,10 +15,12 @@ If you are looking to import your Google Photos takeout, we recommend this commu

 ## Requirements

-- Node.js 20.0 or above
+- Node.js 20 or above
 - Npm

-## Installation
+If you can't install node/npm, there is also a Docker version available below.
+
+## Installation (NPM)

 ```bash
 npm i -g @immich/cli
@@ -30,6 +32,16 @@ NOTE: if you previously installed the legacy CLI, you will need to uninstall it
 npm uninstall -g immich

+## Installation (Docker) + +If npm is not available on your system you can try the Docker version + +bash +docker run -it -v "$(pwd)":/import:ro -e IMMICH_INSTANCE_URL=https://your-immich-instance/api -e IMMICH_API_KEY=your-api-key ghcr.io/immich-app/immich-cli:latest + + +Please modify the IMMICH_INSTANCE_URL and IMMICH_API_KEY environment variables as suitable. You can also use a Docker env file to store your sensitive API key. +

Usage

@@ -39,10 +51,11 @@ immich

Usage: immich [options] [command]

-Immich command line interface +Command line interface for Immich

Options: -V, --version output the version number

-This will store your credentials in a file in your home directory. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually. +This will store your credentials in a auth.yml file in the configuration directory which defaults to ~/.config/. The directory can be set with the -d option or the environment variable IMMICH_CONFIG_DIR. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually.

Once you are authenticated, you can upload assets to your Immich server.

@@ -123,6 +138,12 @@ You can automatically create albums based on the folder name by passing the `--a immich upload --album --recursive directory/


+You can also choose to upload all assets to a specific album with the `--album-name` option.
+
+```bash
+immich upload --album-name "My summer holiday" --recursive directory/
+```
+
 It is possible to skip assets matching a glob pattern by passing the `--ignore` option. See [the library documentation](docs/features/libraries.md) on how to use glob patterns. You can add several exclusion patterns if needed.

 ```bash
@@ -133,6 +154,12 @@ immich upload --ignore **/Raw/** --recursive directory/
 immich upload --ignore **/Raw/** **/*.tif --recursive directory/

+By default, hidden files are skipped. If you want to include hidden files, use the --include-hidden option: + +bash +immich upload --include-hidden --recursive directory/ + +

Obtain the API Key

The API key can be obtained in the user setting panel on the web interface.


/home/runner/work/immich-distribution/immich-distribution
/tmp/tmp.SpCKD0rF8c removed

## Base image
Check the base images for recent relevant changes:

* https://github.com/immich-app/base-images/commits/main/

## Checklist
* Review the changes above
* Possible write a news entry (and push it to this PR)
* Wait for the CI to finish
* Merge the PR

ref #154