@@ -6,7 +6,12 @@ import type { Actor, ActorCollectionCreateOptions, ActorDefaultRunOptions } from
66import open from 'open' ;
77
88import { fetchManifest } from '@apify/actor-templates' ;
9- import { ACTOR_JOB_STATUSES , ACTOR_SOURCE_TYPES , MAX_MULTIFILE_BYTES } from '@apify/consts' ;
9+ import {
10+ ACTOR_JOB_STATUSES ,
11+ ACTOR_JOB_TERMINAL_STATUSES ,
12+ ACTOR_SOURCE_TYPES ,
13+ MAX_MULTIFILE_BYTES ,
14+ } from '@apify/consts' ;
1015import { createHmacSignature } from '@apify/utilities' ;
1116
1217import { ApifyCommand } from '../../lib/command-framework/apify-command.js' ;
@@ -358,18 +363,16 @@ Skipping push. Use --force to override.`,
358363 waitForFinish : 2 , // NOTE: We need to wait some time to Apify open stream and we can create connection
359364 } ) ;
360365
361- try {
362- // While the log is streaming, forward interrupt signals to a
363- // platform-side abort so the build doesn't keep running after the
364- // user gives up waiting (Ctrl+C, SIGTERM from a parent process,
365- // SIGHUP from a closing terminal). The `using` binding guarantees
366- // the listener is removed before we poll for final status.
367- using _signalHandler = useAbortJobOnSignal ( {
368- apifyClient,
369- kind : 'build' ,
370- jobId : build . id ,
371- } ) ;
366+ // Forward interrupt signals (Ctrl+C, SIGTERM, SIGHUP) to a platform-side
367+ // abort for the lifetime of log streaming AND status polling, so the
368+ // build doesn't keep running after the user gives up waiting.
369+ using _signalHandler = useAbortJobOnSignal ( {
370+ apifyClient,
371+ kind : 'build' ,
372+ jobId : build . id ,
373+ } ) ;
372374
375+ try {
373376 await outputJobLog ( { job : build , timeoutMillis : waitForFinishMillis , apifyClient } ) ;
374377 } catch ( err ) {
375378 warning ( { message : 'Can not get log:' } ) ;
@@ -378,6 +381,17 @@ Skipping push. Use --force to override.`,
378381
379382 build = ( await apifyClient . build ( build . id ) . get ( ) ) ! ;
380383
384+ // `outputJobLog` can return before the build is actually terminal (stream
385+ // ended early, timeout hit). Poll so the status branches below see the
386+ // real outcome.
387+ if ( waitForFinishMillis !== undefined ) {
388+ const deadline = Date . now ( ) + waitForFinishMillis ;
389+ while ( ! ACTOR_JOB_TERMINAL_STATUSES . includes ( build . status as never ) && Date . now ( ) < deadline ) {
390+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
391+ build = ( await apifyClient . build ( build . id ) . get ( ) ) ! ;
392+ }
393+ }
394+
381395 if ( this . flags . json ) {
382396 printJsonToStdout ( build ) ;
383397 return ;
@@ -402,9 +416,11 @@ Skipping push. Use --force to override.`,
402416 // @ts -expect-error FIX THESE TYPES 😢
403417 } else if ( build . status === ACTOR_JOB_STATUSES . READY ) {
404418 warning ( { message : 'Build is waiting for allocation.' } ) ;
419+ process . exitCode = CommandExitCodes . BuildTimedOut ;
405420 // @ts -expect-error FIX THESE TYPES 😢
406421 } else if ( build . status === ACTOR_JOB_STATUSES . RUNNING ) {
407422 warning ( { message : 'Build is still running.' } ) ;
423+ process . exitCode = CommandExitCodes . BuildTimedOut ;
408424 // @ts -expect-error FIX THESE TYPES 😢
409425 } else if ( build . status === ACTOR_JOB_STATUSES . ABORTED || build . status === ACTOR_JOB_STATUSES . ABORTING ) {
410426 warning ( { message : 'Build was aborted!' } ) ;
0 commit comments