Skip to content

chore: use pnpm for builds #19752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

chore: use pnpm for builds #19752

wants to merge 8 commits into from

Conversation

midzelis
Copy link
Collaborator

@midzelis midzelis commented Jul 5, 2025

No description provided.

Copy link
Contributor

github-actions bot commented Jul 5, 2025

📖 Documentation deployed to pr-19752.preview.immich.app

@midzelis midzelis mentioned this pull request Jul 5, 2025
@midzelis midzelis force-pushed the chore/docker_permissions branch 2 times, most recently from 97f7e54 to 91ab806 Compare July 9, 2025 22:14
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from 2baf58c to b9f1b85 Compare July 9, 2025 22:39
@github-actions github-actions bot added documentation Improvements or additions to documentation 📱mobile 🖥️web 🗄️server labels Jul 9, 2025
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch 5 times, most recently from 80c0bab to 5367a86 Compare July 10, 2025 01:43
@midzelis midzelis force-pushed the chore/docker_permissions branch from 91ab806 to 351266e Compare July 10, 2025 22:47
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from 5367a86 to 3262c4e Compare July 10, 2025 22:48
@midzelis midzelis force-pushed the chore/docker_permissions branch from 351266e to 89c84cc Compare July 11, 2025 01:12
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch 5 times, most recently from 200431d to 08865cc Compare July 11, 2025 01:42
@midzelis midzelis force-pushed the chore/docker_permissions branch from 89c84cc to 3ab0dbb Compare July 11, 2025 01:50
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch 4 times, most recently from 0d4a6fc to 6d87af1 Compare July 11, 2025 02:11
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch 6 times, most recently from 61efa75 to 9f1fdb3 Compare August 8, 2025 03:12
Conflict

Missing dependency

gitignore

Cli dockerfile

Exiftool optional fix

Update pnpm version

update devcontainer for pnpm
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from 9f1fdb3 to 687e99c Compare August 8, 2025 03:36
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from bb08f8a to e288f6b Compare August 8, 2025 22:01
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from e288f6b to 6c81d08 Compare August 8, 2025 22:28
@midzelis midzelis requested a review from mertalev August 8, 2025 23:49
Copy link
Member

@mertalev mertalev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I think it should get more eyes before merge

@midzelis midzelis requested a review from jrasm91 August 9, 2025 13:11
Comment on lines 35 to 45
- pnpm-store:/usr/src/app/.pnpm-store
- server-node-modules:/usr/src/app/server/node_modules
- github-node_modules:/usr/src/app/.github/node_modules
- cli-node_modules:/usr/src/app/cli/node_modules
- docs-node_modules:/usr/src/app/docs/node_modules
- e2e-node_modules:/usr/src/app/e2e/node_modules
- sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules
- app-node_modules:/usr/src/app/node_modules
- web-node_modules:/usr/src/app/web/node_modules
- sveltekit:/usr/src/app/web/.svelte-kit
- coverage:/usr/src/app/web/coverage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we moving all those to named docker volumes?

Copy link
Collaborator Author

@midzelis midzelis Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few reasons:

  1. This is to avoid permissions issues between the view of the files inside the container vs the ones on the bind-mount on the host. If the container were to be run by a user other than the user that owns the root of the git-clone on the host, then the files would be created with the owner of the user running the container, and if that happened to be 'root' then the files can't be cleaned up with a simple make clean command - it would require sudo make clean which is a little more dangerous/annoying.
  2. Isolation: All of dependency/package install commands are performed from within a docker container, which may be a different architecture (MacOS on arm) or libc (the web container uses alpine with musl instead of glibc) - and some of the dependent packages use native binary code, which only make sense in the architecture/libc version that is within the container it was executed inside. By using volumes, these dependencies are not created on the hosts filesystem.
  3. pnpm performs performs a clone, hard-link, or copy of files (in that order) from the content-addressable-store (/buildcache/pnpm-store) to the virtual store (.pnpm-store). And then creates the dependency node structures in node_modules using symlinks. Using volume mounts makes it more likely that hardlinks will be successful, increasing speed to install dependencies.

