mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
fix(media-use): clean failed asset reservations (#2627)
* fix(media-use): clean failed asset reservations * test(media-use): pin installer guidance exactly
This commit is contained in:
@@ -12,10 +12,11 @@ import {
|
||||
import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { createServer } from "node:http";
|
||||
import { execFileSync, spawnSync } from "node:child_process";
|
||||
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
||||
import { appendRecord, readManifest } from "./lib/manifest.mjs";
|
||||
import { regenerateIndex } from "./lib/index-gen.mjs";
|
||||
import { getProvider } from "./lib/providers.mjs";
|
||||
import { HEYGEN_NOT_FOUND_MESSAGE } from "./lib/heygen-cli.mjs";
|
||||
import { freezeLocalFile } from "./lib/freeze.mjs";
|
||||
import { cachePut, cacheGet, importFromCache } from "./lib/cache.mjs";
|
||||
import { validateCubeFile } from "./lib/cube-validate.mjs";
|
||||
@@ -78,6 +79,26 @@ function spawnResolve(args, opts = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
function spawnResolveAsync(args, opts = {}) {
|
||||
const { env, ...rest } = opts;
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(process.execPath, [RESOLVE_CLI, ...args], {
|
||||
cwd: REPO_ROOT,
|
||||
env: { ...process.env, DO_NOT_TRACK: "1", ...env },
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
...rest,
|
||||
});
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stderr.setEncoding("utf8");
|
||||
child.stdout.on("data", (chunk) => (stdout += chunk));
|
||||
child.stderr.on("data", (chunk) => (stderr += chunk));
|
||||
child.once("error", reject);
|
||||
child.once("close", (status, signal) => resolve({ status, signal, stdout, stderr }));
|
||||
});
|
||||
}
|
||||
|
||||
function makeFrame(dir, name, color) {
|
||||
const out = join(dir, name);
|
||||
execFileSync(
|
||||
@@ -140,7 +161,8 @@ test("bundled SFX resolve without HeyGen on PATH", () => {
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.equal(parsed.ok, true);
|
||||
assert.equal(parsed.provenance.provider, "bundled.sfx");
|
||||
assert.match(parsed.advisory?.message ?? "", /Install: curl -fsSL/);
|
||||
assert.equal(parsed.advisory?.message, HEYGEN_NOT_FOUND_MESSAGE);
|
||||
assert.equal(parsed.advisory.message.includes("| bash"), false);
|
||||
assert.ok(existsSync(join(tmp, parsed.path)));
|
||||
cleanup();
|
||||
});
|
||||
@@ -224,7 +246,10 @@ test("human bundled fallback prints the install hint once", () => {
|
||||
env: { HOME: tmp, PATH: tmp },
|
||||
});
|
||||
assert.equal(result.status, 0, result.stderr);
|
||||
assert.equal(result.stderr.match(/Install: curl -fsSL/g)?.length, 1);
|
||||
assert.equal(
|
||||
result.stderr.match(/Install the CLI from https:\/\/developers\.heygen\.com\/cli/g)?.length,
|
||||
1,
|
||||
);
|
||||
assert.match(result.stdout, /resolved sfx_001/);
|
||||
cleanup();
|
||||
});
|
||||
@@ -409,6 +434,61 @@ test("freezeLocalFile creates parent dirs and copies", () => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test("failed remote freeze removes its reserved placeholder", async () => {
|
||||
setup();
|
||||
const server = createServer((_req, res) => {
|
||||
res.writeHead(503);
|
||||
res.end("unavailable");
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
const port = server.address().port;
|
||||
const binDir = writeFakeHeygen(
|
||||
`printf '%s\\n' '{"data":[{"id":"asset.jpg","url":"http://127.0.0.1:${port}/asset.jpg"}]}'`,
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await spawnResolveAsync(
|
||||
[
|
||||
"--type",
|
||||
"image",
|
||||
"--intent",
|
||||
"download failure",
|
||||
"--provider",
|
||||
"heygen",
|
||||
"--project",
|
||||
tmp,
|
||||
"--json",
|
||||
],
|
||||
{ env: { HOME: tmp, PATH: binDir } },
|
||||
);
|
||||
|
||||
assert.equal(result.status, 1, result.stderr);
|
||||
assert.deepStrictEqual(readdirSync(join(tmp, ".media/images")), []);
|
||||
assert.deepStrictEqual(readManifest(tmp), []);
|
||||
} finally {
|
||||
await new Promise((resolve) => server.close(resolve));
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
test("failed URL ingest removes its reserved placeholder", () => {
|
||||
setup();
|
||||
const result = spawnResolve([
|
||||
"--from",
|
||||
"https://example.invalid/unavailable.jpg",
|
||||
"--type",
|
||||
"image",
|
||||
"--project",
|
||||
tmp,
|
||||
"--json",
|
||||
]);
|
||||
|
||||
assert.equal(result.status, 1, result.stderr);
|
||||
assert.deepStrictEqual(readdirSync(join(tmp, ".media/images")), []);
|
||||
assert.deepStrictEqual(readManifest(tmp), []);
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// --- adopt existing assets ---
|
||||
|
||||
test("--adopt registers existing assets/ files", () => {
|
||||
|
||||
Reference in New Issue
Block a user