fix(linux): make local package architecture explicit

This commit is contained in:
Neil
2026-08-31 05:48:37 -07:00
parent 8c7eb06b51
commit 23a0a829b1
3 changed files with 146 additions and 1 deletions
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env node
import { execFileSync } from 'node:child_process'
import { resolve } from 'node:path'
const SUPPORTED_ARCHES = new Set(['x64', 'arm64'])
/** Select the local Linux package architecture without relying on builder defaults. */
export function resolveLinuxBuildArch({
platform = process.platform,
hostArch = process.arch,
requestedArch = process.env.ORCA_LINUX_BUILD_ARCH
} = {}) {
const arch = requestedArch ?? (platform === 'linux' ? hostArch : 'x64')
if (!SUPPORTED_ARCHES.has(arch)) {
throw new Error(
`Unsupported Linux build architecture: ${arch}. Use ORCA_LINUX_BUILD_ARCH=x64|arm64.`
)
}
return arch
}
export function buildLinuxElectronBuilderArgs(arch, extraArgs = []) {
if (!SUPPORTED_ARCHES.has(arch)) {
throw new Error(`Unsupported Linux build architecture: ${arch}`)
}
return [
'exec',
'electron-builder',
'--config',
'config/electron-builder.config.cjs',
'--linux',
'AppImage',
'deb',
`--${arch}`,
...extraArgs
]
}
export function runLocalLinuxBuild({
arch = resolveLinuxBuildArch(),
extraArgs = [],
environment = process.env,
execFile = execFileSync,
platform = process.platform,
cwd = resolve(import.meta.dirname, '../..')
} = {}) {
const env = { ...environment }
if (arch === 'arm64') {
env.ORCA_LINUX_ARM64_RELEASE = '1'
} else {
delete env.ORCA_LINUX_ARM64_RELEASE
}
const pnpm = platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
execFile(pnpm, buildLinuxElectronBuilderArgs(arch, extraArgs), {
cwd,
env,
stdio: 'inherit'
})
}
if (process.argv[1] && resolve(process.argv[1]) === resolve(import.meta.filename)) {
runLocalLinuxBuild({ extraArgs: process.argv.slice(2) })
}
+81
View File
@@ -0,0 +1,81 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it, vi } from 'vitest'
import {
buildLinuxElectronBuilderArgs,
resolveLinuxBuildArch,
runLocalLinuxBuild
} from './build-linux-local.mjs'
describe('local Linux build target', () => {
it('is the package script used by the local Linux build', () => {
const packageJson = JSON.parse(
readFileSync(resolve(import.meta.dirname, '../../package.json'), 'utf8')
)
expect(packageJson.scripts['build:linux']).toContain(
'node config/scripts/build-linux-local.mjs'
)
})
it('follows a native Linux host architecture', () => {
expect(resolveLinuxBuildArch({ platform: 'linux', hostArch: 'arm64' })).toBe('arm64')
expect(resolveLinuxBuildArch({ platform: 'linux', hostArch: 'x64' })).toBe('x64')
})
it('defaults cross-platform Linux builds to x64 and allows an explicit override', () => {
expect(resolveLinuxBuildArch({ platform: 'darwin', hostArch: 'arm64' })).toBe('x64')
expect(
resolveLinuxBuildArch({ platform: 'darwin', hostArch: 'arm64', requestedArch: 'arm64' })
).toBe('arm64')
})
it('rejects unsupported architectures', () => {
expect(() => resolveLinuxBuildArch({ platform: 'linux', hostArch: 'ia32' })).toThrow(
'Unsupported Linux build architecture'
)
expect(() => buildLinuxElectronBuilderArgs('ia32')).toThrow(
'Unsupported Linux build architecture'
)
})
it('passes an explicit target and matching artifact-name environment', () => {
const execFile = vi.fn()
runLocalLinuxBuild({
arch: 'arm64',
environment: { PATH: '/bin', ORCA_LINUX_ARM64_RELEASE: undefined },
execFile,
platform: 'linux',
cwd: '/workspace'
})
expect(execFile).toHaveBeenCalledWith(
'pnpm',
buildLinuxElectronBuilderArgs('arm64'),
expect.objectContaining({
cwd: '/workspace',
env: expect.objectContaining({ ORCA_LINUX_ARM64_RELEASE: '1' }),
stdio: 'inherit'
})
)
runLocalLinuxBuild({
arch: 'x64',
environment: { PATH: '/bin', ORCA_LINUX_ARM64_RELEASE: '1' },
execFile,
platform: 'linux',
cwd: '/workspace'
})
expect(execFile).toHaveBeenLastCalledWith(
'pnpm',
buildLinuxElectronBuilderArgs('x64'),
expect.objectContaining({
env: expect.not.objectContaining({ ORCA_LINUX_ARM64_RELEASE: expect.anything() })
})
)
})
it('uses the Windows pnpm command name when cross-host packaging', () => {
const execFile = vi.fn()
runLocalLinuxBuild({ arch: 'x64', execFile, platform: 'win32', cwd: 'C:\\workspace' })
expect(execFile.mock.calls[0]?.[0]).toBe('pnpm.cmd')
})
})
+1 -1
View File
@@ -92,7 +92,7 @@
"build:icons": "bash resources/icon-source/generate.sh",
"build:mac": "pnpm run build:desktop && pnpm run build:computer-macos && pnpm run build:keyboard-layout-macos && pnpm run build:notification-status-macos && pnpm run ensure:electron-runtime && node config/scripts/build-mac-local.mjs",
"build:mac:release": "node config/scripts/verify-macos-release-env.mjs && ORCA_MAC_RELEASE=1 pnpm run build:desktop && ORCA_MAC_RELEASE=1 pnpm run build:computer-macos && ORCA_MAC_RELEASE=1 pnpm run build:keyboard-layout-macos && ORCA_MAC_RELEASE=1 pnpm run build:notification-status-macos && pnpm run ensure:electron-runtime && ORCA_MAC_RELEASE=1 electron-builder --config config/electron-builder.config.cjs --mac",
"build:linux": "pnpm run build:desktop && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --linux AppImage deb rpm",
"build:linux": "pnpm run build:desktop && pnpm run ensure:electron-runtime && node config/scripts/build-linux-local.mjs",
"test:e2e": "pnpm run ensure:electron-runtime && npx playwright test --config tests/playwright.config.ts --project=electron-headless",
"test:e2e:workspace-session-golden": "pnpm run ensure:electron-runtime && npx playwright test tests/e2e/golden-quit-relaunch-session.spec.ts tests/e2e/golden-terminal-file-link.spec.ts tests/e2e/golden-worktree-create-switch.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1",
"test:e2e:multi-client-navigation": "node config/scripts/run-multi-client-navigation-e2e.mjs",