From 5487324c26f00adda2d32b896fdae3e2b4e7c7c0 Mon Sep 17 00:00:00 2001 From: hy Date: Wed, 15 Jul 2026 15:01:49 +0800 Subject: [PATCH] fix: preserve native dependencies for release targets --- doc/release.md | 4 + package.json | 4 +- pnpm-lock.yaml | 83 +++++++++++-------- pnpm-workspace.yaml | 8 ++ scripts/prepare-package-stage.mjs | 28 ++++++- .../update/app-update-publish-config.test.ts | 12 +++ 6 files changed, 97 insertions(+), 42 deletions(-) diff --git a/doc/release.md b/doc/release.md index bd4a0c8f..e6852031 100644 --- a/doc/release.md +++ b/doc/release.md @@ -113,6 +113,10 @@ pnpm run package:audit:summary - macOS x64:在同一台 Mac 的 Rosetta x64 Node/Python 环境构建。 - GitHub Actions 不响应 Tag push,不保存安装包 Artifact,也不构建 macOS 或 Linux。 +`pnpm-workspace.yaml` 固定记录 macOS arm64、macOS x64 和 Windows x64 的可选原生依赖。打包时再按当前 OS/CPU 删除不兼容包,不能只用开发机架构生成锁文件。 + +当前 Intel Mac 依赖 `@lancedb/lancedb 0.22.3`,这是项目已验证且包含 `darwin-x64` 原生包的稳定版本。升级 LanceDB 前必须先确认 npm 中同时存在 arm64、x64 和 Windows x64 对应包,并重新执行三个架构的真实启动测试。 + Windows GitHub Actions 只允许手动 `workflow_dispatch`,并按 Tag 设置 concurrency。工作流步骤固定为: 1. 检出输入的 annotated Tag; diff --git a/package.json b/package.json index d6d0ab4f..9039467d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ncurator", - "version": "0.1.5", + "version": "0.1.6", "description": "An Electron application with React and TypeScript", "main": "./out/main/index.js", "author": "example.com", @@ -67,7 +67,7 @@ "@electron-toolkit/utils": "^4.0.0", "@huggingface/transformers": "^3.8.1", "@js-preview/docx": "^1.6.4", - "@lancedb/lancedb": "^0.23.0", + "@lancedb/lancedb": "0.22.3", "@langchain/community": "^1.1.1", "@langchain/core": "^1.1.44", "@langchain/deepseek": "^1.0.25", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44d4eae3..1dbcf03d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,11 +27,11 @@ importers: specifier: ^1.6.4 version: 1.6.4(core-js@3.48.0) '@lancedb/lancedb': - specifier: ^0.23.0 - version: 0.23.0(apache-arrow@17.0.0) + specifier: 0.22.3 + version: 0.22.3(apache-arrow@17.0.0) '@langchain/community': specifier: ^1.1.1 - version: 1.1.2(@browserbasehq/sdk@2.14.0(encoding@0.1.13))(@browserbasehq/stagehand@3.5.0(@cfworker/json-schema@4.1.1)(encoding@0.1.13)(playwright-core@1.58.2)(zod@4.3.6))(@huggingface/transformers@3.8.1)(@ibm-cloud/watsonx-ai@1.7.5)(@lancedb/lancedb@0.23.0(apache-arrow@17.0.0))(@langchain/core@1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@smithy/util-utf8@2.3.0)(better-sqlite3@12.11.1)(cheerio@1.2.0)(crypto-js@4.2.0)(google-auth-library@10.7.0)(ibm-cloud-sdk-core@5.4.5)(ignore@5.3.2)(jsdom@26.1.0(bufferutil@4.1.0))(jsonwebtoken@9.0.3)(lodash@4.17.21)(mammoth@1.11.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6))(pdf-parse@1.1.1)(playwright@1.58.2)(ws@8.21.0(bufferutil@4.1.0)) + version: 1.1.2(@browserbasehq/sdk@2.14.0(encoding@0.1.13))(@browserbasehq/stagehand@3.5.0(@cfworker/json-schema@4.1.1)(encoding@0.1.13)(playwright-core@1.58.2)(zod@4.3.6))(@huggingface/transformers@3.8.1)(@ibm-cloud/watsonx-ai@1.7.5)(@lancedb/lancedb@0.22.3(apache-arrow@17.0.0))(@langchain/core@1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@smithy/util-utf8@2.3.0)(better-sqlite3@12.11.1)(cheerio@1.2.0)(crypto-js@4.2.0)(google-auth-library@10.7.0)(ibm-cloud-sdk-core@5.4.5)(ignore@5.3.2)(jsdom@26.1.0(bufferutil@4.1.0))(jsonwebtoken@9.0.3)(lodash@4.17.21)(mammoth@1.11.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6))(pdf-parse@1.1.1)(playwright@1.58.2)(ws@8.21.0(bufferutil@4.1.0)) '@langchain/core': specifier: ^1.1.44 version: 1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)) @@ -1240,55 +1240,62 @@ packages: peerDependencies: core-js: ^3.0.0 - '@lancedb/lancedb-darwin-arm64@0.23.0': - resolution: {integrity: sha512-8w0sMCNMwBv2kv5+fczGeSVlNOL+BOKChSsO4usM0hMw3PmxasONPctQBsESDuPS8lQ6/AKAQc2HT/ddd5Mg5w==} + '@lancedb/lancedb-darwin-arm64@0.22.3': + resolution: {integrity: sha512-oP2Kic51nLqs27Xo+AzSVlcMgmmfZbU/PseQ3KBtU92rczO5DYU2St1Y7qDUWcjw+RF3H2v/DKzYed16h1wCBQ==} engines: {node: '>= 18'} cpu: [arm64] os: [darwin] - '@lancedb/lancedb-linux-arm64-gnu@0.23.0': - resolution: {integrity: sha512-+xse2IspO7hbuHT4H62q8Ct00fTojnuBxXp1X1I3/27dDvW8E+/itFiJuTZ0YMaJc7nNr9qh9YFXZ9hZdEmReg==} + '@lancedb/lancedb-darwin-x64@0.22.3': + resolution: {integrity: sha512-wOwgZkvBgQM8asjolz4NeyPa8W/AjZv4fwyQxJhTqKTGlB3ntrpdn1m84K5qncTmFFDcDfGgZ4DkNVkVK+ydoQ==} + engines: {node: '>= 18'} + cpu: [x64] + os: [darwin] + + '@lancedb/lancedb-linux-arm64-gnu@0.22.3': + resolution: {integrity: sha512-YUbFuBKQniTZOR9h2/es1f7lDzdHNt8qXs5GaqFmLQv2GNWpnvKXVA/vVffhCNpFB5nV132o1VhXW3KoMubPsw==} engines: {node: '>= 18'} cpu: [arm64] os: [linux] libc: [glibc] - '@lancedb/lancedb-linux-arm64-musl@0.23.0': - resolution: {integrity: sha512-c2UCtGoYjA3oDdw5y3RLK7J2th3rSjYBng+1I03vU9g092y8KATAJO/lV2AtyxSC+esSuyY1dMEaj8ADcXjZAA==} + '@lancedb/lancedb-linux-arm64-musl@0.22.3': + resolution: {integrity: sha512-jVRMtXxxYaDlZSaclCIHB2N+NJvQ1Fj9EaPeBx+HxG2VqUg0vXKef+yiaD2aGo9sAH6mMmkKJsrPhwABpUC4rQ==} engines: {node: '>= 18'} cpu: [arm64] os: [linux] libc: [musl] - '@lancedb/lancedb-linux-x64-gnu@0.23.0': - resolution: {integrity: sha512-OPL7tK3JCTx43ZxvbVs+CljfCer0KrojANQbcJ2V4VAp6XBhKx1sBAlIVGuCrd93pA8UOUP3iHsM7aglPo6rCg==} + '@lancedb/lancedb-linux-x64-gnu@0.22.3': + resolution: {integrity: sha512-co7idTwvNAtbFoFHojhHlTpKsydOm5sZfbtAsQRdoa7g6a61yIrqrMm8D7Ngh756JfzZLFQBMkDUZEW3X4vP/g==} engines: {node: '>= 18'} cpu: [x64] os: [linux] libc: [glibc] - '@lancedb/lancedb-linux-x64-musl@0.23.0': - resolution: {integrity: sha512-1ZEoQDwOrKvwPyAG+95/r1NYqX8Ca5bRek8Vr62CzWCEmHd/pFeEGWZ5STrkh+Bt3GLdi2JOivFtRbmuBAJypQ==} + '@lancedb/lancedb-linux-x64-musl@0.22.3': + resolution: {integrity: sha512-+ipFsn5PCODK7mOMq1gZ5OAZWks5YlgmjAlnYMmU8XxvaK0b6lZdA3s1hTmBaBO9+wv+31ulO55oBN4/U8Yldg==} engines: {node: '>= 18'} cpu: [x64] os: [linux] libc: [musl] - '@lancedb/lancedb-win32-arm64-msvc@0.23.0': - resolution: {integrity: sha512-OuD1mkrgXvijRlXdbx3LvfuorO04FD5qHegnTOWGXh1sIwwrvvhcJAvXUGBNLY4n/lsWvA+xTjtMwRjUitvPKg==} + '@lancedb/lancedb-win32-arm64-msvc@0.22.3': + resolution: {integrity: sha512-E0XywJYnelIe4pzOlvog+aMHKt5ChW27tgmT2V80Z6PXcX6eN9I69Fj0Q6DK6z1YCTPIPu6Na1Hd6d4GqUNKPw==} engines: {node: '>= 18'} cpu: [arm64] os: [win32] - '@lancedb/lancedb-win32-x64-msvc@0.23.0': - resolution: {integrity: sha512-5ve1hvVtp8zWxSE9A+MOQaicXl2Rn0ZG/NUaMTjTD3/CQHPKFmtrqDnM5khoPICTj2O2b10F6mn4cUzl5PASgA==} + '@lancedb/lancedb-win32-x64-msvc@0.22.3': + resolution: {integrity: sha512-/1feFnjz5MIhzXOEU4+1OeGwpAFYczGfefuOGZRsmGWDdt4V6/fza7Hkkxyb2OnTzqpBfy6BdW2+iBguE1JMyQ==} engines: {node: '>= 18'} cpu: [x64] os: [win32] - '@lancedb/lancedb@0.23.0': - resolution: {integrity: sha512-aYrIoEG24AC+wILCL57Ius/Y4yU+xFHDPKLvmjzzN4byAjzeIGF0TC86S5RBt4Ji+dxS7yIWV5Q/gE5/fybIFQ==} + '@lancedb/lancedb@0.22.3': + resolution: {integrity: sha512-nRC0fkg+d7dzCtudKHT+VH7znk6KUXRZyuS6HJYNnIrbvXBxaT6wAPjEbf70KTuqvP2znj48Zg+kiwRqkRnAJw==} engines: {node: '>= 18'} + cpu: [x64, arm64] os: [darwin, linux, win32] peerDependencies: apache-arrow: '>=15.0.0 <=18.1.0' @@ -7947,39 +7954,43 @@ snapshots: dependencies: core-js: 3.48.0 - '@lancedb/lancedb-darwin-arm64@0.23.0': + '@lancedb/lancedb-darwin-arm64@0.22.3': optional: true - '@lancedb/lancedb-linux-arm64-gnu@0.23.0': + '@lancedb/lancedb-darwin-x64@0.22.3': optional: true - '@lancedb/lancedb-linux-arm64-musl@0.23.0': + '@lancedb/lancedb-linux-arm64-gnu@0.22.3': optional: true - '@lancedb/lancedb-linux-x64-gnu@0.23.0': + '@lancedb/lancedb-linux-arm64-musl@0.22.3': optional: true - '@lancedb/lancedb-linux-x64-musl@0.23.0': + '@lancedb/lancedb-linux-x64-gnu@0.22.3': optional: true - '@lancedb/lancedb-win32-arm64-msvc@0.23.0': + '@lancedb/lancedb-linux-x64-musl@0.22.3': optional: true - '@lancedb/lancedb-win32-x64-msvc@0.23.0': + '@lancedb/lancedb-win32-arm64-msvc@0.22.3': optional: true - '@lancedb/lancedb@0.23.0(apache-arrow@17.0.0)': + '@lancedb/lancedb-win32-x64-msvc@0.22.3': + optional: true + + '@lancedb/lancedb@0.22.3(apache-arrow@17.0.0)': dependencies: apache-arrow: 17.0.0 reflect-metadata: 0.2.2 optionalDependencies: - '@lancedb/lancedb-darwin-arm64': 0.23.0 - '@lancedb/lancedb-linux-arm64-gnu': 0.23.0 - '@lancedb/lancedb-linux-arm64-musl': 0.23.0 - '@lancedb/lancedb-linux-x64-gnu': 0.23.0 - '@lancedb/lancedb-linux-x64-musl': 0.23.0 - '@lancedb/lancedb-win32-arm64-msvc': 0.23.0 - '@lancedb/lancedb-win32-x64-msvc': 0.23.0 + '@lancedb/lancedb-darwin-arm64': 0.22.3 + '@lancedb/lancedb-darwin-x64': 0.22.3 + '@lancedb/lancedb-linux-arm64-gnu': 0.22.3 + '@lancedb/lancedb-linux-arm64-musl': 0.22.3 + '@lancedb/lancedb-linux-x64-gnu': 0.22.3 + '@lancedb/lancedb-linux-x64-musl': 0.22.3 + '@lancedb/lancedb-win32-arm64-msvc': 0.22.3 + '@lancedb/lancedb-win32-x64-msvc': 0.22.3 '@langchain/classic@1.0.8(@langchain/core@1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)))(@opentelemetry/api@1.9.0)(cheerio@1.2.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6))(ws@8.21.0(bufferutil@4.1.0))': dependencies: @@ -8003,7 +8014,7 @@ snapshots: - openai - ws - '@langchain/community@1.1.2(@browserbasehq/sdk@2.14.0(encoding@0.1.13))(@browserbasehq/stagehand@3.5.0(@cfworker/json-schema@4.1.1)(encoding@0.1.13)(playwright-core@1.58.2)(zod@4.3.6))(@huggingface/transformers@3.8.1)(@ibm-cloud/watsonx-ai@1.7.5)(@lancedb/lancedb@0.23.0(apache-arrow@17.0.0))(@langchain/core@1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@smithy/util-utf8@2.3.0)(better-sqlite3@12.11.1)(cheerio@1.2.0)(crypto-js@4.2.0)(google-auth-library@10.7.0)(ibm-cloud-sdk-core@5.4.5)(ignore@5.3.2)(jsdom@26.1.0(bufferutil@4.1.0))(jsonwebtoken@9.0.3)(lodash@4.17.21)(mammoth@1.11.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6))(pdf-parse@1.1.1)(playwright@1.58.2)(ws@8.21.0(bufferutil@4.1.0))': + '@langchain/community@1.1.2(@browserbasehq/sdk@2.14.0(encoding@0.1.13))(@browserbasehq/stagehand@3.5.0(@cfworker/json-schema@4.1.1)(encoding@0.1.13)(playwright-core@1.58.2)(zod@4.3.6))(@huggingface/transformers@3.8.1)(@ibm-cloud/watsonx-ai@1.7.5)(@lancedb/lancedb@0.22.3(apache-arrow@17.0.0))(@langchain/core@1.1.44(@opentelemetry/api@1.9.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@smithy/util-utf8@2.3.0)(better-sqlite3@12.11.1)(cheerio@1.2.0)(crypto-js@4.2.0)(google-auth-library@10.7.0)(ibm-cloud-sdk-core@5.4.5)(ignore@5.3.2)(jsdom@26.1.0(bufferutil@4.1.0))(jsonwebtoken@9.0.3)(lodash@4.17.21)(mammoth@1.11.0)(openai@6.36.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6))(pdf-parse@1.1.1)(playwright@1.58.2)(ws@8.21.0(bufferutil@4.1.0))': dependencies: '@browserbasehq/stagehand': 3.5.0(@cfworker/json-schema@4.1.1)(encoding@0.1.13)(playwright-core@1.58.2)(zod@4.3.6) '@ibm-cloud/watsonx-ai': 1.7.5 @@ -8021,7 +8032,7 @@ snapshots: optionalDependencies: '@browserbasehq/sdk': 2.14.0(encoding@0.1.13) '@huggingface/transformers': 3.8.1 - '@lancedb/lancedb': 0.23.0(apache-arrow@17.0.0) + '@lancedb/lancedb': 0.22.3(apache-arrow@17.0.0) '@smithy/util-utf8': 2.3.0 better-sqlite3: 12.11.1 cheerio: 1.2.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2c5e8dcb..847cc755 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,14 @@ packages: - . +supportedArchitectures: + os: + - darwin + - win32 + cpu: + - arm64 + - x64 + allowBuilds: '@google/genai': true better-sqlite3: true diff --git a/scripts/prepare-package-stage.mjs b/scripts/prepare-package-stage.mjs index 611a7d80..a03579db 100644 --- a/scripts/prepare-package-stage.mjs +++ b/scripts/prepare-package-stage.mjs @@ -260,6 +260,22 @@ const stripSourceMapReferences = () => { const pruneNodeModules = () => { const nodeModules = path.join(STAGE_DIR, 'node_modules') const targetPrebuildDirectory = `${process.platform}-${process.arch}` + const supportsCurrentTarget = (values, current) => { + if (!Array.isArray(values) || values.length === 0) return true + const normalized = values.map((value) => String(value).trim()).filter(Boolean) + if (normalized.includes(`!${current}`)) return false + const allowed = normalized.filter((value) => !value.startsWith('!')) + return allowed.length === 0 || allowed.includes(current) + } + const isIncompatiblePackage = (directory) => { + const packageJsonPath = path.join(directory, 'package.json') + if (!fs.existsSync(packageJsonPath)) return false + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) + return ( + !supportsCurrentTarget(packageJson.os, process.platform) || + !supportsCurrentTarget(packageJson.cpu, process.arch) + ) + } const prunePlatformPrebuilds = (directory) => { for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { if (!entry.isDirectory()) continue @@ -281,6 +297,10 @@ const pruneNodeModules = () => { const lowerName = entry.name.toLowerCase() if (entry.isSymbolicLink()) continue if (entry.isDirectory()) { + if (isIncompatiblePackage(entryPath)) { + fs.rmSync(entryPath, { recursive: true, force: true }) + continue + } if (lowerName === 'prebuilds') { prunePlatformPrebuilds(entryPath) } @@ -433,15 +453,15 @@ const main = () => { writeStageLockfile(runtimeDependencies) installRuntimeDependencies() + fs.rmSync(path.join(STAGE_DIR, 'pnpm-lock.yaml'), { force: true }) + pruneCompiledOutput() + pruneNodeModules() + pruneStagedResources() const packagedDependencies = collectInstalledTopLevelDependencies() fs.writeFileSync( path.join(STAGE_DIR, 'package.json'), `${JSON.stringify({ ...stagePackage, dependencies: packagedDependencies }, null, 2)}\n` ) - fs.rmSync(path.join(STAGE_DIR, 'pnpm-lock.yaml'), { force: true }) - pruneCompiledOutput() - pruneNodeModules() - pruneStagedResources() stripSourceMapReferences() const audit = spawnSync( diff --git a/tests/case/settings/update/app-update-publish-config.test.ts b/tests/case/settings/update/app-update-publish-config.test.ts index c2474f87..d2985cc8 100644 --- a/tests/case/settings/update/app-update-publish-config.test.ts +++ b/tests/case/settings/update/app-update-publish-config.test.ts @@ -86,11 +86,23 @@ describe('app update publish config', () => { }) it('keeps the complete installed production dependency closure', async () => { + const packageJson = JSON.parse(await readFile(path.resolve('package.json'), 'utf8')) const packageStage = await readFile(path.resolve('scripts/prepare-package-stage.mjs'), 'utf8') expect(packageStage).toContain('collectInstalledTopLevelDependencies') expect(packageStage).toContain('dependencies: packagedDependencies') + expect(packageStage).toContain('isIncompatiblePackage') expect(packageStage).not.toContain("name.startsWith('history.')") + + const workspaceConfig = await readFile(path.resolve('pnpm-workspace.yaml'), 'utf8') + expect(workspaceConfig).toContain('supportedArchitectures:') + expect(workspaceConfig).toContain('- win32') + expect(workspaceConfig).toContain('- x64') + expect(packageJson.dependencies['@lancedb/lancedb']).toBe('0.22.3') + + const lockfile = await readFile(path.resolve('pnpm-lock.yaml'), 'utf8') + expect(lockfile).toContain("'@lancedb/lancedb-darwin-x64@0.22.3':") + expect(lockfile).toContain("'@lancedb/lancedb-win32-x64-msvc@0.22.3':") }) it('requires local Rosetta builds and stable macOS signatures', async () => {