@@ -20,7 +20,7 @@ import { previewSpec, releaseRuntime, runtimeMetadata, type RunOutput } from "..
2020import { artifactManifestFilesByPath , parseBenchResults , writeBenchmarkArtifactEvidence } from "./recipe-run-benchmark-artifacts.js"
2121import { createRecipeRunContext } from "./recipe-run-context.js"
2222import { collectRecipeDeclaredArtifacts , materializeTypedRecipeDeclaredArtifacts , recipeDeclaredArtifactFailure , recipeProbeFailure , recipeRuntimeEvidenceFiles } from "./recipe-declared-artifacts.js"
23- import { completedRecipeOutputFields , finalizeCompletedRecipeRun , finalizeRecipeValidationFailure , finalizeRecoveredRecipeFailure , runRecipeCleanup , type RunResourceCleanupEvidence } from "./recipe-run-finalizer.js"
23+ import { completedRecipeOutputFields , finalizeCompletedRecipeRun , finalizeRecipeValidationFailure , finalizeRecoveredRecipeFailure , runRecipeCleanup , RunResourceCleanupError , type RunResourceCleanupEvidence } from "./recipe-run-finalizer.js"
2424import { RecipeRunPhaseExecutor } from "./recipe-run-phase-executor.js"
2525import { RecipeArtifactsMountConflictError , recipeArtifactsMountConflict } from "./recipe-run-artifacts-mount-guard.js"
2626import { createRecipeInterruptionController , interruptedRecipeOutput , markRecipeArtifactsFinalized , recipeInterruptionSerializedError } from "./recipe-run-interruption.js"
@@ -353,7 +353,7 @@ async function runRecipe(options: RecipeRunOptions, interruption?: RecipeInterru
353353 await markPreviewLeaseAvailable ( options . previewLeaseFile , { runId : runRecord . runId , preview : artifacts . preview , holdSeconds : options . previewHoldSeconds } )
354354 }
355355 const activeRuntime = runtime
356- cleanupEvidence = await runRecipeCleanup ( runRegistry , runRecord , async ( ) => {
356+ cleanupEvidence = await runManagedServiceCleanup ( runRegistry , runRecord , serviceEvidence , false , async ( ) => {
357357 await awaitRecipe ( "runtime.release" , async ( ) => {
358358 try {
359359 await releaseRuntime ( activeRuntime , successfulRecipe && options . previewHoldBlocking ? options . previewHoldSeconds : 0 , async ( ) => {
@@ -371,7 +371,6 @@ async function runRecipe(options: RecipeRunOptions, interruption?: RecipeInterru
371371 await cleanupRecipePreparedSources ( workspaceMounts , extraPlugins , stagedFiles , overlays , dependencyOverlays )
372372 await cleanupInputMountBaselines ( inputMountBaselinePaths )
373373 } )
374- runRecord = await runRegistry . update ( runRecord . runId , { metadata : { managedRuntimeServices : serviceEvidence } } )
375374 runRecord = await runRegistry . read ( runRecord . runId )
376375 interruption ?. throwIfInterrupted ( )
377376
@@ -506,12 +505,11 @@ async function runRecipe(options: RecipeRunOptions, interruption?: RecipeInterru
506505 ] )
507506 }
508507
509- cleanupEvidence = await runRecipeCleanup ( runRegistry , runRecord , async ( ) => {
508+ cleanupEvidence = await runManagedServiceCleanup ( runRegistry , runRecord , serviceEvidence , true , async ( ) => {
510509 await managedServices ?. release ( )
511510 await cleanupRecipePreparedSources ( workspaceMounts , extraPlugins , stagedFiles , overlays , dependencyOverlays )
512511 await cleanupInputMountBaselines ( inputMountBaselinePaths )
513512 } )
514- runRecord = await runRegistry . update ( runRecord . runId , { metadata : { managedRuntimeServices : serviceEvidence } } )
515513 runRecord = await runRegistry . read ( runRecord . runId )
516514 const fuzzRunResult = recipeFuzzRunResult ( recipe , executions )
517515 return await finalizeRecoveredRecipeFailure ( {
@@ -553,6 +551,27 @@ async function runRecipe(options: RecipeRunOptions, interruption?: RecipeInterru
553551 }
554552}
555553
554+ export async function runManagedServiceCleanup (
555+ runRegistry : RuntimeRunRegistry ,
556+ runRecord : Awaited < ReturnType < RuntimeRunRegistry [ "read" ] > > ,
557+ serviceEvidence : RuntimeServiceEvidence [ ] ,
558+ preservePrimaryFailure : boolean ,
559+ cleanup : ( ) => Promise < void > ,
560+ ) : Promise < RunResourceCleanupEvidence > {
561+ try {
562+ return await runRecipeCleanup ( runRegistry , runRecord , cleanup )
563+ } catch ( error ) {
564+ if ( preservePrimaryFailure && error instanceof RunResourceCleanupError ) {
565+ return error . evidence
566+ }
567+ throw error
568+ } finally {
569+ await runRegistry . update ( runRecord . runId , {
570+ metadata : { managedRuntimeServices : serviceEvidence } ,
571+ } )
572+ }
573+ }
574+
556575async function recipeArtifactsMountConflictFailure ( options : RecipeRunOptions ) : Promise < RecipeRunOutput | undefined > {
557576 const recipePath = resolve ( options . recipePath )
558577 const recipeDirectory = dirname ( recipePath )
0 commit comments