fix(desktop): preserve copyright and verify installer metadata

This commit is contained in:
winewill committed 2026-10-19 16:23:59 +08:00
1 parent f351c96d71
commit 0d9a7f9abf
6 files changed
+23 -9

No files matched your search

@@ -3,6 +3,7 @@ import type { AfterPackContext, BeforePackContext } from 'app-builder-lib'
/** Electron-builder fields asserted by the Desktop release tests. */
export interface DesktopElectronBuilderConfig {
readonly appId: string
readonly copyright: string
readonly artifactName: string
readonly protocols: readonly [{ readonly name: 'DeepSeek Harness'; readonly schemes: readonly ['dsh'] }]
readonly directories: {
+4 -4
View File
@@ -45,14 +45,14 @@
en: b42f103358d0dfd7
zh: a534164ad9eb00da
/desktop-packaging/runtime-file-selection-and-installation-checks:
en: 080d251258b2358f
zh: e3d968a0384971db
en: bfd89e1d139c5729
zh: 5d6cced5462ba13e
/desktop-packaging/desktop-runtime-preparation:
en: a7aa3066e649ffe8
zh: 4334637910058c09
/desktop-packaging/installation-and-release-verification:
en: 0006b6b1ae4998f4
zh: 2bab6918b0c37b25
en: eb35eb973b796643
zh: c1c52311632b7296
/desktop-packaging/dev-note:
en: b75c8458928b72b9
zh: 003ba4e17b4b5269
+2 -2
View File
@@ -230,8 +230,6 @@ The served `time` is the real packing time, so pnpm 11's default 24-hour `minimu
## Runtime file selection and installation checks
Windows lists the installed application by product name without a version suffix; the version remains in the separate version field. The publisher comes from Desktop's `package.json` author name, independently of the signing certificate. These fields take effect when the rebuilt installer installs or updates the application.
Desktop packs workspace packages locally and installs external dependencies through the target's bundled Node and pnpm. [Desktop's file policy](../scripts/runtime-file-policy.ts) then filters the immutable `resources/app.asar/dsh/node_modules` copy before signing and integrity sealing. It omits TypeScript declarations, recognized JavaScript/CSS/TypeScript source maps, TypeScript build caches, Domino's test directory and Yarn development metadata, selected native compiler outputs, and node-pty prebuilds for other platforms. Non-Windows targets also omit `node-pty/third_party/conpty`; Windows targets retain that directory. It preserves runtime JavaScript, target native modules and their DLL/EXE helpers, WASM, unknown assets, licenses, and notices. Dependency manifests pass through electron-builder's metadata cleanup before integrity sealing, so archiving preserves their recorded bytes. The policy does not alter npm tarballs, the bundled package manager, or user-installed plugin files.
The [Electron shell file list](../scripts/electron-builder-config.mjs) excludes recognized JavaScript/CSS/TypeScript source maps and TypeScript build caches from the separate `resources/app.asar/node_modules` dependency collection. These exclusions preserve runtime code, native modules, WASM, data files (including ordinary `.map` assets), licenses, and notices; [shell archive tests](../tests/shell-file-selection.spec.ts) check retained bytes and exclusions.
@@ -274,6 +272,8 @@ An unpacked artifact contains Electron, the materialized dsh production tree, pn
## Installation and release verification
Windows lists the installed application by product name without a version suffix; the version remains in the separate version field. Desktop's `package.json` `author.name` supplies the installer publisher and executable company name, independently of the signing certificate. Windows and macOS retain product-name copyright text. Installation or upgrade with a rebuilt installer applies the new metadata; existing installations retain their previous values until then.
Keep the generated installer, its version and packaging records together. Review signatures and runtime checks before installation, then follow the [installed-update qualification procedure](../tests/installed-update/README.md) for installed launch and upgrade evidence. The [Desktop test record](../tests/README.md) owns verification limits; a successful workflow alone does not establish production preset, new-workstation or installed-upgrade acceptance.
## Dev Note
+2 -2
View File
@@ -230,8 +230,6 @@ pnpm run dev:bundle-registry
## 运行时文件筛选与安装检查
Windows 以不带版本后缀的产品名称显示已安装应用,版本保留在单独的版本字段中。发布者取自 Desktop 的 `package.json` 作者名称,与签名证书相互独立。这些字段在重新构建的安装包安装或更新应用时生效。
Desktop 在本地打包工作区包,并通过目标捆绑的 Node 和 pnpm 安装外部依赖。[Desktop 文件策略](../scripts/runtime-file-policy.ts)随后在签名和完整性封装前过滤不可变的 `resources/app.asar/dsh/node_modules` 副本。它排除 TypeScript 声明、已识别的 JavaScript/CSS/TypeScript source map、TypeScript 构建缓存、Domino 测试目录及 Yarn 开发元数据、选定的原生编译器输出和其他平台的 node-pty 预构建文件。非 Windows 目标还会排除 `node-pty/third_party/conpty`;Windows 目标保留该目录。它保留运行时 JavaScript、目标平台的原生模块及其 DLL/EXE 辅助文件、WASM、未知资源、许可证和 notices。依赖清单在完整性封装前经过 electron-builder 的元数据清理,确保归档保持已记录的字节。该策略不修改 npm tarball、捆绑的包管理器或用户安装的插件文件。
[Electron 外壳文件清单](../scripts/electron-builder-config.mjs)从单独收集的 `resources/app.asar/node_modules` 依赖中排除已识别的 JavaScript/CSS/TypeScript source map 和 TypeScript 构建缓存。这些排除规则保留运行时代码、原生模块、WASM、数据文件(包括普通 `.map` 资源)、许可证和 notices;[外壳归档测试](../tests/shell-file-selection.spec.ts)检查保留文件的字节和排除项。
@@ -274,6 +272,8 @@ macOS 签名打包在组装 App 时、代码签名前写入 `Contents/Resources/
## 安装与发布验收
Windows 以不带版本后缀的产品名称显示已安装应用,版本保留在单独的版本字段中。Desktop 的 `package.json` 中的 `author.name` 提供安装包发布者和可执行文件公司名称,与签名证书相互独立。Windows 和 macOS 的版权文本仍使用产品名称。重新构建的安装包在安装或升级时写入新元数据;既有安装在此之前保留原值。
一起保留生成的安装包、版本和打包记录。安装前检查签名与运行时验证结果,再按[已安装更新验收流程](../tests/installed-update/README.zh.md)记录安装后启动及升级证据。[Desktop 测试记录](../tests/README.zh.md)维护验证限制;工作流成功本身不代表 production preset、新工作站或已安装升级验收通过。
## 开发备注
@@ -114,6 +114,7 @@ export function createElectronBuilderConfig(
...packaged === undefined ? {} : { dshBuildCommit: packaged.commit, dshBuildDirty: packaged.dirty },
},
productName: 'DeepSeek Harness',
copyright: `Copyright © ${new Date().getFullYear()} \${productName}`,
// Unsigned builds carry their own suffix so a shared file can never pass for a release artifact.
artifactName: `deepseek-harness-\${version}-\${os}-\${arch}${output.suffix}.\${ext}`,
directories: { output: output.directory },
+13 -1
View File
@@ -1,7 +1,8 @@
import { tmpdir } from 'node:os'
import { readFileSync } from 'node:fs'
import { Arch, Platform } from 'electron-builder'
import { Packager } from 'app-builder-lib'
import { AppInfo, Packager } from 'app-builder-lib'
import { expandMacro } from 'app-builder-lib/out/util/macroExpander.js'
import { describe, expect, it, vi } from 'vitest'
const { execute } = vi.hoisted(() => ({ execute: vi.fn(async () => undefined) }))
@@ -37,6 +38,17 @@ describe('installer preparation preserves application dependencies', () => {
try {
const { createElectronBuilderConfig } = await import('../electron-builder.config.mjs')
const config = createElectronBuilderConfig(env, platform, 'x64')
const metadataPackager = new Packager({ projectDir: tmpdir() })
Object.defineProperties(metadataPackager, {
config: { value: config },
metadata: { value: JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) },
})
const appInfo = new AppInfo(metadataPackager, undefined)
expect(appInfo.companyName).toBe('Hangzhou DeepSeek Artificial Intelligence Co., Ltd.')
expect(appInfo.copyright).toBe(`Copyright © ${new Date().getFullYear()} DeepSeek Harness`)
if (platform === 'win32') {
expect(expandMacro(config.nsis.uninstallDisplayName, null, appInfo, {}, false)).toBe('DeepSeek Harness')
}
const aboutIcon = config.extraResources.find(resource => resource.to === 'icon.png')
expect(aboutIcon).toBeDefined()
expect(readFileSync(aboutIcon!.from)).toEqual(readFileSync(new URL('../resources/icon-windows.png', import.meta.url)))