perf(windows): expose per-run installer compression

This commit is contained in:
winewill committed 2026-10-20 21:34:54 +08:00
1 parent 122da6fcff
commit f511e17dbd
9 files changed
+43 -5

No files matched your search

+6
View File
@@ -52,6 +52,11 @@ on:
type: string
default: ''
required: false
compression_level:
description: '本轮安装器压缩等级:0..9;留空保留机器配置'
type: string
default: ''
required: false
permissions:
contents: read
@@ -77,6 +82,7 @@ jobs:
PACKAGE_SIGNING: ${{ inputs.signing }}
PACKAGE_CACHE_NAMESPACE: ${{ inputs.cache_namespace }}
PACKAGE_BUILD_ROOT: ${{ inputs.build_root }}
PACKAGE_WINDOWS_COMPRESSION_LEVEL: ${{ inputs.compression_level }}
steps:
- name: Reset packaging checkout
working-directory: ${{ runner.temp }}
+2 -2
View File
@@ -45,8 +45,8 @@
en: b42f103358d0dfd7
zh: a534164ad9eb00da
/desktop-packaging/runtime-file-selection-and-installation-checks:
en: 34273efbc5084038
zh: f255e29623b6af76
en: d87a53ab0f8b0db9
zh: c3b2b96085f29d3b
/desktop-packaging/desktop-runtime-preparation:
en: bce2ee195a876985
zh: ae45df21c23e86c2
+1 -1
View File
@@ -258,7 +258,7 @@ When extraction fails, the installer writes a report with the 7-Zip result and i
Windows packaging fixes the 7-Zip filter to `BCJ` for compatibility with the bundled NSIS decoder. This preserves ARM64 binaries carried by dependencies in x64 installers; automatic ARM64 filtering produces entries that this decoder cannot extract.
`DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL` in the Windows dotenv or machine preset selects installer archive compression from `0` to `9`. If omitted, the existing `ELECTRON_BUILDER_COMPRESSION_LEVEL` environment override remains effective, otherwise the default is `9`. Lower levels trade installer size for packaging time; qualify the complete signed workflow and artifact size before changing a release preset.
`DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL` in the Windows dotenv or machine preset selects installer archive compression from `0` to `9`. If omitted, the existing `ELECTRON_BUILDER_COMPRESSION_LEVEL` environment override remains effective, otherwise the default is `9`. The manual Windows workflow accepts an optional `compression_level` from `0` to `9` that overrides the file setting for that run; leave it empty to retain the machine setting. Lower levels trade installer size for packaging time; qualify the complete signed workflow and artifact size before changing a release preset.
NSIS removes its temporary extraction tree during installation, before the completion page or an automatic launch. The installed production packages remain ordinary files; startup does not extract them again. Installation still writes the complete application tree.
+1 -1
View File
@@ -258,7 +258,7 @@ Windows 安装器在启动时和选定目标目录后检查应用是否正在运
Windows 打包将 7-Zip 过滤器固定为 `BCJ`,以兼容内置的 NSIS 解码器。这样可以保留 x64 安装包中由依赖携带的 ARM64 二进制文件;自动 ARM64 过滤会生成该解码器无法解压的条目。
Windows dotenv 或机器 preset 中的 `DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL` 选择 `0` 至 `9` 的安装包归档压缩等级。省略时,现有 `ELECTRON_BUILDER_COMPRESSION_LEVEL` 环境覆盖仍然生效,否则默认为 `9`。较低等级以安装包体积换取打包时间;修改发布 preset 前应验证完整签名 workflow 和产物体积。
Windows dotenv 或机器 preset 中的 `DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL` 选择 `0` 至 `9` 的安装包归档压缩等级。省略时,现有 `ELECTRON_BUILDER_COMPRESSION_LEVEL` 环境覆盖仍然生效,否则默认为 `9`。手动 Windows workflow 接受可选的 `compression_level`,取值为 `0` 至 `9`,仅对本轮覆盖文件中的设置;留空则保留机器设置。较低等级以安装包体积换取打包时间;修改发布 preset 前应验证完整签名 workflow 和产物体积。
NSIS 在安装阶段清理临时解压目录,完成后才显示完成页或自动启动应用。已安装的生产依赖保持为普通文件;启动时不会再次解压。安装仍会写入完整的应用目录树。
@@ -10,6 +10,7 @@ export function localMacOSPackageEnvironment(environment?: NodeJS.ProcessEnv): N
/**
* Read a machine preset when selected, otherwise the target's required dotenv; no ambient release fallback.
* PACKAGE_TEST_RELEASE_ID overrides the test preset only; blank retains its configured ID.
* PACKAGE_WINDOWS_COMPRESSION_LEVEL explicitly overrides Windows compression; blank retains the file setting.
* @param platform Target platform.
* @param environment Parent environment, retained only for unrelated build tools.
* @param appRoot Desktop application directory; relative credential paths resolve here.
@@ -37,6 +37,7 @@ export function localMacOSPackageEnvironment(environment = process.env) {
/**
* Read a machine preset when selected, otherwise the target's required dotenv; no ambient release fallback.
* PACKAGE_TEST_RELEASE_ID overrides the test preset only; blank retains its configured ID.
* PACKAGE_WINDOWS_COMPRESSION_LEVEL explicitly overrides Windows compression; blank retains the file setting.
* @param {'win32' | 'darwin'} platform Target platform.
* @param {NodeJS.ProcessEnv} environment Parent environment, retained only for unrelated build tools.
* @param {string} appRoot Desktop application directory; relative credential paths resolve here.
@@ -44,6 +45,12 @@ export function localMacOSPackageEnvironment(environment = process.env) {
* @returns {NodeJS.ProcessEnv} Isolated environment with file-owned release settings.
*/
export function loadDesktopPackageEnvironment(platform, environment = process.env, appRoot = APP_ROOT, options = {}) {
const compression = environment.PACKAGE_WINDOWS_COMPRESSION_LEVEL
if (compression !== undefined && compression !== '') {
if (platform !== 'win32' || !/^[0-9]$/u.test(compression)) {
throw new Error('desktop package: PACKAGE_WINDOWS_COMPRESSION_LEVEL requires Windows and an integer from 0 to 9')
}
}
const preset = environment.DSH_PACKAGING_PRESET
let path = join(appRoot, platform === 'win32' ? '.env.windows' : '.env.macos')
if (preset !== undefined) {
@@ -69,6 +76,7 @@ export function loadDesktopPackageEnvironment(platform, environment = process.en
: MACOS_SETTING.test(name) && !publicPlatformSetting.test(name)))
}
}
if (compression !== undefined && compression !== '') settings.DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL = compression
const releaseId = environment.PACKAGE_TEST_RELEASE_ID?.trim()
if (releaseId) {
if (preset !== 'test') throw new Error('desktop package: test release ID override requires the test preset')
@@ -5,6 +5,7 @@ import { execFileSync } from 'node:child_process'
import { desktopCiVersion as windowsCiVersion } from './desktop-ci-version.mjs'
export { desktopCiVersion as windowsCiVersion } from './desktop-ci-version.mjs'
import { loadDesktopPackageEnvironment, validateDesktopPackageEnvironment } from './desktop-package-environment.mjs'
import { resolveWindowsPackageSettings } from './windows-package-settings.mjs'
if (process.argv[1] !== undefined && resolve(process.argv[1]) === import.meta.filename) {
const appRoot = resolve(import.meta.dirname, '..')
@@ -22,6 +23,7 @@ if (process.argv[1] !== undefined && resolve(process.argv[1]) === import.meta.fi
}
}
validateDesktopPackageEnvironment(environment, { platform: 'win32', arch: 'x64' }, { unsigned: mode === 'unsigned' })
console.log(`Windows installer compression level: ${resolveWindowsPackageSettings(environment).compressionLevel}`)
if (!process.env.GITHUB_OUTPUT || !process.env.GITHUB_STEP_SUMMARY) throw new Error('Run this adapter from GitHub Actions')
appendFileSync(process.env.GITHUB_OUTPUT, `version=${version}\n`)
appendFileSync(process.env.GITHUB_STEP_SUMMARY, `Windows x64 ${mode} installer\n\nVersion: ${version}\n\nCommit: ${execFileSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).trim()}\n\nChannel: ${process.env.DSH_DESKTOP_UPDATE_CHANNEL}\n\nSource: ${process.env.PACKAGE_SOURCE_REF}\n\nPreset: ${process.env.DSH_PACKAGING_PRESET}\n`)
@@ -32,6 +32,25 @@ describe('Desktop local packaging configuration', () => {
})
})
it.each(['0', '3', '9'])('applies an explicit Windows workflow compression override %s', async (value) => {
await withDirectory(async (directory) => {
await writeFile(join(directory, '.env.windows'), 'DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL=5\n')
const selected = loadDesktopPackageEnvironment('win32', { PACKAGE_WINDOWS_COMPRESSION_LEVEL: value }, directory)
expect(resolveWindowsPackageSettings(selected).compressionLevel).toBe(Number(value))
const unchanged = loadDesktopPackageEnvironment('win32', { PACKAGE_WINDOWS_COMPRESSION_LEVEL: '' }, directory)
expect(resolveWindowsPackageSettings(unchanged).compressionLevel).toBe(5)
})
})
it.each([' ', '-1', '10', '3.5', '03', 'fast'])('rejects invalid workflow compression %j before reading settings', (value) => {
expect(() => loadDesktopPackageEnvironment('win32', { PACKAGE_WINDOWS_COMPRESSION_LEVEL: value }, 'missing-settings'))
.toThrow('PACKAGE_WINDOWS_COMPRESSION_LEVEL')
})
it('rejects a Windows compression override for macOS before reading settings', () => {
expect(() => loadDesktopPackageEnvironment('darwin', { PACKAGE_WINDOWS_COMPRESSION_LEVEL: '3' }, 'missing-settings'))
.toThrow('PACKAGE_WINDOWS_COMPRESSION_LEVEL')
})
it.each(['', '-1', '10', '3.5', '03', 'fast'])('rejects invalid compression %j before preparation', (value) => {
const selected = { ...RELEASE, DSH_DESKTOP_WINDOWS_COMPRESSION_LEVEL: value }
expect(() => { validateDesktopPackageEnvironment(selected, WINDOWS, { unsigned: true }) })
+3 -1
View File
@@ -68,9 +68,11 @@ it('routes manual packaging to the dedicated runner with explicit preset and sig
expect(workflow.concurrency).toEqual({ group: 'windows-desktop-package', 'cancel-in-progress': false })
expect(workflow.permissions).toEqual({ contents: 'read' })
expect(Object.keys(workflow.on.workflow_dispatch!.inputs).sort()).toEqual([
'build_root', 'build_version', 'cache_namespace', 'preset', 'signing', 'source_ref', 'test_release_id', 'update_channel', 'version_mode',
'build_root', 'build_version', 'cache_namespace', 'compression_level', 'preset', 'signing', 'source_ref', 'test_release_id', 'update_channel', 'version_mode',
])
expect(workflow.on.workflow_dispatch!.inputs.signing!.default).toBe('signed')
expect(workflow.on.workflow_dispatch!.inputs.compression_level).toMatchObject({ type: 'string', default: '', required: false })
expect(job.env.PACKAGE_WINDOWS_COMPRESSION_LEVEL).toBe('${{ inputs.compression_level }}')
expect(workflow.on.workflow_dispatch!.inputs.build_version!.required).toBe(false)
expect(workflow.on.workflow_dispatch!.inputs.version_mode!.default).toBe('default')
expect(workflow.on.workflow_dispatch!.inputs.source_ref!.default).toBe('master')