diff --git a/runner/orchestration/executors/executor.ts b/runner/orchestration/executors/executor.ts index f7d6ef8..7eaaa2d 100644 --- a/runner/orchestration/executors/executor.ts +++ b/runner/orchestration/executors/executor.ts @@ -72,7 +72,7 @@ export const executorSchema = z.object({ ) .describe('Call this function while the server is running'), ]), - z.promise(z.custom()), + z.promise(z.union([z.custom(), z.null()])), ) .nullable(), executeProjectTests: z.function( diff --git a/runner/orchestration/executors/local-executor-config.ts b/runner/orchestration/executors/local-executor-config.ts index ae6df7c..195006e 100644 --- a/runner/orchestration/executors/local-executor-config.ts +++ b/runner/orchestration/executors/local-executor-config.ts @@ -21,9 +21,11 @@ export const localExecutorConfigSchema = z.strictObject({ buildCommand: z.string().optional(), /** * Command to run when starting a development server inside the app. - * Defaults to ` run start --port 0`. + * + * When `undefined`, defaults to ` run start --port 0`. + * When `null`, the app has no server and no runtime testing will occur. */ - serveCommand: z.string().optional(), + serveCommand: z.string().optional().nullable(), /** * Optional command for executing project tests. */ diff --git a/runner/orchestration/executors/local-executor.ts b/runner/orchestration/executors/local-executor.ts index 92c926e..d64f018 100644 --- a/runner/orchestration/executors/local-executor.ts +++ b/runner/orchestration/executors/local-executor.ts @@ -27,6 +27,7 @@ import {callWithTimeout} from '../../utils/timeout.js'; import {executeCommand} from '../../utils/exec.js'; import {cleanupBuildMessage} from '../../workers/builder/worker.js'; import {combineAbortSignals} from '../../utils/abort-signal.js'; +import {ServeTestingResult} from '../../workers/serve-testing/worker-types.js'; let uniqueIDs = 0; @@ -172,13 +173,18 @@ export class LocalExecutor implements Executor { } satisfies TestExecutionResult; } - async serveWebApplication( + async serveWebApplication( _id: EvalID, appDirectoryPath: string, rootPromptDef: RootPromptDefinition, progress: ProgressLogger, - logicWhileServing: (serveUrl: string) => Promise, - ): Promise { + logicWhileServing: (serveUrl: string) => Promise, + ): Promise { + // Serve testing is explicitly disabled. + if (this.config.serveCommand === null) { + return null; + } + return await serveApp( this.getServeCommand(), rootPromptDef, @@ -207,7 +213,7 @@ export class LocalExecutor implements Executor { } getServeCommand(): string { - if (this.config.serveCommand !== undefined) { + if (this.config.serveCommand != null) { return this.config.serveCommand; } diff --git a/runner/orchestration/serve-testing-worker.ts b/runner/orchestration/serve-testing-worker.ts index a076969..0e3b935 100644 --- a/runner/orchestration/serve-testing-worker.ts +++ b/runner/orchestration/serve-testing-worker.ts @@ -87,6 +87,12 @@ export async function serveAndTestApp( }, ); + // An executor might define `serveWebApplication` but conditionally decide + // that no web application can be started/served. + if (result === null) { + return null; + } + if (result.errorMessage === undefined) { progress.log(rootPromptDef, 'success', 'Validation of running app is successful'); } else {