fix(updater): preserve active Linux package recovery

This commit is contained in:
Neil
2026-09-01 22:40:14 -07:00
parent 04f2a826c4
commit 7c3aa110b9
5 changed files with 36 additions and 5 deletions
@@ -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')
+19
View File
@@ -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())
+6 -1
View File
@@ -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
}
@@ -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'
@@ -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.