Switch element-desktop from yarn classic to pnpm (#2843)

This commit is contained in:
Michael Telatynski
2026-02-11 10:50:23 +00:00
committed by GitHub
parent ebf12081c9
commit 684f7c04ff
27 changed files with 9740 additions and 7570 deletions

View File

@@ -18,7 +18,7 @@ but should work equally well for building modules for normal node.
# Running
Hak is invoked with a command and a dependency, eg. `yarn run hak fetch matrix-seshat`.
Hak is invoked with a command and a dependency, eg. `pnpm run hak fetch matrix-seshat`.
If no dependencies are given, hak runs the command on all dependencies.
# Files
@@ -37,15 +37,15 @@ There are a lot of files involved:
Hak works around native node modules that try to fetch or build their native component in
the npm 'install' phase - modules that do this will typically end up with native components
targeted to the build platform and the node that npm/yarn is using, which is no good for an
targeted to the build platform and the node that npm/pnpm is using, which is no good for an
electron app.
It does this by installing it with `--ignore-scripts` and then using `yarn link` to keep the
dependency module separate so yarn doesn't try to run its install / postinstall script
at other points (eg. whenever you `yarn add` a random other dependency).
It does this by installing it with `--ignore-scripts` and then using `pnpm link` to keep the
dependency module separate so pnpm doesn't try to run its install / postinstall script
at other points (eg. whenever you `pnpm add` a random other dependency).
This also means that the dependencies cannot be listed in `dependencies` or
`devDependencies` in the project, since this would cause npm / yarn to install them and
`devDependencies` in the project, since this would cause pnpm to install them and
try to fetch their native parts. Instead, they are listed in `hakDependencies` which
hak reads to install them for you.
@@ -53,9 +53,6 @@ Hak will _not_ install dependencies for the copy of the module it links into you
project, so if your native module has javascript dependencies that are actually needed at
runtime (and not just to fetch / build the native parts), it won't work.
Hak will generate a `.yarnrc` in the project directory to set the link directory to its
own in the .hak directory (unless one already exists, in which case this is your problem).
# Lifecycle
Hak is divided into lifecycle stages, in order:

View File

@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import fsProm from "node:fs/promises";
import pacote from "pacote";
import path from "node:path";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js";
@@ -30,6 +31,13 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
packumentCache,
});
// Workaround for us switching to pnpm but matrix-seshat still using yarn classic
const packageJsonPath = path.join(moduleInfo.moduleBuildDir, "package.json");
const packageJson = await fsProm.readFile(packageJsonPath, "utf-8");
const packageJsonData = JSON.parse(packageJson);
packageJsonData["packageManager"] = "yarn@1.22.22";
await fsProm.writeFile(packageJsonPath, JSON.stringify(packageJsonData, null, 2), "utf-8");
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
await hakEnv.spawn("yarn", ["install", "--ignore-scripts"], {
cwd: moduleInfo.moduleBuildDir,

View File

@@ -6,18 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import type HakEnv from "./hakEnv.js";
import { type DependencyInfo } from "./dep.js";
export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const linkFolder = path.join(hakEnv.dotHakDir, "links");
await hakEnv.spawn("yarn", ["link", "--link-folder", linkFolder], {
cwd: moduleInfo.moduleOutDir,
});
await hakEnv.spawn("yarn", ["link", "--link-folder", linkFolder, moduleInfo.name], {
await hakEnv.spawn("pnpm", ["link", moduleInfo.moduleOutDir], {
cwd: hakEnv.projectRoot,
});
}

View File

@@ -8,7 +8,7 @@ IMAGE=${DOCKER_IMAGE_NAME:-"element-desktop-dockerbuild"}
docker inspect "$IMAGE" 2> /dev/null > /dev/null
if [ $? != 0 ]; then
echo "Docker image $IMAGE not found. Have you run yarn run docker:setup?"
echo "Docker image $IMAGE not found. Have you run pnpm run docker:setup?"
exit 1
fi

View File

@@ -14,7 +14,7 @@ export async function versionFromAsar(): Promise<string> {
try {
await fs.stat("webapp.asar");
} catch {
throw new Error("No 'webapp.asar' found. Run 'yarn run fetch'");
throw new Error("No 'webapp.asar' found. Run 'pnpm run fetch'");
}
return asar.extractFile("webapp.asar", "version").toString().trim();
@@ -25,7 +25,7 @@ export async function setPackageVersion(ver: string): Promise<void> {
// all the various version fields
await new Promise<void>((resolve, reject) => {
childProcess.execFile(
process.platform === "win32" ? "yarn.cmd" : "yarn",
process.platform === "win32" ? "pnpm.cmd" : "pnpm",
[
"version",
"-s",