Files
orca/config/scripts/reclaim-electron-dists.mjs
Neil 2e30187560 feat(dev): sweep the backlog of idle dev Electron bundles (#17803)
* fix(dev): make reclaim report real sizes on Windows and keep setuid intact

Two bugs found by running the reclaim script on real Linux and Windows hosts.

The size report shelled out to `du`, which does not exist on Windows, so every
worktree measured 0 bytes and the script reported nothing reclaimable on the
platform with the largest dist (374MB). Walk the tree in Node instead.

makeTreeReadOnly chmod'd files to a flat 0o555, which clears setuid. On Linux
that would silently strip the bit from chrome-sandbox if a developer had run
the usual `sudo chown root && chmod 4755` workaround -- and under hardlink
sharing it would strip it from every worktree and the cache at once. Clear the
write bits and nothing else.

Measured after the fix: 7.30 GiB across 23 worktrees on one Windows host and
18.31 GiB across 56 on another, both previously reported as 0.

* feat(dev): sweep the backlog of idle dev Electron bundles

out/electron-dev holds one ~275MB patched Electron.app per branch title x
Electron version. The dev runner already prunes them, but only inside the
worktree it is starting and only when that worktree holds more than one bundle
-- and a worktree almost always holds exactly one, so the sweep returns early
every time and nothing ever reclaims another worktree's bundle.

pnpm reclaim:dev-bundles sweeps across every worktree of the repo. Bundles are
pure build output that pnpm dev rebuilds on demand, and rebuilding is cheap now
that the Electron dist is shared.

Reuses the runner's own staleness rules, so a bundle a live process is running
from, or one whose build is still in flight, is never removed. Refuses to run
at all if the process table cannot be read, rather than guessing.

Measured: 120 bundles, 32.2 GiB, on one machine.

Also guards both reclaim scripts behind a direct-invocation check; importing
one for tests previously ran a full sweep at import time.
2026-08-31 22:18:50 -07:00

177 lines
5.4 KiB
JavaScript

#!/usr/bin/env node
// Converts worktrees that already have their own Electron dist over to the shared cache.
// A normal install only shares when Electron is (re)installed, and an existing healthy worktree
// never reaches that path -- so without this, sharing only arrives at the next Electron upgrade.
import { execFileSync } from 'node:child_process'
import { randomUUID } from 'node:crypto'
import {
existsSync,
readFileSync,
readdirSync,
renameSync,
rmSync,
statSync,
writeFileSync
} from 'node:fs'
import path from 'node:path'
import {
hasAdoptedSharedElectronDist,
isUsableElectronDist,
publishSharedElectronDist,
recordAdoptedSharedElectronDist,
resolveSharedElectronDistEntry,
shareElectronDistFromCache
} from './shared-electron-dist-cache.mjs'
import { getElectronPlatformPath } from './electron-platform-path.mjs'
const apply = process.argv.includes('--apply')
const repoRoot = process.argv.includes('--repo')
? path.resolve(process.argv[process.argv.indexOf('--repo') + 1])
: process.cwd()
function listWorktrees(root) {
const raw = execFileSync('git', ['-C', root, 'worktree', 'list', '--porcelain'], {
encoding: 'utf8'
})
return raw
.split('\n')
.filter((line) => line.startsWith('worktree '))
.map((line) => line.slice('worktree '.length).trim())
}
/** Apparent size, walked in Node: `du` does not exist on Windows, where it silently reported 0. */
function measure(targetPath) {
let total = 0
let entries
try {
entries = readdirSync(targetPath, { withFileTypes: true })
} catch {
return 0
}
for (const entry of entries) {
const entryPath = path.join(targetPath, entry.name)
if (entry.isDirectory()) {
total += measure(entryPath)
} else if (!entry.isSymbolicLink()) {
total += statSync(entryPath, { throwIfNoEntry: false })?.size ?? 0
}
}
return total
}
/** Swap in a shared copy behind a rename, so an interrupted run never leaves a partial dist. */
function adoptInto(distPath, entry, identity) {
const stagePath = `${distPath}.reclaim-${process.pid}-${randomUUID()}`
if (!shareElectronDistFromCache(entry, stagePath, identity)) {
rmSync(stagePath, { recursive: true, force: true })
return false
}
const previousPath = `${distPath}.previous-${process.pid}-${randomUUID()}`
renameSync(distPath, previousPath)
try {
renameSync(stagePath, distPath)
} catch (error) {
renameSync(previousPath, distPath)
rmSync(stagePath, { recursive: true, force: true })
throw error
}
rmSync(previousPath, { recursive: true, force: true })
return true
}
function main() {
let reclaimed = 0
let converted = 0
let skipped = 0
for (const worktree of listWorktrees(repoRoot)) {
const electronPackageDir = path.join(worktree, 'node_modules', 'electron')
const distPath = path.join(electronPackageDir, 'dist')
if (!existsSync(path.join(electronPackageDir, 'package.json')) || !existsSync(distPath)) {
continue
}
if (statSync(distPath, { throwIfNoEntry: false })?.isDirectory() !== true) {
continue
}
let version
try {
version = JSON.parse(
readFileSync(path.join(electronPackageDir, 'package.json'), 'utf8')
).version
} catch {
continue
}
const targetPlatform = process.platform
const targetArch = process.arch
let platformPath
try {
platformPath = getElectronPlatformPath(targetPlatform)
} catch {
continue
}
if (!isUsableElectronDist(distPath, version, platformPath)) {
console.log(`skip ${worktree} (dist is not a complete Electron ${version})`)
skipped += 1
continue
}
const entry = resolveSharedElectronDistEntry({
repoRoot: worktree,
electronPackageDir,
version,
targetPlatform,
targetArch
})
if (entry === null) {
continue
}
if (hasAdoptedSharedElectronDist(entry)) {
continue
}
const size = measure(distPath)
if (!apply) {
console.log(`would share ${worktree} ${(size / 1024 ** 3).toFixed(2)} GiB (${version})`)
reclaimed += size
converted += 1
continue
}
try {
if (!existsSync(entry.entryPath)) {
if (publishSharedElectronDist(distPath, entry, { version, platformPath })) {
recordAdoptedSharedElectronDist(entry, writeFileSync)
console.log(`seeded ${worktree} -> ${entry.entryPath}`)
converted += 1
}
continue
}
if (adoptInto(distPath, entry, { version, platformPath })) {
recordAdoptedSharedElectronDist(entry, writeFileSync)
reclaimed += size
converted += 1
console.log(`shared ${worktree} reclaimed ${(size / 1024 ** 3).toFixed(2)} GiB`)
}
} catch (error) {
// A worktree that fails is left exactly as it was; it still has its own working dist.
console.warn(`skip ${worktree} (${error instanceof Error ? error.message : String(error)})`)
skipped += 1
}
}
console.log(
`\n${apply ? 'Shared' : 'Would share'} ${converted} worktree(s); ` +
`${apply ? 'reclaimed' : 'reclaimable'} ~${(reclaimed / 1024 ** 3).toFixed(2)} GiB` +
`${skipped > 0 ? `; skipped ${skipped}` : ''}` +
`${apply ? '' : '\nRe-run with --apply to do it.'}`
)
}
// Guarded so importing this module for tests does not sweep the whole repository.
if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(import.meta.filename)) {
main()
}