Cancel active provisioning jobs when rolling back betas

This commit is contained in:
2026-10-05 17:48:46 -04:00
parent 6ad5e7f4c6
commit 701066aaf8
25 changed files with 564 additions and 37 deletions
+24 -1
View File
@@ -395,7 +395,7 @@ describe('shared activation and partial writes', () => {
.get('legacy-drift') as { provisioning_id: string; restart_state: string; error: string };
const restoration = db().prepare('SELECT provisioning_id FROM deployment_servers WHERE deployment_id = ?')
.get(rollback.deploymentId) as { provisioning_id: string };
expect(old).toMatchObject({ restart_state: 'failed', error: expect.stringContaining('changed while queued') });
expect(old).toMatchObject({ restart_state: 'failed', error: expect.stringContaining('Superseded by rollback') });
expect(restoration.provisioning_id).not.toBe(old.provisioning_id);
});
@@ -438,3 +438,26 @@ describe('shared activation and partial writes', () => {
expect(komodoRestart).not.toHaveBeenCalled();
});
});
describe('rollback supersedes provisioning', () => {
it.each(['when-empty', 'manual'] as const)('replaces an unhealthy beta restart with a %s rollback without waiting for recovery', async restart => {
const beta = await queueChange('beta');
const { db } = await import('../../src/lib/server/db/index.js');
const { rollbackBeta } = await import('../../src/lib/server/fleet/beta.js');
const { komodoInspectHealthy, komodoRestart } = await import('../../src/lib/server/integrations/komodo.js');
await tick('beta');
const old = db().prepare('SELECT provisioning_id FROM beta_servers WHERE beta_id=?').get(beta.sourceId) as { provisioning_id: string };
expect(db().prepare('SELECT state FROM server_deployments WHERE id=?').get(old.provisioning_id)).toEqual({ state: 'awaiting-health' });
vi.mocked(komodoInspectHealthy).mockResolvedValue({ ok: false, state: 'exited', reason: 'container failed to start' });
const rollback = await rollbackBeta(Number(beta.sourceId), { restart });
expect(db().prepare('SELECT state FROM server_deployments WHERE id=?').get(old.provisioning_id)).toEqual({ state: 'cancelled' });
expect(db().prepare('SELECT * FROM restart_rollout WHERE operation_id=?').all(old.provisioning_id)).toEqual([]);
const replacement = db().prepare('SELECT provisioning_id,restart_state FROM deployment_servers WHERE deployment_id=?').get(rollback.deploymentId) as { provisioning_id: string; restart_state: string };
expect(replacement.provisioning_id).not.toBe(old.provisioning_id);
await tick('campaign');
expect(await readFile(destination())).toEqual(restart === 'manual' ? after : before);
expect(komodoRestart).toHaveBeenCalledTimes(restart === 'manual' ? 1 : 2);
expect(db().prepare('SELECT state FROM server_deployments WHERE id=?').get(replacement.provisioning_id))
.toEqual({ state: restart === 'manual' ? 'waiting' : 'awaiting-health' });
});
});