mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
fix(cli): don't override exit code after artifact validated
The render command's post-artifact-validated cleanup (telemetry flush,
feedback prompt, worker/browser teardown, stray promise rejections) can
throw AFTER the producer has committed a valid MP4 to disk. Field signal
ts=1784169760, ts=1784171150, ts=1784172467 (all win32/x64, CLI 0.7.58,
ffmpeg=no, 1080x1920): ffprobe + visual QA confirmed the outputs are
valid, but the CLI exited 1 after the terminal "artifact validated" log
with no final error message.
Introduce a `renderSucceeded` sentinel that flips after `executeRenderJob`
(or the Docker child render) resolves cleanly. From that point on:
- Post-render steps in the render command (trackRenderMetrics,
printRenderComplete, warnIfWebmAlphaDropped, maybePromptRenderFeedback)
run through `runPostRenderStep`/`runPostRenderStepAsync` guards that
swallow throws, log a compact warning to stderr, and sanitize a stray
`process.exitCode` back to 0.
- The CLI's top-level `uncaughtException` handler logs the throw for
diagnosis but exits 0 instead of 1 when the render already succeeded.
- The CLI's `unhandledRejection` handler stops flipping `commandFailed`
(which drove the success:false telemetry field) when the render
already succeeded.
Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
— Via
This commit is contained in:
@@ -81,6 +81,11 @@ import { runEnvironmentChecks } from "../browser/preflight.js";
|
||||
import { detectH264EncoderMode } from "../browser/ffmpeg.js";
|
||||
import { chromeLaunchRemediation } from "../browser/linuxDeps.js";
|
||||
import { killOrphanedProcesses } from "../utils/orphanCleanup.js";
|
||||
import {
|
||||
markRenderSucceeded,
|
||||
runPostRenderStep,
|
||||
runPostRenderStepAsync,
|
||||
} from "../utils/render-success-state.js";
|
||||
import type { ProducerLogger, RenderJob } from "@hyperframes/producer";
|
||||
import {
|
||||
MAX_VP9_CPU_USED,
|
||||
@@ -1413,23 +1418,35 @@ async function renderDocker(
|
||||
|
||||
const elapsed = Date.now() - startTime;
|
||||
|
||||
// Docker child exited 0 → the containerized producer already validated
|
||||
// AND committed the artifact. Mirror renderLocal's post-success guarantee
|
||||
// so any late throw here (telemetry flush, feedback prompt) cannot flip
|
||||
// the exit code.
|
||||
markRenderSucceeded();
|
||||
|
||||
// Track metrics (no job object available from Docker — use a minimal stub)
|
||||
trackRenderComplete({
|
||||
durationMs: elapsed,
|
||||
fps: fpsToNumber(options.fps),
|
||||
quality: options.quality,
|
||||
workers: options.workers,
|
||||
docker: true,
|
||||
gpu: options.gpu,
|
||||
authoringSkill: options.authoringSkill,
|
||||
...getMemorySnapshot(),
|
||||
});
|
||||
runPostRenderStep("trackRenderComplete", () =>
|
||||
trackRenderComplete({
|
||||
durationMs: elapsed,
|
||||
fps: fpsToNumber(options.fps),
|
||||
quality: options.quality,
|
||||
workers: options.workers,
|
||||
docker: true,
|
||||
gpu: options.gpu,
|
||||
authoringSkill: options.authoringSkill,
|
||||
...getMemorySnapshot(),
|
||||
}),
|
||||
);
|
||||
|
||||
// ponytail: Docker runs the producer in a child process, so no perfSummary is
|
||||
// threaded back here; the summary shows render time only (never a wrong video
|
||||
// length). Probe the output with ffprobe if a duration figure is wanted here.
|
||||
printRenderComplete(outputPath, elapsed, options.quiet);
|
||||
warnIfWebmAlphaDropped(outputPath, options.format, options.quiet);
|
||||
runPostRenderStep("printRenderComplete", () =>
|
||||
printRenderComplete(outputPath, elapsed, options.quiet),
|
||||
);
|
||||
runPostRenderStep("warnIfWebmAlphaDropped", () =>
|
||||
warnIfWebmAlphaDropped(outputPath, options.format, options.quiet),
|
||||
);
|
||||
if (options.exitAfterComplete) scheduleRenderProcessExit();
|
||||
return { renderTimeMs: elapsed };
|
||||
}
|
||||
@@ -1559,6 +1576,13 @@ export async function renderLocal(
|
||||
);
|
||||
}
|
||||
|
||||
// Render resolved without throwing → producer's `artifact validated`
|
||||
// checkpoint fired AND the artifact was committed to disk. From this
|
||||
// point on, ANY thrown teardown error must not be allowed to override
|
||||
// the exit code. Field signal ts=1784169760 / ts=1784171150 / ts=1784172467
|
||||
// (win32/x64, CLI 0.7.58): valid MP4 on disk, exited 1 with no error print.
|
||||
markRenderSucceeded();
|
||||
|
||||
maybeConsumeDeParallelRouterTrial(deParallelRouterTrialArmed, job, options.quiet);
|
||||
const elapsed = Date.now() - startTime;
|
||||
if (job.outcome === "completed_with_warnings") {
|
||||
@@ -1566,20 +1590,26 @@ export async function renderLocal(
|
||||
console.warn(c.warn(` [${warning.code}] ${warning.message}`));
|
||||
}
|
||||
}
|
||||
trackRenderMetrics(job, elapsed, options, false);
|
||||
printRenderComplete(
|
||||
outputPath,
|
||||
elapsed,
|
||||
options.quiet,
|
||||
job.perfSummary?.compositionDurationSeconds,
|
||||
job.perfSummary?.totalFrames,
|
||||
runPostRenderStep("trackRenderMetrics", () => trackRenderMetrics(job, elapsed, options, false));
|
||||
runPostRenderStep("printRenderComplete", () =>
|
||||
printRenderComplete(
|
||||
outputPath,
|
||||
elapsed,
|
||||
options.quiet,
|
||||
job.perfSummary?.compositionDurationSeconds,
|
||||
job.perfSummary?.totalFrames,
|
||||
),
|
||||
);
|
||||
runPostRenderStep("warnIfWebmAlphaDropped", () =>
|
||||
warnIfWebmAlphaDropped(outputPath, options.format, options.quiet),
|
||||
);
|
||||
warnIfWebmAlphaDropped(outputPath, options.format, options.quiet);
|
||||
if (!options.skipFeedback) {
|
||||
await maybePromptRenderFeedback({
|
||||
renderDurationMs: elapsed,
|
||||
quiet: options.quiet,
|
||||
});
|
||||
await runPostRenderStepAsync("maybePromptRenderFeedback", () =>
|
||||
maybePromptRenderFeedback({
|
||||
renderDurationMs: elapsed,
|
||||
quiet: options.quiet,
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (options.exitAfterComplete) scheduleRenderProcessExit();
|
||||
const durationMs = job.perfSummary
|
||||
|
||||
Reference in New Issue
Block a user