diff --git a/config/scripts/pr-workflow-parallelism.test.mjs b/config/scripts/pr-workflow-parallelism.test.mjs index 8a4dffe70ee..1253bc01cd2 100644 --- a/config/scripts/pr-workflow-parallelism.test.mjs +++ b/config/scripts/pr-workflow-parallelism.test.mjs @@ -96,8 +96,13 @@ describe('PR workflow parallelism', () => { .split(/\s+/) .filter((token) => !['apt-get', 'install', 'sudo', ''].includes(token)) .filter((token) => !token.startsWith('-')) - const jobsInstallingPackages = Object.entries(workflow.jobs) - .filter(([, job]) => (job.steps ?? []).some((step) => aptPackages(step).length > 0)) + const requiredShells = ['zsh', 'fish'] + const jobsInstallingShells = Object.entries(workflow.jobs) + .filter(([, job]) => + (job.steps ?? []).some((step) => + aptPackages(step).some((packageName) => requiredShells.includes(packageName)) + ) + ) .map(([name]) => name) expect(shellStep).toBeDefined() @@ -105,11 +110,11 @@ describe('PR workflow parallelism', () => { expect(shellStep.run.split(/\s+/)).toContain('--maxWorkers=1') // Why the whole workflow, not just the general shards: any other lane installing // these shells would silently start running the real-shell tests twice. - expect(jobsInstallingPackages).toEqual(['shell_contracts']) + expect(jobsInstallingShells).toEqual(['shell_contracts']) // Why each shell is asserted: the live tests skip themselves when the binary is // missing, so a dropped package silently empties this lane instead of failing it. const shellPackages = workflow.jobs.shell_contracts.steps.flatMap(aptPackages) - for (const shell of ['zsh', 'fish']) { + for (const shell of requiredShells) { expect(shellPackages).toContain(shell) } expect(shellInstall.with['native-runtime']).toBe('node') diff --git a/src/main/updater-events.test.ts b/src/main/updater-events.test.ts index faa713d6c68..092995c50cd 100644 --- a/src/main/updater-events.test.ts +++ b/src/main/updater-events.test.ts @@ -270,6 +270,25 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => { }) }) + it('keeps manual-install recovery when a later check finds only the installed release', async () => { + const { emit, context, getArtifact } = await register() + emit('update-downloaded', downloadedEvent()) + + emit('update-available', { version: '1.0.51' }) + + expect(getArtifact()).toEqual(expect.objectContaining({ version: '1.0.61' })) + expect(context.sendStatus).toHaveBeenLastCalledWith({ + state: 'error', + message: 'Quit Orca before running the system package install command.', + recovery: { + kind: 'linux-package-install', + packageType: 'deb', + reason: 'manual-install-required', + version: '1.0.61' + } + }) + }) + it('clears recovery when a newer update takes over before no-update settles', async () => { const { emit, context, getArtifact } = await register() emit('update-downloaded', downloadedEvent()) diff --git a/src/main/updater-events.ts b/src/main/updater-events.ts index c0546abd807..4503aa1e04e 100644 --- a/src/main/updater-events.ts +++ b/src/main/updater-events.ts @@ -150,7 +150,12 @@ export function registerAutoUpdaterHandlers({ scheduleAutomaticUpdateCheck(AUTO_UPDATE_CHECK_INTERVAL_MS) } } - sendStatus({ state: 'not-available', userInitiated: wasUserInitiated || undefined }) + sendStatus( + getRetainedLinuxPackageManualInstallStatus() ?? { + state: 'not-available', + userInitiated: wasUserInitiated || undefined + } + ) return } diff --git a/src/main/updater.headless-serve-install.test.ts b/src/main/updater.headless-serve-install.test.ts index 1c756f2f4ce..b33b8a4fd3b 100644 --- a/src/main/updater.headless-serve-install.test.ts +++ b/src/main/updater.headless-serve-install.test.ts @@ -169,6 +169,7 @@ describe('headless serve update install handoff', () => { checkForUpdatesFromMenu() await vi.advanceTimersByTimeAsync(0) + autoUpdaterMock.emit('download-progress', { percent: 100 }) autoUpdaterMock.emit('update-downloaded', { version: pendingInstaller.version }) const nativeReadyHandler = nativeUpdaterMock.on.mock.calls.find( ([event]) => event === 'update-downloaded' diff --git a/src/main/updater.quit-and-install.test.ts b/src/main/updater.quit-and-install.test.ts index 945538b3895..05044c203f8 100644 --- a/src/main/updater.quit-and-install.test.ts +++ b/src/main/updater.quit-and-install.test.ts @@ -287,6 +287,7 @@ describe('updater', () => { }) }) + autoUpdaterMock.emit('download-progress', { percent: 100 }) autoUpdaterMock.emit('update-downloaded', { version: '1.0.61' }) // Why: on macOS install commits only once Squirrel is ready; mark it ready so this test covers the post-commit path on all platforms.