From c5219dcfb25683b71ee72639a254dc849abb4846 Mon Sep 17 00:00:00 2001 From: winewill Date: Wed, 4 Nov 2026 13:38:16 +0800 Subject: [PATCH] fix(desktop): validate archive settings before retained files --- apps/desktop/packaging/README.i18n.yaml | 8 ++++---- apps/desktop/packaging/README.md | 4 ++-- apps/desktop/packaging/README.zh.md | 4 ++-- apps/desktop/scripts/archive-desktop-ci.ts | 2 +- apps/desktop/tests/retain-desktop-ci.spec.ts | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/desktop/packaging/README.i18n.yaml b/apps/desktop/packaging/README.i18n.yaml index 27d558a343..cd2ea3a547 100644 --- a/apps/desktop/packaging/README.i18n.yaml +++ b/apps/desktop/packaging/README.i18n.yaml @@ -24,11 +24,11 @@ en: 5b4f0f80a117f202 zh: ff05be196c181087 /desktop-packaging/windows-actions-packaging: - en: 748f7ae145c98ed6 - zh: c91ee5ffaeaa77df + en: 7bd0f4aa899a7295 + zh: a27c75934844123d /desktop-packaging/macos-self-hosted-packaging: - en: 004642a4a84a8ad5 - zh: 807a4517785a5153 + en: 3bd14c640893b192 + zh: 7c236cbe46be4a47 /desktop-packaging/unsigned-windows-test-installer: en: f429bc0c280e2dfa zh: 4adbcc9e906bdf80 diff --git a/apps/desktop/packaging/README.md b/apps/desktop/packaging/README.md index 685e1b0cba..f33819c47f 100644 --- a/apps/desktop/packaging/README.md +++ b/apps/desktop/packaging/README.md @@ -115,7 +115,7 @@ Select the workflow in Actions, choose the source branch, preset, signing mode a All Windows packaging modes, including test and unsigned, require the repository variable `DESKTOP_PUBLISH_RUNNERS`; configure the [original-machine route](../publishing/ci/README.md#machine-setup) before dispatch. -Open the completed run in Actions and download its Artifacts from the independent `upload-artifact` job. Installer names use the original `package_run_attempt`; diagnostic names use the current `run_attempt`. If archival fails after packaging succeeds, rerun only `upload-artifact` to reuse the retained installers. `windows-x64-signed---.zip` and `windows-x64-unsigned---.zip` contain the corresponding EXE; `windows-package-logs--` contains packaging diagnostics. Installer ZIPs record each retained copy’s modification time in local DOS and absolute Unix fields; this is not a guarantee of the original build time. The upload steps are `Retain installers for the selected mode` and `Retain packaging diagnostics`; their step durations and timestamped logs show upload time. These artifacts are not a Release or download-site publication. +Open the completed run in Actions and download its Artifacts from the independent `upload-artifact` job. Installer names use the original `package_run_attempt`; diagnostic names use the current `run_attempt`. If archival fails after packaging succeeds, rerun only `upload-artifact` to reuse the retained installers. `windows-x64-signed---.zip` and `windows-x64-unsigned---.zip` contain the corresponding EXE; `windows-package-logs--` contains packaging diagnostics. Installer ZIPs record each retained copy’s modification time as local time in the DOS field and absolute time in the Unix field; this is not a guarantee of the original build time. The upload steps are `Retain installers for the selected mode` and `Retain packaging diagnostics`; their step durations and timestamped logs show upload time. These artifacts are not a Release or download-site publication. For cache measurements, `cache_namespace` selects a retained subdirectory for both dependency stores and upstream downloads; leave it empty for normal shared caches. Use a new name for a cold sample and repeat that name for warm samples. Names contain 1–64 lowercase letters, digits or hyphens, start with a letter or digit, and cannot be Windows device names. This does not reset the separate signature cache or OS file cache; report those states and Job start-to-completion time alongside phase timings and artifact size. Before dependency installation, the workflow records the Node version, available CPU parallelism, logical CPU count, and total/free memory. @@ -127,7 +127,7 @@ Installer uploads store the already-compressed release files without ZIP recompr ## macOS self-hosted packaging -The [Apple Silicon workflow](../../../.github/workflows/macos-package.yml) and [Intel workflow](../../../.github/workflows/macos-intel-package.yml) produce separate arm64 and x64 packages on the Apple Silicon runner labeled `dsh-mac-package-trial`. Both share one concurrency group. The Intel workflow checks Rosetta execution before dependency installation; its selected source must include the target-aware macOS CI adapter. Both select `test` or `production` and use the existing signing, notarization and packaged-runtime checks. When the selected source's dsh ships the Computer Use bundle, each workflow builds, notarizes and stages the helper for both architectures with `scripts/cua-helper/package.ts` and `stage.ts` after the configuration check, the steps npm publication uses; `skip_notarization` does not skip the helper's notarization. A source that predates helper packaging only emits a warning, and Computer Use cannot prepare its helper in that package. Successful DMG/ZIP files and diagnostic logs are retained for 14 days without publishing a release. Installer uploads disable redundant ZIP compression. Artifacts are named `macos-----.zip`, with `arch` set to `arm64` or `x64`; entry timestamps describe retained copies in local DOS and absolute Unix fields, not necessarily the original build time. The operator must verify a complete Actions run and installation on the target architecture before release qualification. The `compression_level` dropdown defaults to `3` and also offers `7`; it overrides the machine preset for this run and affects only ZIP and automatic-update downloads, not DMG. +The [Apple Silicon workflow](../../../.github/workflows/macos-package.yml) and [Intel workflow](../../../.github/workflows/macos-intel-package.yml) produce separate arm64 and x64 packages on the Apple Silicon runner labeled `dsh-mac-package-trial`. Both share one concurrency group. The Intel workflow checks Rosetta execution before dependency installation; its selected source must include the target-aware macOS CI adapter. Both select `test` or `production` and use the existing signing, notarization and packaged-runtime checks. When the selected source's dsh ships the Computer Use bundle, each workflow builds, notarizes and stages the helper for both architectures with `scripts/cua-helper/package.ts` and `stage.ts` after the configuration check, the steps npm publication uses; `skip_notarization` does not skip the helper's notarization. A source that predates helper packaging only emits a warning, and Computer Use cannot prepare its helper in that package. Successful DMG/ZIP files and diagnostic logs are retained for 14 days without publishing a release. Installer uploads disable redundant ZIP compression. Artifacts are named `macos-----.zip`, with `arch` set to `arm64` or `x64`; entry timestamps describe retained copies as local time in the DOS field and absolute time in the Unix field, this is not a guarantee of the original build time. The operator must verify a complete Actions run and installation on the target architecture before release qualification. The `compression_level` dropdown defaults to `3` and also offers `7`; it overrides the machine preset for this run and affects only ZIP and automatic-update downloads, not DMG. Both macOS workflows require the repository variable `DESKTOP_PUBLISH_RUNNERS`, including test and unnotarized modes. Their independent `upload-artifact` job retains installer names with the original build attempt; if archival fails after packaging succeeds, rerun only that job. See [original-machine routing and recovery](../publishing/ci/README.md#recovery-and-records). diff --git a/apps/desktop/packaging/README.zh.md b/apps/desktop/packaging/README.zh.md index 7f13f20528..2923d1c056 100644 --- a/apps/desktop/packaging/README.zh.md +++ b/apps/desktop/packaging/README.zh.md @@ -115,7 +115,7 @@ runner 的受监督启动和恢复见 [Windows runner 机器准备](../windows-s 所有 Windows 打包模式(含 test 和 unsigned)都要求仓库变量 `DESKTOP_PUBLISH_RUNNERS`;触发前配置[原机器路由](../publishing/ci/README.zh.md#machine-setup)。 -在 Actions 打开完成的运行,下载独立 `upload-artifact` job 生成的 Artifacts。安装包名称使用原构建的 `package_run_attempt`,诊断名称使用当前 `run_attempt`。打包成功但归档失败时,仅重跑 `upload-artifact` 以复用保留的安装包。`windows-x64-signed---.zip` 与 `windows-x64-unsigned---.zip` 包含对应 EXE;`windows-package-logs--` 包含打包诊断。安装包 ZIP 用本地 DOS 和绝对 Unix 字段记录各留存副本的修改时间,不保证是原始构建时间。上传步骤名为 `Retain installers for the selected mode` 和 `Retain packaging diagnostics`;步骤耗时与带时间戳的日志显示上传用时。这些产物不等于发布 Release 或下载站内容。 +在 Actions 打开完成的运行,下载独立 `upload-artifact` job 生成的 Artifacts。安装包名称使用原构建的 `package_run_attempt`,诊断名称使用当前 `run_attempt`。打包成功但归档失败时,仅重跑 `upload-artifact` 以复用保留的安装包。`windows-x64-signed---.zip` 与 `windows-x64-unsigned---.zip` 包含对应 EXE;`windows-package-logs--` 包含打包诊断。安装包 ZIP 用 DOS 字段的本地时间和 Unix 字段的绝对时间记录各留存副本的修改时间,不保证是原始构建时间。上传步骤名为 `Retain installers for the selected mode` 和 `Retain packaging diagnostics`;步骤耗时与带时间戳的日志显示上传用时。这些产物不等于发布 Release 或下载站内容。 测量缓存时,`cache_namespace` 为两个依赖 store 和上游下载选择保留的子目录;留空使用正常共享缓存。新名称用于冷缓存采样,再次使用同名用于热缓存采样。名称由 1–64 个小写字母、数字或连字符组成,以字母或数字开头,且不能为 Windows 设备名。这不会重置独立的签名缓存或操作系统文件缓存;应将其状态、Job 开始至完成的总耗时与阶段耗时和产物体积一并报告。workflow 在依赖安装前记录 Node 版本、可用 CPU 并行数、逻辑 CPU 数及总内存和空闲内存。 @@ -127,7 +127,7 @@ runner 的受监督启动和恢复见 [Windows runner 机器准备](../windows-s ## macOS 自托管打包 -[Apple Silicon 工作流](../../../.github/workflows/macos-package.yml)与 [Intel 工作流](../../../.github/workflows/macos-intel-package.yml)在带有 `dsh-mac-package-trial` 标签的 Apple Silicon runner 上分别生成 arm64 和 x64 安装包,两者共用一个并发组。Intel 工作流在安装依赖前检查 Rosetta 能否执行;所选源码必须包含按目标架构校验的 macOS CI 适配脚本。两者均选择 `test` 或 `production`,并复用现有签名、公证和打包运行时检查。所选源码的 dsh 随附 Computer Use 组合包时,两者都在配置检查之后用 `scripts/cua-helper/package.ts` 和 `stage.ts` 构建、公证并放入两种架构的 helper,与 npm 发布的步骤相同;`skip_notarization` 不会跳过 helper 的公证。源码早于 helper 打包支持时只输出警告,该安装包中的 Computer Use 无法准备 helper。成功的 DMG/ZIP 与诊断日志保留 14 天,不发布 release;安装包上传关闭重复 ZIP 压缩。产物名为 `macos-----.zip`,其中 `arch` 为 `arm64` 或 `x64`;条目时间以本地 DOS 和绝对 Unix 字段记录留存副本的修改时间,不一定是原始构建时间。操作人员须验收完整 Actions 运行及目标架构上的安装,才能确认可交付。`compression_level` 下拉选项默认为 `3`,也可选择 `7`;本次运行以该选项覆盖机器预设,只影响 ZIP 和自动升级下载,不影响 DMG。 +[Apple Silicon 工作流](../../../.github/workflows/macos-package.yml)与 [Intel 工作流](../../../.github/workflows/macos-intel-package.yml)在带有 `dsh-mac-package-trial` 标签的 Apple Silicon runner 上分别生成 arm64 和 x64 安装包,两者共用一个并发组。Intel 工作流在安装依赖前检查 Rosetta 能否执行;所选源码必须包含按目标架构校验的 macOS CI 适配脚本。两者均选择 `test` 或 `production`,并复用现有签名、公证和打包运行时检查。所选源码的 dsh 随附 Computer Use 组合包时,两者都在配置检查之后用 `scripts/cua-helper/package.ts` 和 `stage.ts` 构建、公证并放入两种架构的 helper,与 npm 发布的步骤相同;`skip_notarization` 不会跳过 helper 的公证。源码早于 helper 打包支持时只输出警告,该安装包中的 Computer Use 无法准备 helper。成功的 DMG/ZIP 与诊断日志保留 14 天,不发布 release;安装包上传关闭重复 ZIP 压缩。产物名为 `macos-----.zip`,其中 `arch` 为 `arm64` 或 `x64`;条目时间以 DOS 字段的本地时间和 Unix 字段的绝对时间记录留存副本的修改时间,不保证是原始构建时间。操作人员须验收完整 Actions 运行及目标架构上的安装,才能确认可交付。`compression_level` 下拉选项默认为 `3`,也可选择 `7`;本次运行以该选项覆盖机器预设,只影响 ZIP 和自动升级下载,不影响 DMG。 两个 macOS 工作流都要求仓库变量 `DESKTOP_PUBLISH_RUNNERS`,包括 test 和未公证模式。独立 `upload-artifact` job 的安装包名称保留原构建 attempt;打包成功但归档失败时,仅重跑该 job。参见[原机器路由与恢复](../publishing/ci/README.zh.md#recovery-and-records)。 diff --git a/apps/desktop/scripts/archive-desktop-ci.ts b/apps/desktop/scripts/archive-desktop-ci.ts index 7e89915de8..4829a898a4 100644 --- a/apps/desktop/scripts/archive-desktop-ci.ts +++ b/apps/desktop/scripts/archive-desktop-ci.ts @@ -27,9 +27,9 @@ export async function verifyDesktopArchive(env: NodeJS.ProcessEnv): Promise>> 11, (dosTime >>> 5) & 63, (dosTime & 31) * 2]).toEqual([11, 2, 42]) - const start = directoryOffset + 46 + bytes.readUInt16LE(directoryOffset + 28) + const start = directoryOffset + 46 + nameLength const end = start + bytes.readUInt16LE(directoryOffset + 30) let unixTime: number | undefined for (let offset = start; offset < end; offset += 4 + bytes.readUInt16LE(offset + 2)) { @@ -89,7 +89,7 @@ it.each(['../escape.zip', '-option.zip', 'missing-extension', 'missing-output']) const output = join(root, 'archive-output') const result = spawnSync(process.execPath, ['--import', 'tsx', archiveScript], { encoding: 'utf8', env: { ...process.env, ...archiveEnv, RUNNER_TEMP: root, GITHUB_OUTPUT: name === 'missing-output' ? '' : output, - DESKTOP_ARCHIVE_NAME: name === 'missing-output' ? 'fixture.zip' : name } }) + DESKTOP_ARCHIVE_NAME: name === 'missing-output' ? 'fixture.zip' : name, RUNNER_NAME: 'wrong-machine' } }) expect(result.status).toBe(1) expect(result.stderr).toContain('desktop archival: invalid ZIP output settings') await expect(readFile(output)).rejects.toMatchObject({ code: 'ENOENT' })