@gfxlabs/third-eye-cli 3.25.0 → 3.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.mjs +142 -1
- package/dist/bin.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bin.mjs
CHANGED
|
@@ -27,6 +27,16 @@ import { RPCLink } from "@orpc/client/fetch";
|
|
|
27
27
|
import { execa } from "execa";
|
|
28
28
|
import { XMLParser } from "fast-xml-parser";
|
|
29
29
|
//#region \0rolldown/runtime.js
|
|
30
|
+
var __defProp = Object.defineProperty;
|
|
31
|
+
var __exportAll = (all, no_symbols) => {
|
|
32
|
+
let target = {};
|
|
33
|
+
for (var name in all) __defProp(target, name, {
|
|
34
|
+
get: all[name],
|
|
35
|
+
enumerable: true
|
|
36
|
+
});
|
|
37
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
38
|
+
return target;
|
|
39
|
+
};
|
|
30
40
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
31
41
|
//#endregion
|
|
32
42
|
//#region src/log.ts
|
|
@@ -1231,6 +1241,22 @@ const getPagesFromExternalLoader = async () => {
|
|
|
1231
1241
|
};
|
|
1232
1242
|
//#endregion
|
|
1233
1243
|
//#region src/shots/shots.ts
|
|
1244
|
+
/**
|
|
1245
|
+
* Wait for Storybook play functions to complete before screenshotting.
|
|
1246
|
+
* Checks __STORYBOOK_PREVIEW__.currentRender.phase and data-play-fn-done attribute.
|
|
1247
|
+
*/
|
|
1248
|
+
const waitForPlayFunction = async (page, shotItem, logger) => {
|
|
1249
|
+
if (shotItem.shotMode !== "storybook") return;
|
|
1250
|
+
try {
|
|
1251
|
+
await page.waitForFunction(() => {
|
|
1252
|
+
if (window.__STORYBOOK_PREVIEW__?.currentRender?.phase === "playing") return false;
|
|
1253
|
+
if (document.getElementById("storybook-root")?.dataset.playFnDone === "false") return false;
|
|
1254
|
+
return true;
|
|
1255
|
+
}, { timeout: config.timeouts?.loadState ?? 3e4 });
|
|
1256
|
+
} catch {
|
|
1257
|
+
logger.process("info", "general", `Play function wait timed out for ${shotItem.id} — proceeding with screenshot`);
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1234
1260
|
const takeScreenShot = async ({ browser, shotItem, logger }) => {
|
|
1235
1261
|
const context = await browser.newContext(shotItem.browserConfig);
|
|
1236
1262
|
const page = await context.newPage();
|
|
@@ -1275,6 +1301,7 @@ const takeScreenShot = async ({ browser, shotItem, logger }) => {
|
|
|
1275
1301
|
} catch (error) {
|
|
1276
1302
|
logger.process("error", "timeout", `Timeout while waiting for all network requests: ${shotItem.url}`, error);
|
|
1277
1303
|
}
|
|
1304
|
+
await waitForPlayFunction(page, shotItem, logger);
|
|
1278
1305
|
if (config.beforeScreenshot) await config.beforeScreenshot(page, {
|
|
1279
1306
|
shotMode: shotItem.shotMode,
|
|
1280
1307
|
id: shotItem.id,
|
|
@@ -1773,6 +1800,21 @@ const createTypedClient = (options) => {
|
|
|
1773
1800
|
};
|
|
1774
1801
|
//#endregion
|
|
1775
1802
|
//#region src/api.ts
|
|
1803
|
+
var api_exports = /* @__PURE__ */ __exportAll({
|
|
1804
|
+
getAffectedStories: () => getAffectedStories,
|
|
1805
|
+
getApiToken: () => getApiToken,
|
|
1806
|
+
getGitInfoFromAPI: () => getGitInfoFromAPI,
|
|
1807
|
+
prepareUpload: () => prepareUpload,
|
|
1808
|
+
processShots: () => processShots,
|
|
1809
|
+
sendCheckCacheToAPI: () => sendCheckCacheToAPI,
|
|
1810
|
+
sendFinalizeToAPI: () => sendFinalizeToAPI,
|
|
1811
|
+
sendFindSquashMergeParentsToAPI: () => sendFindSquashMergeParentsToAPI,
|
|
1812
|
+
sendHasBuildsWithCommitsToAPI: () => sendHasBuildsWithCommitsToAPI,
|
|
1813
|
+
sendInitToAPI: () => sendInitToAPI,
|
|
1814
|
+
sendRecordLogsToAPI: () => sendRecordLogsToAPI,
|
|
1815
|
+
uploadShot: () => uploadShot,
|
|
1816
|
+
uploadStorybookArchive: () => uploadStorybookArchive
|
|
1817
|
+
});
|
|
1776
1818
|
const createClient = (platformUrl, apiKey, apiToken) => createTypedClient({
|
|
1777
1819
|
url: platformUrl,
|
|
1778
1820
|
apiKey,
|
|
@@ -2253,6 +2295,16 @@ const platformRunner = async (config, apiToken) => {
|
|
|
2253
2295
|
initialCommitsWithBuilds.push(lastCommit);
|
|
2254
2296
|
} else log.process("info", "general", `📌 Last build on branch ${lastCommit.slice(0, 7)} not in local git (rebase?), skipping`);
|
|
2255
2297
|
}
|
|
2298
|
+
if (config.baseBranch) {
|
|
2299
|
+
const mergeBase = getMergeBaseInfo(config.baseBranch);
|
|
2300
|
+
if (mergeBase) {
|
|
2301
|
+
const mbCommitsWithBuilds = await sendHasBuildsWithCommitsToAPI(config, apiToken, mergeBase.mergeBaseAncestors);
|
|
2302
|
+
for (const c of mbCommitsWithBuilds) if (!initialCommitsWithBuilds.includes(c)) {
|
|
2303
|
+
log.process("info", "general", `📌 Seeding with base branch build: ${c.slice(0, 7)}`);
|
|
2304
|
+
initialCommitsWithBuilds.push(c);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2256
2308
|
log.process("info", "general", "🔍 Resolving ancestor builds from git history...");
|
|
2257
2309
|
const { parentCommits, visitedCommitsWithoutBuilds } = await getParentCommits((commits) => sendHasBuildsWithCommitsToAPI(config, apiToken, commits), {
|
|
2258
2310
|
firstCommittedAtSeconds: gitInfo.firstBuildCreatedAt ?? void 0,
|
|
@@ -2372,6 +2424,90 @@ const platformRunner = async (config, apiToken) => {
|
|
|
2372
2424
|
process.exit(1);
|
|
2373
2425
|
}
|
|
2374
2426
|
};
|
|
2427
|
+
const patchBuildRunner = async (patchBuildArg, config, apiToken) => {
|
|
2428
|
+
const { execSync } = await import("node:child_process");
|
|
2429
|
+
const parts = patchBuildArg.split("...");
|
|
2430
|
+
if (parts.length !== 2) {
|
|
2431
|
+
log.process("error", "general", `Invalid --patch-build format. Expected: head...base (e.g. feature...main)`);
|
|
2432
|
+
process.exit(1);
|
|
2433
|
+
}
|
|
2434
|
+
const [headRef, baseRef] = parts;
|
|
2435
|
+
log.process("info", "general", `🩹 Patch build: computing merge base between ${headRef} and ${baseRef}...`);
|
|
2436
|
+
let mergeBaseCommit;
|
|
2437
|
+
try {
|
|
2438
|
+
mergeBaseCommit = execSync(`git merge-base ${headRef} ${baseRef}`, { encoding: "utf-8" }).trim();
|
|
2439
|
+
} catch {
|
|
2440
|
+
log.process("error", "general", `Failed to compute merge base between ${headRef} and ${baseRef}`);
|
|
2441
|
+
process.exit(1);
|
|
2442
|
+
}
|
|
2443
|
+
log.process("info", "general", `📍 Merge base commit: ${mergeBaseCommit.slice(0, 7)}`);
|
|
2444
|
+
const { sendHasBuildsWithCommitsToAPI: checkCommits } = await Promise.resolve().then(() => api_exports);
|
|
2445
|
+
if ((await checkCommits(config, apiToken, [mergeBaseCommit])).length > 0) {
|
|
2446
|
+
log.process("info", "general", `✅ Build already exists for merge base ${mergeBaseCommit.slice(0, 7)}, no patch build needed.`);
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
const originalRef = execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
2450
|
+
const originalBranch = execSync("git rev-parse --abbrev-ref HEAD", { encoding: "utf-8" }).trim();
|
|
2451
|
+
log.process("info", "general", `📦 Saving current state (${originalBranch} @ ${originalRef.slice(0, 7)})...`);
|
|
2452
|
+
let hasStash = false;
|
|
2453
|
+
try {
|
|
2454
|
+
hasStash = !execSync("git stash", { encoding: "utf-8" }).trim().includes("No local changes");
|
|
2455
|
+
} catch {}
|
|
2456
|
+
try {
|
|
2457
|
+
log.process("info", "general", `🔄 Checking out merge base ${mergeBaseCommit.slice(0, 7)}...`);
|
|
2458
|
+
execSync(`git checkout ${mergeBaseCommit}`, { stdio: "pipe" });
|
|
2459
|
+
log.process("info", "general", "📦 Installing dependencies...");
|
|
2460
|
+
try {
|
|
2461
|
+
execSync("pnpm install --frozen-lockfile", {
|
|
2462
|
+
stdio: "pipe",
|
|
2463
|
+
timeout: 12e4
|
|
2464
|
+
});
|
|
2465
|
+
} catch {
|
|
2466
|
+
try {
|
|
2467
|
+
execSync("npm ci", {
|
|
2468
|
+
stdio: "pipe",
|
|
2469
|
+
timeout: 12e4
|
|
2470
|
+
});
|
|
2471
|
+
} catch {
|
|
2472
|
+
execSync("npm install", {
|
|
2473
|
+
stdio: "pipe",
|
|
2474
|
+
timeout: 12e4
|
|
2475
|
+
});
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
log.process("info", "general", "📖 Building Storybook...");
|
|
2479
|
+
if (config.storybookShots?.storybookUrl) try {
|
|
2480
|
+
execSync("npx storybook build", {
|
|
2481
|
+
stdio: "pipe",
|
|
2482
|
+
timeout: 3e5
|
|
2483
|
+
});
|
|
2484
|
+
} catch {
|
|
2485
|
+
log.process("info", "general", "Storybook build command failed, trying build-storybook...");
|
|
2486
|
+
execSync("npx build-storybook", {
|
|
2487
|
+
stdio: "pipe",
|
|
2488
|
+
timeout: 3e5
|
|
2489
|
+
});
|
|
2490
|
+
}
|
|
2491
|
+
const originalCommitHash = config.commitHash;
|
|
2492
|
+
const originalRefName = config.commitRefName;
|
|
2493
|
+
config.commitHash = mergeBaseCommit;
|
|
2494
|
+
config.commitRefName = baseRef;
|
|
2495
|
+
log.process("info", "general", "🚀 Running Third Eye for merge base...");
|
|
2496
|
+
await platformRunner(config, apiToken);
|
|
2497
|
+
config.commitHash = originalCommitHash;
|
|
2498
|
+
config.commitRefName = originalRefName;
|
|
2499
|
+
log.process("info", "general", `✅ Patch build complete for merge base ${mergeBaseCommit.slice(0, 7)}`);
|
|
2500
|
+
} finally {
|
|
2501
|
+
log.process("info", "general", `🔄 Restoring original state...`);
|
|
2502
|
+
try {
|
|
2503
|
+
if (originalBranch === "HEAD") execSync(`git checkout ${originalRef}`, { stdio: "pipe" });
|
|
2504
|
+
else execSync(`git checkout ${originalBranch}`, { stdio: "pipe" });
|
|
2505
|
+
if (hasStash) execSync("git stash pop", { stdio: "pipe" });
|
|
2506
|
+
} catch (err) {
|
|
2507
|
+
log.process("error", "general", `Failed to restore git state: ${err instanceof Error ? err.message : String(err)}`);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2375
2511
|
//#endregion
|
|
2376
2512
|
//#region src/docker-runner/utils.ts
|
|
2377
2513
|
const executeDockerRun = async ({ version }) => {
|
|
@@ -2446,7 +2582,11 @@ const generatePagesFromSitemap = async () => {
|
|
|
2446
2582
|
//#endregion
|
|
2447
2583
|
//#region src/bin.ts
|
|
2448
2584
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
2449
|
-
const
|
|
2585
|
+
const args = yargs(hideBin(process.argv)).option("patch-build", {
|
|
2586
|
+
type: "string",
|
|
2587
|
+
describe: "Create a patch build for the merge base. Format: head...base (e.g. feature...main)"
|
|
2588
|
+
}).parseSync();
|
|
2589
|
+
const commandArgs = args._;
|
|
2450
2590
|
const version = getVersion();
|
|
2451
2591
|
if (version) log.process("info", "general", `Version: ${version}`);
|
|
2452
2592
|
(async () => {
|
|
@@ -2475,6 +2615,7 @@ if (version) log.process("info", "general", `Version: ${version}`);
|
|
|
2475
2615
|
log.process("info", "general", `🚀 Starting Lost Pixel in 'platform' mode`);
|
|
2476
2616
|
const apiToken = await getPlatformApiToken(config);
|
|
2477
2617
|
if (commandArgs.includes("finalize")) await sendFinalizeToAPI(config, apiToken);
|
|
2618
|
+
else if (args["patch-build"]) await patchBuildRunner(args["patch-build"], config, apiToken);
|
|
2478
2619
|
else await platformRunner(config, apiToken);
|
|
2479
2620
|
} else {
|
|
2480
2621
|
log.process("info", "general", `🚀 Starting Lost Pixel in 'generateOnly' mode`);
|