oh, and named volumes vs anonymous volumes because anonymous volumes are removed when container is removed, and containers are auto-removed at the end of every make command.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soooo, generally a nice change but kind of unrelated to this PR?

Comment on lines +45 to +48
// eslint-disable-next-line unicorn/prefer-module
const basePath = dirname(__filename);
const packageFile = join(basePath, '..', 'package.json');
const { version } = JSON.parse(readFileSync(packageFile, 'utf8'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change and why is the prefer module linting error here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think because we used to get the version from the package.json file and that doesn't exist in the server directory anymore.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nevermind, I think it originally was removed, but it is still there in this version of the PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: package.json still exists in each of the 8 workspace modules contained in this monorepo.

However, reading it like this:

const { version } = JSON.parse(readFileSync('./package.json', 'utf8'));

uses a relative path, which is resolved against the current-working-directory, which isn't /usr/src/app/server any longer. The way to fix this is read the file from the absolute path of the server package.json. This is determined by using the CommonJS style __filename global, mostly because the ESM alternative is more verbose, and -- well, the default output of the server is CommonJS anyways, not ESM, so using import.meta.url would end up requiring even more steps to adapt back to CommonJS.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the CWD now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ends up being the WORKDIR in the various Dockerfile stages.

For production images, this is /usr/src/app (but server is at /usr/src/app/server)
For server dev image, this is /usr/src/app
For web dev image, this is /usr/src/app/web
For devcontainer images, this is /workspaces/immich

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Fair enough, thanks for explaining

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an unrelated change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - the format of the the paths of individual dependencies served from node_modules when running in dev mode has changed, and this adapts the regexps to the pnpm's changes to these paths.

@@ -60,3 +65,5 @@ export default defineConfig({
},
},
});

export default mergeConfig(viteConfig, vitestConfig);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? AFAICT using the defineConfig from vite is perfectly fine https://vitest.dev/config/#configuring-vitest

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why (maybe because pnpm is more strict?), but I was not able to specify the 'test' property within a defineConfig from vite. I was able to specify test when importing defineConfig from vitest/config - however, then there was an type-error on the plugins property in the config. The one way that worked was what you see here - import both the vitest config and the vite config, then merge them. Also, the triple slash command in the docs did not help.

In fact, I looked at all the 'solutions' here: https://stackoverflow.com/questions/72146352/vitest-defineconfig-test-does-not-exist-in-type-userconfigexport and only the mergeConfig technique (one of the alternatives in the comments) was the only one that worked for me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: I found another solution that just needs a new type import that is a little cleaner

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks good to me, thanks!

@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch 3 times, most recently from 2975ee8 to c302fcf Compare August 10, 2025 04:09
node-version-file: './server/.nvmrc'
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version-file: './.github/.nvmrc'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this still wrong?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking more carefully, this is actually formatting all of the projects, not just .github. You'd technically have to run a version of setup-node for each project. This all may be a moot point, since the node version is always the same for every project.

Would it make sense to just treat the node version as a workspace level setting, instead of per-project? Then, the nvmrc file could be moved up to the root directory of the git repo.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll revert to just using 'server/.nvmrc' as before for now

@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from c302fcf to c7ac088 Compare August 10, 2025 15:06
@midzelis midzelis force-pushed the chore/pnpm_stacked_squashed branch from eb1b85c to 5bc6a15 Compare August 10, 2025 16:32
Copy link
Member

@danieldietzler danieldietzler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Excited for pnpm

Comment on lines 175 to 185
pnpm-store:
github-node_modules:
server-node-modules:
cli-node_modules:
docs-node_modules:
e2e-node_modules:
sdk-node_modules:
app-node_modules:
web-node_modules:
sveltekit:
coverage:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those aren't used anymore are they?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants