fix(build): preserve fresh startup metadata across rebuilds

This commit is contained in:
Vincent Koc
2026-05-31 07:00:44 +02:00
parent 51dee73a5d
commit ef9e9bf6b9
6 changed files with 112 additions and 6 deletions

View File

@@ -214,7 +214,9 @@ describe("resolveBuildAllSteps", () => {
});
it("keeps the full profile aligned with the declared steps", () => {
expect(resolveBuildAllSteps("full")).toEqual(BUILD_ALL_STEPS);
expect(resolveBuildAllSteps("full").map((step) => step.label)).toEqual(
BUILD_ALL_STEPS.map((step) => step.label),
);
expect(BUILD_ALL_PROFILES.full).toEqual(BUILD_ALL_STEPS.map((step) => step.label));
});
@@ -246,7 +248,7 @@ describe("resolveBuildAllSteps", () => {
throw new Error(`Missing ${profile} tsdown step`);
}
expect(BUILD_ALL_PROFILE_STEP_ENV[profile].tsdown).toEqual({
expect(BUILD_ALL_PROFILE_STEP_ENV[profile].tsdown).toMatchObject({
OPENCLAW_RUN_NODE_SKIP_DTS_BUILD: "1",
});
expect(
@@ -257,6 +259,30 @@ describe("resolveBuildAllSteps", () => {
}
});
it("preserves startup metadata only for profiles that regenerate it", () => {
for (const profile of ["full", "ciArtifacts", "cliStartup"]) {
const tsdown = resolveBuildAllSteps(profile).find((step) => step.label === "tsdown");
if (!tsdown) {
throw new Error(`Missing ${profile} tsdown step`);
}
expect(resolveBuildAllStep(tsdown, { env: {} }).options.env).toMatchObject({
OPENCLAW_PRESERVE_CLI_STARTUP_METADATA: "1",
});
}
for (const profile of ["gatewayWatch", "qaRuntime"]) {
const tsdown = resolveBuildAllSteps(profile).find((step) => step.label === "tsdown");
if (!tsdown) {
throw new Error(`Missing ${profile} tsdown step`);
}
expect(resolveBuildAllStep(tsdown, { env: {} }).options.env).not.toHaveProperty(
"OPENCLAW_PRESERVE_CLI_STARTUP_METADATA",
);
}
});
it("uses a minimal built runtime profile for gateway watch regression", () => {
expect(resolveBuildAllSteps("gatewayWatch").map((step) => step.label)).toEqual([
"tsdown",

View File

@@ -320,6 +320,39 @@ describe("resolveTsdownBuildInvocation", () => {
await expect(fsPromises.readFile(unrelatedFile, "utf8")).resolves.toBe("keep\n");
});
it("removes CLI startup metadata during default tsdown clean", async () => {
const rootDir = createTempDir("openclaw-tsdown-clean-metadata-default-");
const metadataFile = path.join(rootDir, "dist", "cli-startup-metadata.json");
await fsPromises.mkdir(path.dirname(metadataFile), { recursive: true });
await fsPromises.writeFile(metadataFile, '{"generatedBy":"test"}\n');
cleanTsdownOutputRoots({ cwd: rootDir });
await expectPathMissing(metadataFile);
});
it("preserves CLI startup metadata across opted-in build-all tsdown clean", async () => {
const rootDir = createTempDir("openclaw-tsdown-clean-metadata-");
const metadataFile = path.join(rootDir, "dist", "cli-startup-metadata.json");
const staleFile = path.join(rootDir, "dist", "stale.js");
const nestedStaleFile = path.join(rootDir, "dist", "nested", "stale.js");
await fsPromises.mkdir(path.dirname(nestedStaleFile), { recursive: true });
await fsPromises.writeFile(metadataFile, '{"generatedBy":"test"}\n');
await fsPromises.writeFile(staleFile, "stale\n");
await fsPromises.writeFile(nestedStaleFile, "stale\n");
cleanTsdownOutputRoots({
cwd: rootDir,
env: { OPENCLAW_PRESERVE_CLI_STARTUP_METADATA: "1" },
});
await expect(fsPromises.readFile(metadataFile, "utf8")).resolves.toBe(
'{"generatedBy":"test"}\n',
);
await expectPathMissing(staleFile);
await expectPathMissing(nestedStaleFile);
});
it("preserves existing package declarations when tsdown DTS output is skipped", async () => {
const rootDir = createTempDir("openclaw-tsdown-clean-skip-dts-");
const declarationFile = path.join(

View File

@@ -93,6 +93,7 @@ describe("write-cli-startup-metadata", () => {
const written = JSON.parse(readFileSync(outputPath, "utf8")) as {
browserHelpText: string;
channelOptions: string[];
generatorSignature: string;
nodesHelpText: string;
rootHelpText: string;
secretsHelpText: string;
@@ -104,6 +105,7 @@ describe("write-cli-startup-metadata", () => {
};
};
expect(written.channelOptions).toContain("matrix");
expect(written.generatorSignature).toMatch(/^[a-f0-9]{40}$/u);
expect(written.browserHelpText).toContain("Usage:");
expect(written.browserHelpText).toContain("openclaw browser");
expect(written.secretsHelpText).toContain("Usage:");
@@ -154,6 +156,16 @@ describe("write-cli-startup-metadata", () => {
await writeMetadata();
expect(nodesRenderCount).toBe(1);
const staleGeneratorMetadata = JSON.parse(readFileSync(outputPath, "utf8")) as Record<
string,
unknown
>;
staleGeneratorMetadata.generatorSignature = "stale-generator";
writeFileSync(outputPath, `${JSON.stringify(staleGeneratorMetadata, null, 2)}\n`, "utf8");
await writeMetadata();
expect(nodesRenderCount).toBe(2);
writeFixtureFile(
tempRoot,
"extensions/canvas/src/cli.ts",
@@ -165,7 +177,7 @@ describe("write-cli-startup-metadata", () => {
const written = JSON.parse(readFileSync(outputPath, "utf8")) as {
nodesHelpText: string;
};
expect(nodesRenderCount).toBe(2);
expect(written.nodesHelpText).toContain("openclaw nodes 2");
expect(nodesRenderCount).toBe(3);
expect(written.nodesHelpText).toContain("openclaw nodes 3");
});
});