Compare commits

...

5 Commits

Author SHA1 Message Date
Michael Telatynski
3dbcc4233b Merge conflict 2025-12-02 14:10:17 +00:00
Michael Telatynski
0d800f9999 Try with yarn berry 2025-12-02 14:07:21 +00:00
Michael Telatynski
d7a95473df Update to 26.3.3
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-12-02 09:56:45 +00:00
renovate[bot]
90194bbd64 Update dependency @playwright/test to v1.57.0 (#2719)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-01 16:06:13 +00:00
Michael Telatynski
c827e806ea Remove keytar-forked (#2723) 2025-11-28 14:52:35 +00:00
20 changed files with 10136 additions and 7686 deletions

View File

@@ -55,6 +55,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
cache: "yarn"

View File

@@ -122,6 +122,7 @@ jobs:
path: |
./.hak
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: .node-version

View File

@@ -105,6 +105,7 @@ jobs:
with:
python-version: "3.13"
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: .node-version
@@ -113,10 +114,6 @@ jobs:
- name: Install Deps
run: "yarn install --frozen-lockfile"
# Python 3.12 drops distutils which keytar relies on
- name: Install setuptools
run: pip3 install setuptools
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
run: yarn build:native:universal

View File

@@ -56,6 +56,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: .node-version

View File

@@ -40,6 +40,10 @@ jobs:
with:
repository: ${{ github.repository == 'element-hq/element-web-pro' && 'element-hq/element-desktop' || github.repository }}
# https://github.com/actions/setup-node/issues/480#issuecomment-2907867335
- run: npm install -g corepack@0.34.5 --force
if: runner.os == 'Windows'
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: .node-version

View File

@@ -148,6 +148,9 @@ jobs:
rustup default stable
rustup target add ${{ steps.config.outputs.target }}
# https://github.com/actions/setup-node/issues/480#issuecomment-2907867335
- run: npm install -g corepack@0.34.5 --force
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: .node-version

View File

@@ -11,6 +11,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: package.json
@@ -25,7 +26,7 @@ jobs:
i18n_lint:
name: "i18n Check"
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@t3chguy/corepack
permissions:
pull-requests: read
with:
@@ -37,6 +38,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: package.json
@@ -55,6 +57,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: package.json
@@ -73,6 +76,7 @@ jobs:
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
- run: corepack enable
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
with:
node-version-file: package.json

1
.gitignore vendored
View File

@@ -19,3 +19,4 @@ yarn-error.log
/scripts/hak/**/*.js
.DS_Store
/playwright-report
/.yarn/install-state.gz

View File

@@ -4,13 +4,10 @@ FROM rust:bullseye@sha256:4886b155a84b46ad61df6a2249905bea8c61fc1eaa903398713233
ENV DEBIAN_FRONTEND=noninteractive
RUN curl --proto "=https" -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn
RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
apt-get -y -qq install --no-install-recommends \
# tclsh is required for building SQLite as part of SQLCipher
tcl \
# libsecret-1-dev is required even for prebuild keytar
libsecret-1-dev \
# Used by seshat (when not SQLCIPHER_STATIC) \
libsqlcipher-dev && \
apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
@@ -18,6 +15,7 @@ RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip
ENV DEBUG_COLORS=true
ENV FORCE_COLOR=true
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
WORKDIR /project

View File

@@ -9,3 +9,4 @@ ARCH="${archMap["$TARGETARCH"]}"
NODE_VERSION=$(cat /.node-version | sed -e 's/^v//')
curl --proto "=https" -L "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md
corepack enable

View File

@@ -17,7 +17,8 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
}
console.log("Running yarn install");
await hakEnv.spawn("yarn", ["install"], {
await hakEnv.spawn("corepack", ["yarn@1.22.22", "install"], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,
@@ -26,7 +27,7 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
const buildTarget = hakEnv.wantsStaticSqlCipher() ? "build-bundled" : "build";
console.log("Running yarn build");
await hakEnv.spawn("yarn", ["run", buildTarget], {
await hakEnv.spawn("corepack", ["yarn@1.22.22", "run", buildTarget], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,

View File

@@ -65,7 +65,6 @@
"counterpart": "^0.18.6",
"electron-store": "^11.0.0",
"electron-window-state": "^5.0.3",
"keytar-forked": "7.10.0",
"minimist": "^1.2.6",
"png-to-ico": "^3.0.0",
"uuid": "^13.0.0"
@@ -77,7 +76,7 @@
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "4.0.1",
"@playwright/test": "1.56.1",
"@playwright/test": "1.57.0",
"@stylistic/eslint-plugin": "^5.0.0",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
@@ -86,12 +85,12 @@
"@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "26.3.2",
"app-builder-lib": "26.3.3",
"chokidar": "^4.0.0",
"detect-libc": "^2.0.0",
"electron": "39.2.3",
"electron-builder": "26.3.2",
"electron-builder-squirrel-windows": "26.3.2",
"electron-builder": "26.3.3",
"electron-builder-squirrel-windows": "26.3.3",
"electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
@@ -122,5 +121,6 @@
"@types/node": "18.19.130",
"config-file-ts": "0.2.8-rc1",
"node-abi": "4.24.0"
}
},
"packageManager": "yarn@4.12.0"
}

View File

@@ -6,8 +6,6 @@ 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 keytar from "keytar-forked";
import { test, expect } from "../../element-desktop-test.js";
declare global {
@@ -61,34 +59,6 @@ test.describe("App launch", () => {
),
).resolves.not.toBeNull();
});
test.describe("migrate from keytar", () => {
test.skip(
process.env.GITHUB_ACTIONS && ["linux", "darwin"].includes(process.platform),
"GitHub Actions hosted runner are not a compatible environment for this test",
);
const pickleKey = "DEADBEEF1234";
const keytarService = "element.io";
const keytarKey = `${userId}|${deviceId}`;
test.beforeAll(async () => {
await keytar.setPassword(keytarService, keytarKey, pickleKey);
await expect(keytar.getPassword(keytarService, keytarKey)).resolves.toBe(pickleKey);
});
test.afterAll(async () => {
await keytar.deletePassword(keytarService, keytarKey);
});
test("should migrate successfully", async ({ page }) => {
await expect(
page.evaluate(
([userId, deviceId]) => window.mxPlatformPeg.get().getPickleKey(userId, deviceId),
[userId, deviceId],
),
).resolves.toBe(pickleKey);
});
});
});
test.describe("--no-update", () => {

View File

@@ -40,7 +40,7 @@ the npm 'install' phase - modules that do this will typically end up with native
targeted to the build platform and the node that npm/yarn 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
It does this by installing it with `--mode=skip-build` 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).

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import fsProm from "node:fs/promises";
import pacote from "pacote";
import pacote, { type Packument } from "pacote";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js";
@@ -25,13 +25,13 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
console.log("Fetching " + moduleInfo.name + "@" + moduleInfo.version);
const packumentCache = new Map();
const packumentCache = new Map<string, Packument>();
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleBuildDir, {
packumentCache,
});
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
await hakEnv.spawn("yarn", ["install", "--ignore-scripts"], {
await hakEnv.spawn("corepack", ["yarn@1.22.22", "install", "--mode=skip-build"], {
cwd: moduleInfo.moduleBuildDir,
});
@@ -45,6 +45,7 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
// actual runtime dependencies will have to be added to the main app's
// dependencies. We can't tell what dependencies are real runtime deps
// and which are just used for native module building.
console.log("@@ Pacote2", moduleInfo.moduleOutDir);
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleOutDir, {
packumentCache,
});

View File

@@ -84,6 +84,7 @@ export default class HakEnv {
npm_config_target: this.runtimeVersion,
npm_config_build_from_source: "true",
npm_config_devdir: path.join(os.homedir(), ".electron-gyp"),
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
};
}

View File

@@ -38,10 +38,11 @@ export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo):
);
}
await hakEnv.spawn("yarn", ["link"], {
console.log("@@", moduleInfo.moduleOutDir);
await hakEnv.spawn("corepack", ["yarn@1.22.22", "link"], {
cwd: moduleInfo.moduleOutDir,
});
await hakEnv.spawn("yarn", ["link", moduleInfo.name], {
await hakEnv.spawn("corepack", ["yarn@1.22.22", "link", moduleInfo.name], {
cwd: hakEnv.projectRoot,
});
}

View File

@@ -111,7 +111,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
try {
ret = await store.getSecret(`${args[0]}|${args[1]}`);
} catch {
// if an error is thrown (e.g. keytar can't connect to the keychain),
// if an error is thrown (e.g. we can't initialise safeStorage),
// then return null, which means the default pickle key will be used
ret = null;
}

View File

@@ -15,22 +15,10 @@ limitations under the License.
*/
import ElectronStore from "electron-store";
import keytar from "keytar-forked";
import { app, safeStorage, dialog, type SafeStorage, type Session } from "electron";
import { _t } from "./language-helper.js";
/**
* Legacy keytar service name for storing secrets.
* @deprecated
*/
const KEYTAR_SERVICE = "element.io";
/**
* Super legacy keytar service name for reading secrets.
* @deprecated
*/
const LEGACY_KEYTAR_SERVICE = "riot.im";
/**
* String union type representing all the safeStorage backends.
* + The "unknown" backend shouldn't exist in practice once the app is ready
@@ -147,7 +135,7 @@ const enum Mode {
/**
* JSON-backed store for settings which need to be accessible by the main process.
* Secrets are stored within the `safeStorage` object, encrypted with safeStorage.
* Any secrets operations are blocked on Electron app ready emit, and keytar migration if still needed.
* Any secrets operations are blocked on Electron app ready emit.
*/
class Store extends ElectronStore<StoreData> {
private static internalInstance?: Store;
@@ -283,8 +271,6 @@ class Store extends ElectronStore<StoreData> {
/**
* Prepare the safeStorage backend for use.
* We don't eagerly import from keytar as that would bring in data for all Element profiles and not just the current one,
* so we import lazily in getSecret.
*
* This will relaunch the app in some cases, in which case it will return false and the caller should abort startup.
*
@@ -462,7 +448,6 @@ class Store extends ElectronStore<StoreData> {
/**
* Get the stored secret for the key.
* Lazily migrates keys from keytar if they are not yet in the store.
*
* @param key The string key name.
*
@@ -470,25 +455,11 @@ class Store extends ElectronStore<StoreData> {
*/
public async getSecret(key: string): Promise<string | undefined> {
await this.safeStorageReady();
let secret = this.secrets!.get(key);
if (secret) return secret;
try {
secret = await this.getSecretKeytar(key);
} catch (e) {
console.warn(`Failed to read data from keytar with key='${key}'`, e);
}
if (secret) {
console.debug("Migrating secret from keytar", key);
this.secrets!.set(key, secret);
}
return secret;
return this.secrets!.get(key);
}
/**
* Add the secret for the key to the keychain.
* We write to both safeStorage & keytar to support downgrading the application.
*
* @param key The string key name.
* @param secret The string password.
@@ -498,46 +469,16 @@ class Store extends ElectronStore<StoreData> {
public async setSecret(key: string, secret: string): Promise<void> {
await this.safeStorageReady();
this.secrets!.set(key, secret);
try {
await keytar.setPassword(KEYTAR_SERVICE, key, secret);
} catch (e) {
console.warn(`Failed to write safeStorage backwards-compatibility key='${key}' data to keytar`, e);
}
}
/**
* Delete the stored password for the key.
* Removes from safeStorage, keytar & keytar legacy.
*
* @param key The string key name.
*/
public async deleteSecret(key: string): Promise<void> {
await this.safeStorageReady();
this.secrets!.delete(key);
try {
await this.deleteSecretKeytar(key);
} catch (e) {
console.warn(`Failed to delete secret with key='${key}' from keytar`, e);
}
}
/**
* @deprecated will be removed in the near future
*/
private async getSecretKeytar(key: string): Promise<string | undefined> {
return (
(await keytar.getPassword(KEYTAR_SERVICE, key)) ??
(await keytar.getPassword(LEGACY_KEYTAR_SERVICE, key)) ??
undefined
);
}
/**
* @deprecated will be removed in the near future
*/
private async deleteSecretKeytar(key: string): Promise<void> {
await keytar.deletePassword(LEGACY_KEYTAR_SERVICE, key);
await keytar.deletePassword(KEYTAR_SERVICE, key);
}
}

17668
yarn.lock

File diff suppressed because it is too large Load Diff