test(e2e/windows): the app-update driver waits out the real update and checks staged main
Once launch capture works, two Windows hermes-desktop-app-update failures
show up (run 36286580917):
- v2026.9.24 -> HEAD (installer-script, installer-script+desktop,
desktop-installer@latest): the app's update is correct but slow. From
v2026.9.24 it runs the historical venv->PM takeover and a full Desktop
rebuild (the `hermes update` alone took 9m43s). launch-from-spec's 10 min
default gave up 9m55s after the Update now click while the updater window
showed "Updating code and dependencies 9m 22s elapsed". windows-e2e.ps1
now passes --timeout-ms 1800000, in line with open-app-update's 35 min
wait. The driver's self-deadline is now measured after the update wait
instead of being a flat 20 min inside it.
- HEAD -> NEXT: Desktop offered real GitHub main (0f4a98f8) instead of the
staged NEXT, so assertStagedBranch refused to click. HEAD's Electron main
is one ESM bundle, and checkout-source.ts binds promisify(execFile) at
load, before installSourceBranchProbe patches execFile in the packaged
app. POSIX avoids this by wrapping the launcher script, which Windows
skips. The probe now also hooks ChildProcess.prototype.spawn, which every
child passes through, and reuses branchProbeArgs, which already knows both
the --run-module and cmd.exe .cmd shapes. Verified locally: a promisify
captured before the hook now gets `--git <real> --branch main`, and other
commands are untouched.
This commit is contained in:
@@ -114,13 +114,6 @@ async function main() {
|
||||
// holding node's event loop open, so the driver can outlive its own
|
||||
// finished test. Success and failure paths exit explicitly; this unref'd
|
||||
// timer is the backstop so no unknown state holds a runner past its budget.
|
||||
const SELF_DEADLINE_MS = 20 * 60 * 1000;
|
||||
const selfDeadline = setTimeout(() => {
|
||||
log(`DRIVER SELF-TIMEOUT after ${SELF_DEADLINE_MS / 60000}min - exiting 124 (phase: ${currentPhase})`);
|
||||
process.exit(124);
|
||||
}, SELF_DEADLINE_MS);
|
||||
selfDeadline.unref();
|
||||
|
||||
const { values } = parseArgs({
|
||||
options: {
|
||||
spec: { type: 'string' },
|
||||
@@ -134,6 +127,14 @@ async function main() {
|
||||
'timeout-ms': { type: 'string', default: '600000' },
|
||||
},
|
||||
});
|
||||
// After the update wait (--timeout-ms), not inside it: launch, OLD chat and
|
||||
// relaunch checks get their own 20 minutes.
|
||||
const SELF_DEADLINE_MS = Number(values['timeout-ms']) + 20 * 60 * 1000;
|
||||
const selfDeadline = setTimeout(() => {
|
||||
log(`DRIVER SELF-TIMEOUT after ${SELF_DEADLINE_MS / 60000}min - exiting 124 (phase: ${currentPhase})`);
|
||||
process.exit(124);
|
||||
}, SELF_DEADLINE_MS);
|
||||
selfDeadline.unref();
|
||||
if (!values.spec) throw new Error('--spec is required');
|
||||
if (!values['old-sha'] || !values['chat-out'] || !values['mock-url'] || !values['repo-dir']) {
|
||||
throw new Error('--old-sha, --chat-out, --mock-url and --repo-dir are required for OLD chat');
|
||||
|
||||
@@ -131,6 +131,19 @@ if (process.env.HERMES_E2E_SOURCE_ROOT && process.env.HERMES_E2E_SOURCE_GIT) {
|
||||
}
|
||||
const custom = Symbol.for('nodejs.util.promisify.custom')
|
||||
childProcess.execFile[custom] = (file, args, options) => original[custom](file, select(args), options)
|
||||
// HEAD's Electron main is one ESM bundle: checkout-source.ts bound
|
||||
// promisify(execFile) at load, before installSourceBranchProbe runs in the
|
||||
// packaged app, so neither hook above reaches it. Every child still goes
|
||||
// through ChildProcess.prototype.spawn, whose args carry argv0 first.
|
||||
const proto = childProcess.ChildProcess.prototype
|
||||
const spawnChild = proto.spawn
|
||||
proto.spawn = function (options) {
|
||||
const rest = Array.isArray(options?.args) ? options.args.slice(1) : null
|
||||
const selected = rest && select(rest)
|
||||
return spawnChild.call(this, selected && selected !== rest
|
||||
? { ...options, args: [options.args[0], ...selected] }
|
||||
: options)
|
||||
}
|
||||
// v2026.9.21 does its source check in Electron: remote get-url selects
|
||||
// GitHub's public REST API unless its real Git process sees staged origin.
|
||||
// Redirect only the legacy check's two Git reads, not arbitrary subprocesses.
|
||||
|
||||
@@ -610,10 +610,13 @@ function Invoke-HermesDesktopAppUpdate([string]$TargetSha) {
|
||||
$prevEap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
|
||||
Push-Location $WorkRoot
|
||||
try {
|
||||
# 30 min, not the 10 min default: from v2026.9.24 the app's update
|
||||
# runs the historical venv->PM takeover plus a full Desktop rebuild
|
||||
# (9m43s measured), like the 35 min open-app-update wait below.
|
||||
& $node (Join-Path $AssetsDir "launch-from-spec.mjs") --spec $spec `
|
||||
--old-sha (Read-State).old --chat-out $chatOut --mock-url $env:HERMES_E2E_MOCK_URL `
|
||||
--result (Join-Path $HermesHome ".hermes-update-result.json") `
|
||||
--expect-sha $TargetSha --repo-dir $InstallDir 2>&1 |
|
||||
--expect-sha $TargetSha --repo-dir $InstallDir --timeout-ms 1800000 2>&1 |
|
||||
ForEach-Object { Write-Host " pw| $_" }
|
||||
$driveExit = $LASTEXITCODE
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user