Skip to content

Commit b456ed9

Browse files
fix(cli): preserve update failures during lock cleanup
1 parent f81de44 commit b456ed9

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

packages/sim-cli/src/update/install.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,39 @@ describe('installing a CLI update', () => {
340340
expect(output.join('')).not.toContain('Updated Sim')
341341
})
342342

343+
it.each(['registry', 'installer'])(
344+
'preserves the original %s failure when releasing the lock also fails',
345+
async (phase) => {
346+
const failure = new CliUpdateError(`${phase} permission denied`)
347+
const run = vi.fn().mockResolvedValueOnce(join(directory, 'node_modules'))
348+
if (phase === 'installer') run.mockResolvedValueOnce(JSON.stringify('2.1.5'))
349+
run.mockImplementationOnce(async () => {
350+
writeFileSync(join(`${packageRoot}.lock`, 'obstruction'), '')
351+
throw failure
352+
})
353+
354+
await expect(installUpdate({ ...options(), run })).rejects.toBe(failure)
355+
expect(output.join('')).toContain('Cannot release the Sim update lock')
356+
expect(output.join('')).not.toContain('Updated Sim')
357+
}
358+
)
359+
360+
it('fails with a CLI error when only releasing the lock fails', async () => {
361+
const run = vi
362+
.fn()
363+
.mockResolvedValueOnce(join(directory, 'node_modules'))
364+
.mockImplementationOnce(async () => {
365+
writeFileSync(join(`${packageRoot}.lock`, 'obstruction'), '')
366+
return JSON.stringify('2.1.2')
367+
})
368+
369+
await expect(installUpdate({ ...options(), run })).rejects.toMatchObject({
370+
constructor: CliUpdateError,
371+
message: expect.stringContaining('Cannot release the Sim update lock'),
372+
cause: expect.objectContaining({ code: 'ENOTEMPTY' }),
373+
})
374+
})
375+
343376
it.each(['invalid', '2.1.5-dev.1.1'])(
344377
'rejects an invalid or wrong-channel installed version: %s',
345378
async (version) => {

packages/sim-cli/src/update/install.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ export async function installUpdate(options: InstallUpdateOptions = {}): Promise
220220
throw new CliUpdateError(`Cannot lock Sim for update: ${getErrorMessage(cause)}`, { cause })
221221
}
222222
)
223+
let updateFailed = false
223224
try {
224225
if (readInstalledVersion(installedEntry) !== currentVersion) {
225226
throw new CliUpdateError(
@@ -267,11 +268,17 @@ export async function installUpdate(options: InstallUpdateOptions = {}): Promise
267268
write(
268269
`Updated Sim ${currentVersion}${version}. The next invocation will use the new version.\n`
269270
)
271+
} catch (error) {
272+
updateFailed = true
273+
throw error
270274
} finally {
271275
await release().catch((cause: unknown) => {
272-
throw new CliUpdateError(`Cannot release the Sim update lock: ${getErrorMessage(cause)}`, {
273-
cause,
274-
})
276+
const message = `Cannot release the Sim update lock: ${getErrorMessage(cause)}`
277+
if (updateFailed) {
278+
write(`${message}\n`)
279+
} else {
280+
throw new CliUpdateError(message, { cause })
281+
}
275282
})
276283
}
277284
}

0 commit comments

Comments
 (0)