Skip to content

Commit 023f2a8

Browse files
authored
Merge branch 'main' into timestams-with-seconds
2 parents d288f0a + 4b9019e commit 023f2a8

File tree

93 files changed

+1352
-360
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+1352
-360
lines changed

.github/workflows/preview-label.yaml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020

2121
remove-label:
2222
runs-on: ubuntu-latest
23-
if: ${{ github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'preview') }}
23+
if: ${{ (github.event.action == 'closed' || github.event.pull_request.head.repo.fork) && contains(github.event.pull_request.labels.*.name, 'preview') }}
2424
permissions:
2525
pull-requests: write
2626
steps:
@@ -33,3 +33,15 @@ jobs:
3333
repo: context.repo.repo,
3434
name: 'preview'
3535
})
36+
37+
- uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2.8.2
38+
if: ${{ github.event.pull_request.head.repo.fork }}
39+
with:
40+
message-id: 'preview-status'
41+
message: 'PRs from forks cannot have preview environments.'
42+
43+
- uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2.8.2
44+
if: ${{ !github.event.pull_request.head.repo.fork }}
45+
with:
46+
message-id: 'preview-status'
47+
message: 'Preview environment has been removed.'

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ dev-update:
1010
dev-scale:
1111
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
1212

13+
dev-docs:
14+
npm --prefix docs run start
15+
1316
.PHONY: e2e
1417
e2e:
1518
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans

docs/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
npm-debug.log*
1919
yarn-debug.log*
2020
yarn-error.log*
21-
yarn.lock
21+
yarn.lock
22+
23+
/static/openapi.json

docs/docs/administration/reverse-proxy.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
Users can deploy a custom reverse proxy that forwards requests to Immich. This way, the reverse proxy can handle TLS termination, load balancing, or other advanced features. All reverse proxies between Immich and the user must forward all headers and set the `Host`, `X-Real-IP`, `X-Forwarded-Proto` and `X-Forwarded-For` headers to their appropriate values. Additionally, your reverse proxy should allow for big enough uploads. By following these practices, you ensure that all custom reverse proxies are fully compatible with Immich.
44

5-
:::note
6-
The Repair page can take a long time to load. To avoid server timeouts or errors, we recommend specifying a timeout of at least 10 minutes on your proxy server.
7-
:::
8-
95
:::caution
106
Immich does not support being served on a sub-path such as `location /immich {`. It has to be served on the root path of a (sub)domain.
117
:::

docs/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"format": "prettier --check .",
88
"format:fix": "prettier --write .",
99
"start": "docusaurus start --port 3005",
10-
"build": "docusaurus build",
10+
"copy:openapi": "jq -c < ../open-api/immich-openapi-specs.json > ./static/openapi.json || exit 0",
11+
"build": "npm run copy:openapi && docusaurus build",
1112
"swizzle": "docusaurus swizzle",
1213
"deploy": "docusaurus deploy",
1314
"clear": "docusaurus clear",

docs/src/pages/cursed-knowledge.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import {
1616
mdiCloudKeyOutline,
1717
mdiRegex,
1818
mdiCodeJson,
19+
mdiClockOutline,
20+
mdiAccountOutline,
21+
mdiRestart,
1922
} from '@mdi/js';
2023
import Layout from '@theme/Layout';
2124
import React from 'react';
@@ -26,6 +29,42 @@ const withLanguage = (date: Date) => (language: string) => date.toLocaleDateStri
2629
type Item = Omit<TimelineItem, 'done' | 'getDateLabel'> & { date: Date };
2730

