Merge branch 'feat/desktop-electron-app'
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / node 22.19 (push) Has been cancelled
CI / node 26 (push) Has been cancelled
CI / python 3.10 / keyless SDK (push) Has been cancelled
CI / windows node 24 / wine blocking (push) Has been cancelled
CI / wine apt cache (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Has been cancelled
Release (vendor) / Pack npm tarballs (push) Has been cancelled
Release (vendor) / Publish to npm (push) Has been cancelled
Release (dsh) / Pack npm tarballs (push) Has been cancelled
Release (dsh) / Publish to npm (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Has been cancelled
Deploy documentation / build (push) Has been cancelled
Landlock Run / Matrix (push) Has been cancelled
Landlock Run / darwin (no platform package — degradation proof) (push) Has been cancelled
Deploy documentation / deploy (push) Has been cancelled
Landlock Run / ${{ matrix.platform }} (push) Has been cancelled
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / node 22.19 (push) Has been cancelled
CI / node 26 (push) Has been cancelled
CI / python 3.10 / keyless SDK (push) Has been cancelled
CI / windows node 24 / wine blocking (push) Has been cancelled
CI / wine apt cache (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Has been cancelled
Release (vendor) / Pack npm tarballs (push) Has been cancelled
Release (vendor) / Publish to npm (push) Has been cancelled
Release (dsh) / Pack npm tarballs (push) Has been cancelled
Release (dsh) / Publish to npm (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Has been cancelled
Deploy documentation / build (push) Has been cancelled
Landlock Run / Matrix (push) Has been cancelled
Landlock Run / darwin (no platform package — degradation proof) (push) Has been cancelled
Deploy documentation / deploy (push) Has been cancelled
Landlock Run / ${{ matrix.platform }} (push) Has been cancelled
# Conflicts: # apps/desktop/scripts/build-harness.mjs
This commit is contained in:
@@ -17,6 +17,11 @@
|
||||
* `scripts/harness-excludes.json`). Nothing is excluded unless it is provably
|
||||
* outside the dsh runtime dependency closure.
|
||||
*
|
||||
* The copy is followed by a relink pass (harness-relink.mjs) that rewrites every
|
||||
* Windows junction / absolute link into a RELATIVE in-tree symlink, so the
|
||||
* packaged harness no longer references the build machine's dev tree, then by a
|
||||
* self-containment check and a `dsh --version` smoke test.
|
||||
*
|
||||
* Run from the repository root before `desktop:pack`.
|
||||
*/
|
||||
|
||||
@@ -24,6 +29,7 @@ import { cpSync, chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, read
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { assertSelfContained, probeSymlinkSupport, relinkHarness } from './harness-relink.mjs'
|
||||
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), '../../..')
|
||||
const out = join(root, 'apps/desktop/build/harness')
|
||||
@@ -32,13 +38,41 @@ const out = join(root, 'apps/desktop/build/harness')
|
||||
const harnessDirs = ['node_modules', 'vendor', 'packages', 'native']
|
||||
const extraDirs = [['apps/cli', 'apps/cli'], ['apps/web', 'apps/web']]
|
||||
|
||||
// A compact, portable harness depends on rewriting Windows junctions / absolute
|
||||
// links into RELATIVE in-tree symlinks (see harness-relink.mjs). If this host
|
||||
// cannot create directory symlinks, the only fallback is dereferencing the whole
|
||||
// pnpm store — a multi-GB bloat — so refuse unless --dereference-ok opts in.
|
||||
const dereferenceOk = process.argv.includes('--dereference-ok')
|
||||
if (!probeSymlinkSupport() && !dereferenceOk) {
|
||||
throw new Error(
|
||||
'cannot assemble a self-contained harness: this host cannot create directory symlinks.\n' +
|
||||
'Enable Windows Developer Mode or run as an administrator (macOS and Linux need no setup),\n' +
|
||||
'or pass --dereference-ok to accept a much larger dereferenced harness.',
|
||||
)
|
||||
}
|
||||
|
||||
// A missing critical dir silently shipped a broken (link-less) harness before.
|
||||
// Refuse loudly instead: each one must exist, and lib/web must already be built.
|
||||
for (const d of [...harnessDirs, ...extraDirs.map(([src]) => src)]) {
|
||||
if (!existsSync(join(root, d))) {
|
||||
throw new Error(`cannot build the harness: ${d}/ is missing — run \`pnpm install\` first`)
|
||||
}
|
||||
}
|
||||
for (const [label, path] of [
|
||||
['the dsh CLI (apps/cli/lib/bin.js)', join(root, 'apps/cli/lib/bin.js')],
|
||||
['the web frontend dist (apps/web/dist)', join(root, 'apps/web/dist')],
|
||||
]) {
|
||||
if (!existsSync(path)) {
|
||||
throw new Error(`cannot build the harness: ${label} is missing — run \`pnpm desktop:build\` first`)
|
||||
}
|
||||
}
|
||||
|
||||
rmSync(out, { recursive: true, force: true })
|
||||
mkdirSync(join(out, 'apps'), { recursive: true })
|
||||
mkdirSync(join(out, 'bin'), { recursive: true })
|
||||
|
||||
for (const d of harnessDirs) {
|
||||
const src = join(root, d)
|
||||
if (existsSync(src)) cpSync(src, join(out, d), { recursive: true })
|
||||
cpSync(join(root, d), join(out, d), { recursive: true })
|
||||
}
|
||||
for (const [src, dst] of extraDirs) {
|
||||
cpSync(join(root, src), join(out, dst), { recursive: true })
|
||||
@@ -246,3 +280,32 @@ function fmtSize(bytes) {
|
||||
}
|
||||
|
||||
console.log(`assembled self-contained harness at ${out}`)
|
||||
|
||||
// Normalize every link to a relative in-tree target, then prove the tree no
|
||||
// longer references the build machine. This is the guarantee that the packaged
|
||||
// app runs detached from the development environment. Re-run until a pass makes
|
||||
// no further changes: rewriting one link can expose another (e.g. a package the
|
||||
// copy dereferenced into a real dir whose internal links only become reachable
|
||||
// on the next walk), so a single pass may not converge.
|
||||
let report
|
||||
for (let pass = 1; pass <= 5; pass += 1) {
|
||||
report = relinkHarness(out, root)
|
||||
console.log(
|
||||
`relink pass ${pass}: ${report.normalized} rewritten, ${report.unchanged} in-tree, ` +
|
||||
`${report.dereferenced} dereferenced, ${report.removed} dropped`,
|
||||
)
|
||||
if (report.errors.length > 0) {
|
||||
throw new Error(`harness relink failed:\n${report.errors.join('\n')}`)
|
||||
}
|
||||
if (report.normalized === 0 && report.removed === 0) break
|
||||
}
|
||||
assertSelfContained(out)
|
||||
console.log('harness links: self-contained (no link escapes the bundle)')
|
||||
|
||||
// Boot smoke: the bundled CLI must run straight from the bundle, proving the
|
||||
// relinked node_modules resolves without the repository present.
|
||||
const version = execFileSync(join(out, 'bin', nodeFile), [join(out, 'apps/cli/lib/bin.js'), '--version'], {
|
||||
cwd: out,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
console.log(`bundled dsh: ${version.trim()}`)
|
||||
|
||||
Reference in New Issue
Block a user