From 82912249b02953db81143cf87eff546542592903 Mon Sep 17 00:00:00 2001 From: Seydi Charyyev Date: Sun, 26 Jul 2026 09:39:25 +0500 Subject: [PATCH] fix(desktop): make lint and unit-test gates work on Windows The desktop quality gate does not work on a Windows checkout: two checks pass without examining anything, one fails on every file, and one reports violations its own allowlist already covers. pnpm test quoted the test glob with single quotes. On Windows pnpm runs scripts through cmd.exe, which does not strip them, so node received the quotes literally and matched no files - reporting 0 tests with exit code 0, a silent green. Double quotes are stripped by cmd.exe and POSIX shells alike, so CI behaviour on Linux is unchanged. With no .gitattributes, core.autocrlf=true (the Git for Windows default) checks every text file out as CRLF. Biome formats with LF, so biome check failed on 1632 of 1633 files, and virtuaWheelModePatch.test.mjs, which matches patches/*.patch with newline-joined patterns, failed with it. The stored blobs are already LF, so pinning eol=lf causes no renormalisation churn. check-px-text-core and check-file-sizes-core compare path.relative output against roots and allowlist keys authored with forward slashes. On Windows the separator is a backslash, so the px-text allowlist never matched (5 false violations) and findRule matched no rule at all: check:file-sizes examined 0 of 1097 files and still exited 0. check-pubkey-truncation-core already normalises the same way; this applies it to the other two. After the change the Windows run agrees with CI - check:file-sizes reports the same runtime.rs violation main is currently failing on. Desktop unit tests still fail on Windows until #2758 lands; this stops hiding those failures rather than fixing them. Signed-off-by: Seydi Charyyev --- .gitattributes | 8 ++++++++ desktop/package.json | 2 +- scripts/check-file-sizes-core.mjs | 21 +++++++++++++++------ scripts/check-px-text-core.mjs | 12 ++++++++---- 4 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..f36b1615d0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# Git for Windows defaults to core.autocrlf=true, so without this every text +# file lands in the working copy with CRLF. Biome formats with LF +# (biome.json sets no lineEnding override), which fails `biome check` on +# effectively every file, and +# desktop/src/features/messages/ui/virtuaWheelModePatch.test.mjs asserts on +# patches/*.patch with `\n`-joined patterns. Normalize to LF in the working +# copy on every platform; the stored blobs are already LF. +* text=auto eol=lf diff --git a/desktop/package.json b/desktop/package.json index 8c5795e359..6726bfdcad 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -14,7 +14,7 @@ "lint": "biome lint .", "check": "biome check . && pnpm check:file-sizes && pnpm check:px-text && pnpm check:pubkey-truncation", "format": "biome format --write .", - "test": "node --import ./test-loader.mjs --experimental-strip-types --test 'src/**/*.test.mjs'", + "test": "node --import ./test-loader.mjs --experimental-strip-types --test \"src/**/*.test.mjs\"", "preview": "vite preview", "tauri": "tauri", "test:e2e": "pnpm build:e2e && playwright test", diff --git a/scripts/check-file-sizes-core.mjs b/scripts/check-file-sizes-core.mjs index 196630ee7e..0da7994756 100644 --- a/scripts/check-file-sizes-core.mjs +++ b/scripts/check-file-sizes-core.mjs @@ -10,6 +10,13 @@ import path from "node:path"; * the two apps can never drift. */ +// `rules[].root` and the `overrides` keys are authored with `/`, but +// path.relative yields `\` on Windows — so every comparison against them has +// to happen in posix form or it silently matches nothing. +function toPosixPath(relativePath) { + return relativePath.split(path.sep).join("/"); +} + async function walkFiles(directory) { const entries = await fs.readdir(directory, { withFileTypes: true }); const files = await Promise.all( @@ -27,10 +34,8 @@ async function walkFiles(directory) { } function findRule(rules, relativePath) { - return rules.find((rule) => { - const normalizedRoot = `${rule.root}${path.sep}`; - return relativePath.startsWith(normalizedRoot); - }); + const posixPath = toPosixPath(relativePath); + return rules.find((rule) => posixPath.startsWith(`${rule.root}/`)); } function countLines(content) { @@ -82,11 +87,15 @@ export async function runFileSizeCheck({ continue; } - const limit = overrides.get(relativePath) ?? rule.maxLines; + const limit = overrides.get(toPosixPath(relativePath)) ?? rule.maxLines; const content = await fs.readFile(filePath, "utf8"); const lineCount = countLines(content); if (lineCount > limit) { - violations.push({ limit, lineCount, relativePath }); + violations.push({ + limit, + lineCount, + relativePath: toPosixPath(relativePath), + }); } } diff --git a/scripts/check-px-text-core.mjs b/scripts/check-px-text-core.mjs index b488fe262d..3f98aa5408 100644 --- a/scripts/check-px-text-core.mjs +++ b/scripts/check-px-text-core.mjs @@ -75,10 +75,14 @@ export async function runPxTextCheck({ const violations = []; for (const filePath of candidateFiles) { - const relativePath = path.relative(projectRoot, filePath); - const rule = rules.find((r) => - relativePath.startsWith(`${r.root}${path.sep}`), - ); + // `rules[].root` and the `overrides` keys are authored with `/`, but + // path.relative yields `\` on Windows — so every comparison against them + // has to happen in posix form or it silently matches nothing. + const relativePath = path + .relative(projectRoot, filePath) + .split(path.sep) + .join("/"); + const rule = rules.find((r) => relativePath.startsWith(`${r.root}/`)); if (!rule) { continue; }