2831
const items: Item[] = [
32+
{
33+
icon: mdiClockOutline,
34+
iconColor: 'gray',
35+
title: 'setTimeout is cursed',
36+
description:
37+
'The setTimeout method in JavaScript is cursed when used with small values because the implementation may or may not actually wait the specified time.',
38+
link: {
39+
url: 'https://github.com/immich-app/immich/pull/20655',
40+
text: '#20655',
41+
},
42+
date: new Date(2025, 7, 4),
43+
},
44+
{
45+
icon: mdiAccountOutline,
46+
iconColor: '#DAB1DA',
47+
title: 'PostgreSQL USER is cursed',
48+
description:
49+
'The USER keyword in PostgreSQL is cursed because you can select from it like a table, which leads to confusion if you have a table name user as well.',
50+
link: {
51+
url: 'https://github.com/immich-app/immich/pull/19891',
52+
text: '#19891',
53+
},
54+
date: new Date(2025, 7, 4),
55+
},
56+
{
57+
icon: mdiRestart,
58+
iconColor: '#8395e3',
59+
title: 'PostgreSQL RESET is cursed',
60+
description:
61+
'PostgreSQL RESET is cursed because it is impossible to RESET a PostgreSQL extension parameter if the extension has been uninstalled.',
62+
link: {
63+
url: 'https://github.com/immich-app/immich/pull/19363',
64+
text: '#19363',
65+
},
66+
date: new Date(2025, 5, 20),
67+
},
2968
{
3069
icon: mdiRegex,
3170
iconColor: 'purple',

e2e/src/api/specs/album.e2e-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ describe('/albums', () => {
683683
.set('Authorization', `Bearer ${user1.accessToken}`)
684684
.send({ role: AlbumUserRole.Editor });
685685

686-
expect(status).toBe(200);
686+
expect(status).toBe(204);
687687

688688
// Get album to verify the role change
689689
const { body } = await request(app)

e2e/src/api/specs/asset.e2e-spec.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ describe('/asset', () => {
555555
expect(body).toMatchObject({ id: user1Assets[0].id, livePhotoVideoId: null });
556556
});
557557

558-
it('should update date time original when sidecar file contains DateTimeOriginal', async () => {
558+
it.skip('should update date time original when sidecar file contains DateTimeOriginal', async () => {
559559
const sidecarData = `<?xpacket begin='?' id='W5M0MpCehiHzreSzNTczkc9d'?>
560560
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 12.40'>
561561
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
@@ -854,6 +854,30 @@ describe('/asset', () => {
854854
});
855855
});
856856

857+
describe('PUT /assets', () => {
858+
it('should update date time original relatively', async () => {
859+
const { status, body } = await request(app)
860+
.put(`/assets/`)
861+
.set('Authorization', `Bearer ${user1.accessToken}`)
862+
.send({ ids: [user1Assets[0].id], dateTimeRelative: -1441 });
863+
864+
expect(body).toEqual({});
865+
expect(status).toEqual(204);
866+
867+
const result = await request(app)
868+
.get(`/assets/${user1Assets[0].id}`)
869+
.set('Authorization', `Bearer ${user1.accessToken}`)
870+
.send();
871+
872+
expect(result.body).toMatchObject({
873+
id: user1Assets[0].id,
874+
exifInfo: expect.objectContaining({
875+
dateTimeOriginal: '2023-11-19T01:10:00+00:00',
876+
}),
877+
});
878+
});
879+
});
880+
857881
describe('POST /assets', () => {
858882
beforeAll(setupTests, 30_000);
859883

e2e/src/api/specs/partner.e2e-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ describe('/partners', () => {
116116
.delete(`/partners/${user3.userId}`)
117117
.set('Authorization', `Bearer ${user1.accessToken}`);
118118

119-
expect(status).toBe(200);
119+
expect(status).toBe(204);
120120
});
121121

122122
it('should throw a bad request if partner not found', async () => {

e2e/src/api/specs/shared-link.e2e-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ describe('/shared-links', () => {
485485
.delete(`/shared-links/${linkWithAlbum.id}`)
486486
.set('Authorization', `Bearer ${user1.accessToken}`);
487487

488-
expect(status).toBe(200);
488+
expect(status).toBe(204);
489489
});
490490
});
491491
});

0 commit comments

Comments
 (0)