diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index 0d1cbaf0563fcf..f9eea89a11ef87 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -16,12 +16,13 @@ jobs:
permissions: {}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
permission-contents: write
permission-pull-requests: write
+ permission-workflows: write
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -35,6 +36,7 @@ jobs:
github_token: ${{ steps.token.outputs.token }}
label_pattern: '^backport:(release/.+)$'
add_team_reviewers: team
+ add_labels: 'backport'
auto_merge_enabled: true
auto_merge_method: squash
comment_style: summary
diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml
index 68744fada6f2ab..72ad1b495b8f26 100644
--- a/.github/workflows/build-mobile.yml
+++ b/.github/workflows/build-mobile.yml
@@ -58,7 +58,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -66,7 +66,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -87,7 +87,7 @@ jobs:
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -206,7 +206,7 @@ jobs:
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml
index 06f61f03fac7f8..18aedf96820f67 100644
--- a/.github/workflows/cache-cleanup.yml
+++ b/.github/workflows/cache-cleanup.yml
@@ -19,7 +19,7 @@ jobs:
actions: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index abc075259b3078..4d6a6c7b18b39b 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -31,7 +31,7 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -64,7 +64,7 @@ jobs:
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 1adfe05138e4d7..ff300e86741311 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -44,7 +44,7 @@ jobs:
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -58,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -71,7 +71,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
# âšī¸ Command-line programs to run using the OS shell.
# đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -84,6 +84,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
category: '/language:${{matrix.language}}'
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 26fc0264898286..ec23e1f6dd27d0 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -29,7 +29,7 @@ jobs:
highest-in-line: ${{ steps.scope.outputs.highest-in-line }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -37,7 +37,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml
index e7911d97f40f94..b44ddf939f9212 100644
--- a/.github/workflows/docs-build.yml
+++ b/.github/workflows/docs-build.yml
@@ -21,7 +21,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -29,7 +29,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -55,7 +55,7 @@ jobs:
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml
index b88e3f56dcea11..79529c71682e62 100644
--- a/.github/workflows/docs-deploy.yml
+++ b/.github/workflows/docs-deploy.yml
@@ -20,7 +20,7 @@ jobs:
artifact: ${{ steps.get-artifact.outputs.result }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -128,7 +128,7 @@ jobs:
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/docs-destroy.yml b/.github/workflows/docs-destroy.yml
index cdb3f83c96f99b..c6a185a234bf20 100644
--- a/.github/workflows/docs-destroy.yml
+++ b/.github/workflows/docs-destroy.yml
@@ -17,7 +17,7 @@ jobs:
pull-requests: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml
index f17f7922aae538..b94af4047df7a6 100644
--- a/.github/workflows/draft-release.yml
+++ b/.github/workflows/draft-release.yml
@@ -31,7 +31,7 @@ jobs:
esac
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -175,11 +175,12 @@ jobs:
permissions: {}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
permission-contents: write
+ permission-discussions: write
- name: Publish release
env:
diff --git a/.github/workflows/fix-format.yml b/.github/workflows/fix-format.yml
index 3c84838ad1e07d..94c54b97018fe0 100644
--- a/.github/workflows/fix-format.yml
+++ b/.github/workflows/fix-format.yml
@@ -15,7 +15,7 @@ jobs:
pull-requests: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/migration-order.yml b/.github/workflows/migration-order.yml
index 7cf39ae5bff64b..e609302bed6f1c 100644
--- a/.github/workflows/migration-order.yml
+++ b/.github/workflows/migration-order.yml
@@ -25,7 +25,7 @@ jobs:
ORDER: ${{ github.workspace }}/server/src/schema/migrations/ORDER
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/pr-label-validation.yml b/.github/workflows/pr-label-validation.yml
index 5820a8b284d279..f23fc45253bb10 100644
--- a/.github/workflows/pr-label-validation.yml
+++ b/.github/workflows/pr-label-validation.yml
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index d924c84596a8e6..a9d53d088b0e3c 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml
index a24827f51aac08..cf27d07a565b69 100644
--- a/.github/workflows/prepare-release.yml
+++ b/.github/workflows/prepare-release.yml
@@ -59,7 +59,7 @@ jobs:
esac
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/preview-label.yaml b/.github/workflows/preview-label.yaml
index 95be3b88e2d20c..e47ec0d062fbe2 100644
--- a/.github/workflows/preview-label.yaml
+++ b/.github/workflows/preview-label.yaml
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -33,7 +33,7 @@ jobs:
pull-requests: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml
index 9c6101e4e11916..798408fff5fe76 100644
--- a/.github/workflows/sdk.yml
+++ b/.github/workflows/sdk.yml
@@ -16,7 +16,7 @@ jobs:
packages: write
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml
index e53375f64af9d2..c4545b9de3cdb3 100644
--- a/.github/workflows/static_analysis.yml
+++ b/.github/workflows/static_analysis.yml
@@ -20,7 +20,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -28,7 +28,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -51,7 +51,7 @@ jobs:
working-directory: ./mobile
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5da8fd00026cc1..8367c490a2e739 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -17,7 +17,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -25,7 +25,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -78,7 +78,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -107,7 +107,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -139,7 +139,7 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -171,7 +171,7 @@ jobs:
working-directory: ./packages/cli
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -216,7 +216,7 @@ jobs:
working-directory: ./web
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -255,7 +255,7 @@ jobs:
working-directory: ./web
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -284,7 +284,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -335,7 +335,7 @@ jobs:
working-directory: ./e2e
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -368,7 +368,7 @@ jobs:
working-directory: ./server
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -405,7 +405,7 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -484,7 +484,7 @@ jobs:
runner: [ubuntu-latest, ubuntu-24.04-arm]
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -594,7 +594,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -632,7 +632,7 @@ jobs:
working-directory: ./machine-learning
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -663,7 +663,7 @@ jobs:
working-directory: ./.github
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -694,7 +694,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -716,7 +716,7 @@ jobs:
contents: read
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -774,7 +774,7 @@ jobs:
- 5432:5432
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/.github/workflows/weblate-lock.yml b/.github/workflows/weblate-lock.yml
index 4875ebfe0da134..c21962880cbd55 100644
--- a/.github/workflows/weblate-lock.yml
+++ b/.github/workflows/weblate-lock.yml
@@ -24,7 +24,7 @@ jobs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
@@ -32,7 +32,7 @@ jobs:
- name: Check what should run
id: check
- uses: immich-app/devtools/actions/pre-job@03514eceb4a27cd714976a866b350df5ce175720 # pre-job-action-v2.1.0
+ uses: immich-app/devtools/actions/pre-job@75493d49052d536863fc96100086782c5279b145 # pre-job-action-v2.1.1
with:
github-token: ${{ steps.token.outputs.token }}
filters: |
@@ -48,7 +48,7 @@ jobs:
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
steps:
- id: token
- uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
+ uses: immich-app/devtools/actions/create-workflow-token@df46d635b905e618b88fc4c95baa920aeb30b309 # create-workflow-token-action-v3.0.1
with:
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
diff --git a/README.md b/README.md
index 02ae01857e5295..ba774d44cdd7b9 100644
--- a/README.md
+++ b/README.md
@@ -118,16 +118,6 @@ Read more about translations [here](https://docs.immich.app/developer/translatio

-## Star history
-
-
-
-
-
-
-
-
-
## Contributors
diff --git a/docs/docs/guides/smtp-microsoft365.md b/docs/docs/guides/smtp-microsoft365.md
index 2ba78a4e181e2e..a8e0e6f71a4436 100644
--- a/docs/docs/guides/smtp-microsoft365.md
+++ b/docs/docs/guides/smtp-microsoft365.md
@@ -1,5 +1,10 @@
# SMTP settings using Microsoft 365
+:::info Deprecated by Microsoft
+Microsoft has announced the [deprecation](https://techcommunity.microsoft.com/blog/exchange/updated-exchange-online-smtp-auth-basic-authentication-deprecation-timeline/4489835) of SMTP Basic Auth.
+We no longer recommend using this setup method. Alternate methods are available but not within the scope of the Immich docs.
+:::
+
This guide walks you through how to get the information you need to set up your Immich instance to send emails using Microsoft's SMTP server.
## Create an app password
diff --git a/mobile/test/presentation/widgets/asset_viewer/asset_page_zoom_reset_test.dart b/mobile/test/presentation/widgets/asset_viewer/asset_page_zoom_reset_test.dart
index f4ee4f353cfc71..0961fc5d7dfd60 100644
--- a/mobile/test/presentation/widgets/asset_viewer/asset_page_zoom_reset_test.dart
+++ b/mobile/test/presentation/widgets/asset_viewer/asset_page_zoom_reset_test.dart
@@ -14,6 +14,7 @@ import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import '../../../fixtures/asset.stub.dart';
+import '../../../unit/presentation/presentation_context.dart';
/// Timeline displaying a single asset that we can swap
class _SwappableTimelineService extends TimelineService {
@@ -40,10 +41,21 @@ class _ZoomedNotifier extends AssetViewerStateNotifier {
}
void main() {
+ late PresentationContext context;
+
+ setUp(() async {
+ context = await PresentationContext.create();
+ });
+
+ tearDown(() async {
+ await context.dispose();
+ });
+
testWidgets('resets zoom when the displayed asset is replaced on reload', (tester) async {
final timeline = _SwappableTimelineService(LocalAssetStub.image1);
final container = ProviderContainer(
overrides: [
+ ...context.overrides,
timelineServiceProvider.overrideWithValue(timeline),
assetViewerProvider.overrideWith(_ZoomedNotifier.new),
],
@@ -73,8 +85,6 @@ void main() {
),
);
await tester.pump(const Duration(milliseconds: 600));
- // Ignore any image load errors
- tester.takeException();
expect(container.read(assetViewerProvider).isZoomed, isTrue);
@@ -84,7 +94,6 @@ void main() {
await tester.idle();
await tester.pump();
- tester.takeException();
expect(container.read(assetViewerProvider).isZoomed, isFalse);
});
diff --git a/server/src/queries/integrity.repository.sql b/server/src/queries/integrity.repository.sql
index 8d8461e70081ee..c1faaea064e536 100644
--- a/server/src/queries/integrity.repository.sql
+++ b/server/src/queries/integrity.repository.sql
@@ -65,6 +65,28 @@ from
where
"person"."thumbnailPath" in $1
+-- IntegrityRepository.getTrackedPaths
+select
+ "asset"."originalPath" as "path"
+from
+ "asset"
+where
+ "asset"."originalPath" in $1
+union
+select
+ "asset_file"."path" as "path"
+from
+ "asset_file"
+where
+ "asset_file"."path" in $2
+union
+select
+ "person"."thumbnailPath" as "path"
+from
+ "person"
+where
+ "person"."thumbnailPath" in $3
+
-- IntegrityRepository.getAssetCount
select
count(*) as "count"
diff --git a/server/src/repositories/integrity.repository.ts b/server/src/repositories/integrity.repository.ts
index 227e69a074d90f..2599da47bdb8fd 100644
--- a/server/src/repositories/integrity.repository.ts
+++ b/server/src/repositories/integrity.repository.ts
@@ -94,6 +94,24 @@ export class IntegrityRepository {
.execute();
}
+ @GenerateSql({ params: [DummyValue.STRING] })
+ getTrackedPaths(paths: string[]) {
+ return this.db
+ .selectFrom('asset')
+ .select('asset.originalPath as path')
+ .where('asset.originalPath', 'in', paths)
+ .union((eb) =>
+ eb.selectFrom('asset_file').select('asset_file.path as path').where('asset_file.path', 'in', paths),
+ )
+ .union((eb) =>
+ eb
+ .selectFrom('person')
+ .select((eb) => eb.ref('person.thumbnailPath').$castTo().as('path'))
+ .where('person.thumbnailPath', 'in', paths),
+ )
+ .execute();
+ }
+
@GenerateSql({ params: [] })
getAssetCount() {
return this.db
diff --git a/server/src/services/integrity.service.spec.ts b/server/src/services/integrity.service.spec.ts
index 997f337f2b1941..d4b38d632860c5 100644
--- a/server/src/services/integrity.service.spec.ts
+++ b/server/src/services/integrity.service.spec.ts
@@ -13,6 +13,69 @@ describe(IntegrityService.name, () => {
expect(sut).toBeDefined();
});
+ describe('handleUntrackedRefresh', () => {
+ beforeEach(() => {
+ mocks.integrityReport.getTrackedPaths.mockResolvedValue([]);
+ });
+
+ it('should delete a report whose path is now referenced by an asset', async () => {
+ const path = '/data/upload/admin/ab/asset.mov';
+ mocks.integrityReport.getTrackedPaths.mockResolvedValue([{ path }] as never);
+
+ await sut.handleUntrackedRefresh({ items: [{ reportId: 'report-id', path }] });
+
+ expect(mocks.integrityReport.deleteByIds).toHaveBeenCalledWith(['report-id']);
+ expect(mocks.storage.stat).not.toHaveBeenCalled();
+ });
+
+ it('should keep a report whose path is still untracked and present on disk', async () => {
+ mocks.storage.stat.mockResolvedValue({} as never);
+
+ await sut.handleUntrackedRefresh({ items: [{ reportId: 'report-id', path: '/data/upload/orphan.mov' }] });
+
+ expect(mocks.integrityReport.deleteByIds).not.toHaveBeenCalled();
+ });
+
+ it('should not query for references when the batch is empty', async () => {
+ await sut.handleUntrackedRefresh({ items: [] });
+
+ expect(mocks.integrityReport.getTrackedPaths).not.toHaveBeenCalled();
+ expect(mocks.integrityReport.deleteByIds).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('deleteIntegrityReport', () => {
+ it('should not unlink a path that is now tracked', async () => {
+ const path = '/data/upload/admin/ab/asset.mov';
+ mocks.integrityReport.getById.mockResolvedValue({ path } as never);
+ mocks.integrityReport.getTrackedPaths.mockResolvedValue([{ path }] as never);
+
+ await sut.deleteIntegrityReport('user-id', 'report-id');
+
+ expect(mocks.storage.unlink).not.toHaveBeenCalled();
+ expect(mocks.integrityReport.deleteById).toHaveBeenCalledWith('report-id');
+ });
+ });
+
+ describe('handleDeleteIntegrityReports', () => {
+ it('should unlink only paths that are still untracked', async () => {
+ const tracked = '/data/upload/admin/ab/asset.mov';
+ const untracked = '/data/upload/orphan.mov';
+ mocks.integrityReport.getTrackedPaths.mockResolvedValue([{ path: tracked }] as never);
+ mocks.storage.unlink.mockResolvedValue();
+
+ await sut.handleDeleteIntegrityReports({
+ reports: [
+ { id: 'tracked-report', path: tracked },
+ { id: 'untracked-report', path: untracked },
+ ] as never,
+ });
+
+ expect(mocks.storage.unlink).toHaveBeenCalledExactlyOnceWith(untracked);
+ expect(mocks.integrityReport.deleteByIds).toHaveBeenCalledWith(['tracked-report', 'untracked-report']);
+ });
+ });
+
describe('handleDeleteAllIntegrityReports', () => {
beforeEach(() => {
mocks.integrityReport.streamIntegrityReportsByProperty.mockReturnValue((function* () {})() as never);
diff --git a/server/src/services/integrity.service.ts b/server/src/services/integrity.service.ts
index 6c7a505812409d..18add1c065b379 100644
--- a/server/src/services/integrity.service.ts
+++ b/server/src/services/integrity.service.ts
@@ -190,7 +190,10 @@ export class IntegrityService extends BaseService {
} else if (fileAssetId) {
await this.assetRepository.deleteFiles([{ id: fileAssetId }]);
} else {
- await this.storageRepository.unlink(path);
+ const trackedPaths = await this.integrityRepository.getTrackedPaths([path]);
+ if (trackedPaths.length === 0) {
+ await this.storageRepository.unlink(path);
+ }
await this.integrityRepository.deleteById(id);
}
}
@@ -311,8 +314,17 @@ export class IntegrityService extends BaseService {
async handleUntrackedRefresh({ items }: IIntegrityPathWithReportJob): Promise {
this.logger.log(`Processing batch of ${items.length} reports to check if they are out of date.`);
+ const tracked =
+ items.length > 0 ? await this.integrityRepository.getTrackedPaths(items.map(({ path }) => path)) : [];
+ const trackedPaths = new Set(tracked.map(({ path }) => path));
+
const results = await Promise.all(
items.map(async ({ reportId, path }) => {
+ // The path was untracked when the report was written; an asset may reference it now.
+ if (trackedPaths.has(path)) {
+ return reportId;
+ }
+
try {
await this.storageRepository.stat(path);
return;
@@ -697,7 +709,13 @@ export class IntegrityService extends BaseService {
}
if (byPath.length > 0) {
- await Promise.all(byPath.map(({ path }) => this.storageRepository.unlink(path).catch(() => void 0)));
+ const tracked = await this.integrityRepository.getTrackedPaths(byPath.map(({ path }) => path));
+ const trackedPaths = new Set(tracked.map(({ path }) => path));
+ await Promise.all(
+ byPath
+ .filter(({ path }) => !trackedPaths.has(path))
+ .map(({ path }) => this.storageRepository.unlink(path).catch(() => void 0)),
+ );
await this.integrityRepository.deleteByIds(byPath.map(({ id }) => id));
}