@@ -17,6 +17,7 @@ import { z } from 'zod';
17
17
import { editToolParameters } from './editTool' ;
18
18
import { getAbsolutePath } from '~/lib/stores/files' ;
19
19
import { streamOutput } from '~/utils/process' ;
20
+ import { outputLabels , type OutputLabels } from './deployToolOutputLabels' ;
20
21
21
22
const logger = createScopedLogger ( 'ActionRunner' ) ;
22
23
@@ -372,25 +373,88 @@ export class ActionRunner {
372
373
case 'deploy' : {
373
374
const container = await this . #webcontainer;
374
375
await waitForContainerBootState ( ContainerBootState . READY ) ;
375
- const convexProc = await container . spawn ( 'sh' , [
376
- '-c' ,
377
- 'eslint . && convex dev --once && tsc --noEmit -p tsconfig.app.json' ,
378
- ] ) ;
379
- action . abortSignal . addEventListener ( 'abort' , ( ) => {
380
- convexProc . kill ( ) ;
381
- } ) ;
382
-
383
- const { output, exitCode } = await streamOutput ( convexProc , {
384
- onOutput : ( output ) => {
385
- this . terminalOutput . set ( output ) ;
386
- } ,
387
- debounceMs : 50 ,
388
- } ) ;
389
- const cleanedOutput = cleanConvexOutput ( output ) ;
390
- if ( exitCode !== 0 ) {
391
- throw new Error ( `Convex failed with exit code ${ exitCode } : ${ cleanedOutput } ` ) ;
376
+
377
+ // TODO need to get the output into here
378
+ result = '' ;
379
+
380
+ /** Return a promise of output on success, throws an error containing output on failure. */
381
+ const run = async ( command : string , args : string [ ] , errorPrefix : OutputLabels ) : Promise < string > => {
382
+ const t0 = performance . now ( ) ;
383
+ const proc = await container . spawn ( command , args ) ;
384
+ let abortListener : ( ) => void = ( ) => {
385
+ proc . kill ( ) ;
386
+ } ;
387
+ action . abortSignal . addEventListener ( 'abort' , abortListener ) ;
388
+ const { output : output , exitCode : exitCode } = await streamOutput ( proc , {
389
+ onOutput : ( output ) => {
390
+ this . terminalOutput . set ( output ) ;
391
+ } ,
392
+ debounceMs : 50 ,
393
+ } ) ;
394
+
395
+ const cleanedOutput = cleanConvexOutput ( output ) ;
396
+ const time = performance . now ( ) - t0 ;
397
+ logger . trace ( 'finished' , errorPrefix , 'in' , Math . round ( time ) ) ;
398
+ if ( exitCode !== 0 ) {
399
+ throw new Error ( `[${ errorPrefix } ] Failed with exit code ${ exitCode } : ${ cleanedOutput } ` ) ;
400
+ }
401
+ action . abortSignal . removeEventListener ( 'abort' , abortListener ) ;
402
+ return cleanedOutput + '\n\n' ;
403
+ } ;
404
+
405
+ /*
406
+ result += await run(
407
+ 'sh',
408
+ [
409
+ '-c',
410
+ 'convex codegen' +
411
+ ' && tsc --noEmit -p tsconfig.app.json' +
412
+ ' && eslint convex' +
413
+ ' && convex dev --once --typecheck=disable',
414
+ ],
415
+ 'do everything' as any,
416
+ );
417
+ */
418
+
419
+ const t0 = performance . now ( ) ;
420
+ result += await run ( 'convex' , [ 'codegen' , '--typecheck=disable' ] , outputLabels . convexTypecheck ) ;
421
+
422
+ // what if we ran tsc, eslint, and deploy all at the same time?
423
+ const tscP = await run ( 'tsc' , [ '--noEmit' , '-p' , 'tsconfig.app.json' ] , outputLabels . frontendTypecheck ) ;
424
+
425
+ const eslintP = ( async function maybeRunEslint ( ) : Promise < string > {
426
+ // Only run eslint if the file we expect is present and contains '@convex-dev/eslint-plugin'
427
+ // Projects created with older versions of Chef have this file but it does not container
428
+ // @convex -dev/eslint-plugin.
429
+ let contents = '' ;
430
+ try {
431
+ contents = await container . fs . readFile ( 'eslint.config.js' , 'utf-8' ) ;
432
+ } catch ( e : any ) {
433
+ if ( ! e . message . includes ( 'ENOENT: no such file or directory' ) ) {
434
+ throw e ;
435
+ }
436
+ }
437
+ if ( contents . includes ( '@convex-dev/eslint-plugin' ) ) {
438
+ await run ( 'eslint' , [ 'convex' ] , outputLabels . convexLint ) ;
439
+ }
440
+ return '' ;
441
+ } ) ( ) ;
442
+
443
+ const deployP = run ( 'convex' , [ 'dev' , '--once' , '--typecheck=disable' ] , outputLabels . convexDeploy ) ;
444
+
445
+ const [ tscResult , eslintResult , deployResult ] = await Promise . allSettled ( [ tscP , eslintP , deployP ] ) ;
446
+ console . log ( 'parallel stuff done in' , performance . now ( ) - t0 ) ;
447
+ // TODO abort later ones?
448
+ // Throw the first failure in this order
449
+ for ( const pResult of [ tscResult , eslintResult , deployResult ] ) {
450
+ if ( pResult . status === 'fulfilled' ) {
451
+ result += pResult . value ;
452
+ } else {
453
+ throw pResult . reason ;
454
+ }
392
455
}
393
- result = cleanedOutput ;
456
+
457
+ result += await run ( 'convex' , [ 'dev' , '--once' , '--typecheck=disable' ] , outputLabels . convexDeploy ) ;
394
458
395
459
// Start the default preview if it’s not already running
396
460
if ( ! workbenchStore . isDefaultPreviewRunning ( ) ) {
0 commit comments