export interface E2EEnvironment { readonly environment: Record; destroy(): Promise; } export async function runE2ELifecycle(params: { provision: () => Promise; prepare: (environment: TEnvironment) => Promise; bootstrap: (environment: TEnvironment) => Promise; runChild: (environment: Record) => Promise; }): Promise { const environment = await params.provision(); let mainFailure: Error | undefined; let exitCode: number | undefined; try { await params.prepare(environment); await params.bootstrap(environment); exitCode = await params.runChild(environment.environment); } catch (error) { mainFailure = error instanceof Error ? error : new Error(String(error)); } try { await environment.destroy(); } catch (cleanupError) { if (!mainFailure) { throw cleanupError; } throw new AggregateError([mainFailure, cleanupError], "E2E execution and cleanup failed."); } if (mainFailure) { throw mainFailure; } return exitCode ?? 1; }