mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
fix: prune stale root chunks before rebuilds
This commit is contained in:
@@ -16,6 +16,7 @@ const extraArgs = process.argv.slice(2);
|
||||
const INEFFECTIVE_DYNAMIC_IMPORT_RE = /\[INEFFECTIVE_DYNAMIC_IMPORT\]/;
|
||||
const UNRESOLVED_IMPORT_RE = /\[UNRESOLVED_IMPORT\]/;
|
||||
const ANSI_ESCAPE_RE = new RegExp(String.raw`\u001B\[[0-9;]*m`, "g");
|
||||
const HASHED_ROOT_JS_RE = /^(?<base>.+)-[A-Za-z0-9_-]+\.js$/u;
|
||||
|
||||
function removeDistPluginNodeModulesSymlinks(rootDir) {
|
||||
const extensionsDir = path.join(rootDir, "extensions");
|
||||
@@ -47,6 +48,34 @@ function pruneStaleRuntimeSymlinks() {
|
||||
removeDistPluginNodeModulesSymlinks(path.join(cwd, "dist-runtime"));
|
||||
}
|
||||
|
||||
export function pruneStaleRootChunkFiles(params = {}) {
|
||||
const cwd = params.cwd ?? process.cwd();
|
||||
const fsImpl = params.fs ?? fs;
|
||||
const roots = [path.join(cwd, "dist"), path.join(cwd, "dist-runtime")];
|
||||
for (const root of roots) {
|
||||
let entries = [];
|
||||
try {
|
||||
entries = fsImpl.readdirSync(root, { withFileTypes: true });
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
if (!entry.isFile()) {
|
||||
continue;
|
||||
}
|
||||
if (!HASHED_ROOT_JS_RE.test(entry.name)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
fsImpl.rmSync(path.join(root, entry.name), { force: true });
|
||||
} catch {
|
||||
// Best-effort cleanup. The subsequent build will overwrite any stragglers.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function pruneSourceCheckoutBundledPluginNodeModules(params = {}) {
|
||||
const cwd = params.cwd ?? process.cwd();
|
||||
const logger = params.logger ?? console;
|
||||
@@ -116,6 +145,7 @@ function isMainModule() {
|
||||
if (isMainModule()) {
|
||||
pruneSourceCheckoutBundledPluginNodeModules();
|
||||
pruneStaleRuntimeSymlinks();
|
||||
pruneStaleRootChunkFiles();
|
||||
const invocation = resolveTsdownBuildInvocation();
|
||||
const result = spawnSync(invocation.command, invocation.args, invocation.options);
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import fs from "node:fs";
|
||||
import fsPromises from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
pruneSourceCheckoutBundledPluginNodeModules,
|
||||
pruneStaleRootChunkFiles,
|
||||
resolveTsdownBuildInvocation,
|
||||
} from "../../scripts/tsdown-build.mjs";
|
||||
import { createScriptTestHarness } from "./test-helpers.js";
|
||||
|
||||
const { createTempDir } = createScriptTestHarness();
|
||||
|
||||
describe("resolveTsdownBuildInvocation", () => {
|
||||
it("routes Windows tsdown builds through the pnpm runner instead of shell=true", () => {
|
||||
@@ -56,4 +62,44 @@ describe("resolveTsdownBuildInvocation", () => {
|
||||
warn.mockRestore();
|
||||
rmSync.mockRestore();
|
||||
});
|
||||
|
||||
it("prunes stale hashed root chunk files but keeps stable aliases and nested assets", async () => {
|
||||
const rootDir = createTempDir("openclaw-tsdown-build-");
|
||||
const distDir = path.join(rootDir, "dist");
|
||||
const distRuntimeDir = path.join(rootDir, "dist-runtime");
|
||||
await fsPromises.mkdir(path.join(distDir, "control-ui"), { recursive: true });
|
||||
await fsPromises.mkdir(distRuntimeDir, { recursive: true });
|
||||
await fsPromises.writeFile(path.join(distDir, "delegate-BPjCe4gC.js"), "old delegate\n");
|
||||
await fsPromises.writeFile(path.join(distDir, "compact.runtime-2DiEmVcA.js"), "old runtime\n");
|
||||
await fsPromises.writeFile(path.join(distDir, "compact.runtime.js"), "stable alias\n");
|
||||
await fsPromises.writeFile(path.join(distDir, "entry.js"), "entry\n");
|
||||
await fsPromises.writeFile(path.join(distDir, "control-ui", "index.html"), "asset\n");
|
||||
await fsPromises.writeFile(
|
||||
path.join(distRuntimeDir, "heartbeat-runner.runtime-fspOEj_1.js"),
|
||||
"old runtime\n",
|
||||
);
|
||||
await fsPromises.writeFile(path.join(distRuntimeDir, "heartbeat-runner.runtime.js"), "alias\n");
|
||||
|
||||
pruneStaleRootChunkFiles({ cwd: rootDir });
|
||||
|
||||
await expect(
|
||||
fsPromises.readFile(path.join(distDir, "compact.runtime.js"), "utf8"),
|
||||
).resolves.toBe("stable alias\n");
|
||||
await expect(fsPromises.readFile(path.join(distDir, "entry.js"), "utf8")).resolves.toBe(
|
||||
"entry\n",
|
||||
);
|
||||
await expect(
|
||||
fsPromises.readFile(path.join(distDir, "control-ui", "index.html"), "utf8"),
|
||||
).resolves.toBe("asset\n");
|
||||
await expect(
|
||||
fsPromises.readFile(path.join(distRuntimeDir, "heartbeat-runner.runtime.js"), "utf8"),
|
||||
).resolves.toBe("alias\n");
|
||||
await expect(fsPromises.stat(path.join(distDir, "delegate-BPjCe4gC.js"))).rejects.toThrow();
|
||||
await expect(
|
||||
fsPromises.stat(path.join(distDir, "compact.runtime-2DiEmVcA.js")),
|
||||
).rejects.toThrow();
|
||||
await expect(
|
||||
fsPromises.stat(path.join(distRuntimeDir, "heartbeat-runner.runtime-fspOEj_1.js")),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user