Skip to content

Commit fa017eb

Browse files
committed
refactor plus fix tests
1 parent 5ae1076 commit fa017eb

2 files changed

Lines changed: 69 additions & 36 deletions

File tree

src/commands/actors/push.ts

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,16 @@ Skipping push. Use --force to override.`,
362362
info({ message: `${isEnabled ? 'Enabled' : 'Disabled'} standby mode for Actor ${actor.name}.` });
363363
}
364364

365-
// Build Actor on Apify and wait for build to finish
365+
// Build Actor on Apify and wait for build to finish.
366+
// Cap the initial wait by the user's `-w` budget so `-w 0` actually
367+
// returns immediately instead of always waiting 2s; otherwise short
368+
// builds can complete before our polling loop ever starts.
366369
run({ message: `Building Actor ${actor.name}` });
370+
const initialWaitForFinish =
371+
waitForFinishMillis === undefined ? 2 : Math.min(2, Math.floor(waitForFinishMillis / 1000));
367372
let build = await actorClient.build(version, {
368373
useCache: true,
369-
waitForFinish: 2, // NOTE: We need to wait some time to Apify open stream and we can create connection
374+
waitForFinish: initialWaitForFinish,
370375
});
371376

372377
// Forward interrupt signals to a platform-side abort so the build
@@ -445,7 +450,10 @@ Skipping push. Use --force to override.`,
445450
// build succeeds. Wait for the tag to point at this build so callers
446451
// that immediately run against the tag don't race the previous build.
447452
if (!pollErrorAbort && buildTag && build.status === ACTOR_JOB_STATUSES.SUCCEEDED) {
448-
const tagDeadline = Math.min(Date.now() + 30_000, waitDeadline ?? Infinity);
453+
// Tag application is a post-success platform step; don't cap it by
454+
// the build's wait deadline, or a build that succeeds on the last
455+
// poll leaves no time to observe the tag and we always warn.
456+
const tagDeadline = Date.now() + 30_000;
449457
let tagApplied = false;
450458
let tagPollWarned = false;
451459
while (Date.now() < tagDeadline) {
@@ -472,6 +480,55 @@ Skipping push. Use --force to override.`,
472480
}
473481
}
474482

483+
const status = build.status as string;
484+
interface Outcome {
485+
exitCode?: CommandExitCodes;
486+
report: () => void;
487+
}
488+
let outcome: Outcome;
489+
if (pollErrorAbort) {
490+
outcome = {
491+
exitCode: CommandExitCodes.BuildFailed,
492+
report: () =>
493+
error({
494+
message: `Gave up waiting for build after ${MAX_CONSECUTIVE_POLL_ERRORS} consecutive failures fetching build status; the build may still be running on the platform.`,
495+
}),
496+
};
497+
} else if (status === ACTOR_JOB_STATUSES.SUCCEEDED) {
498+
outcome = { report: () => success({ message: 'Actor was deployed to Apify cloud and built there.' }) };
499+
} else if (status === ACTOR_JOB_STATUSES.READY) {
500+
outcome = {
501+
exitCode: this.flags.failOnTimeout ? CommandExitCodes.BuildTimedOut : undefined,
502+
report: () => warning({ message: 'Timed out waiting for build; it is still waiting for allocation.' }),
503+
};
504+
} else if (status === ACTOR_JOB_STATUSES.RUNNING) {
505+
outcome = {
506+
exitCode: this.flags.failOnTimeout ? CommandExitCodes.BuildTimedOut : undefined,
507+
report: () => warning({ message: 'Timed out waiting for build; it is still running.' }),
508+
};
509+
} else if (status === ACTOR_JOB_STATUSES.ABORTED || status === ACTOR_JOB_STATUSES.ABORTING) {
510+
outcome = {
511+
exitCode: CommandExitCodes.BuildAborted,
512+
report: () => warning({ message: 'Build was aborted!' }),
513+
};
514+
} else if (status === ACTOR_JOB_STATUSES.TIMED_OUT || status === ACTOR_JOB_STATUSES.TIMING_OUT) {
515+
outcome = {
516+
exitCode: CommandExitCodes.BuildTimedOut,
517+
report: () => warning({ message: 'Build timed out!' }),
518+
};
519+
} else {
520+
outcome = {
521+
exitCode: CommandExitCodes.BuildFailed,
522+
report: () => error({ message: 'Build failed!' }),
523+
};
524+
}
525+
526+
// Set exit code before the `--json` early-return so JSON callers
527+
// can still rely on process exit status for non-terminal end states.
528+
if (outcome.exitCode !== undefined) {
529+
process.exitCode = outcome.exitCode;
530+
}
531+
475532
if (this.flags.json) {
476533
printJsonToStdout(build);
477534
return;
@@ -491,36 +548,6 @@ Skipping push. Use --force to override.`,
491548
await open(`https://console.apify.com${redirectUrlPart}/actors/${build.actId}`);
492549
}
493550

494-
if (pollErrorAbort) {
495-
error({
496-
message: `Gave up waiting for build after ${MAX_CONSECUTIVE_POLL_ERRORS} consecutive failures fetching build status; the build may still be running on the platform.`,
497-
});
498-
process.exitCode = CommandExitCodes.BuildFailed;
499-
} else if (build.status === ACTOR_JOB_STATUSES.SUCCEEDED) {
500-
success({ message: 'Actor was deployed to Apify cloud and built there.' });
501-
// @ts-expect-error FIX THESE TYPES 😢
502-
} else if (build.status === ACTOR_JOB_STATUSES.READY) {
503-
warning({ message: 'Timed out waiting for build; it is still waiting for allocation.' });
504-
if (this.flags.failOnTimeout) {
505-
process.exitCode = CommandExitCodes.BuildTimedOut;
506-
}
507-
// @ts-expect-error FIX THESE TYPES 😢
508-
} else if (build.status === ACTOR_JOB_STATUSES.RUNNING) {
509-
warning({ message: 'Timed out waiting for build; it is still running.' });
510-
if (this.flags.failOnTimeout) {
511-
process.exitCode = CommandExitCodes.BuildTimedOut;
512-
}
513-
// @ts-expect-error FIX THESE TYPES 😢
514-
} else if (build.status === ACTOR_JOB_STATUSES.ABORTED || build.status === ACTOR_JOB_STATUSES.ABORTING) {
515-
warning({ message: 'Build was aborted!' });
516-
process.exitCode = CommandExitCodes.BuildAborted;
517-
// @ts-expect-error FIX THESE TYPES 😢
518-
} else if (build.status === ACTOR_JOB_STATUSES.TIMED_OUT || build.status === ACTOR_JOB_STATUSES.TIMING_OUT) {
519-
warning({ message: 'Build timed out!' });
520-
process.exitCode = CommandExitCodes.BuildTimedOut;
521-
} else {
522-
error({ message: 'Build failed!' });
523-
process.exitCode = CommandExitCodes.BuildFailed;
524-
}
551+
outcome.report();
525552
}
526553
}

test/api/commands/push.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,10 @@ describe('[api] apify push', () => {
490490
it(
491491
'should exit with BuildTimedOut when --wait-for-finish elapses before the build finishes',
492492
async () => {
493-
const testActor = await testUserClient.actors().create(TEST_ACTOR);
493+
const testActor = await testUserClient.actors().create({
494+
...TEST_ACTOR,
495+
name: `${TEST_ACTOR.name}-timeout-fail`,
496+
});
494497
actorsForCleanup.add(testActor.id);
495498
const previousExitCode = process.exitCode;
496499
process.exitCode = undefined;
@@ -514,7 +517,10 @@ describe('[api] apify push', () => {
514517
it(
515518
'should not set exit code when --fail-on-timeout is disabled and wait elapses',
516519
async () => {
517-
const testActor = await testUserClient.actors().create(TEST_ACTOR);
520+
const testActor = await testUserClient.actors().create({
521+
...TEST_ACTOR,
522+
name: `${TEST_ACTOR.name}-timeout-nofail`,
523+
});
518524
actorsForCleanup.add(testActor.id);
519525
const previousExitCode = process.exitCode;
520526
process.exitCode = undefined;

0 commit comments

Comments
 (0)