mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-17 16:12:21 -06:00
test(plugins): deduplicate publication fixtures (#124312)
This commit is contained in:
committed by
GitHub
parent
38e0ae6ec8
commit
eb13f5719f
@@ -0,0 +1,62 @@
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { writeJsonFile } from "./temp-repo.js";
|
||||
|
||||
type PublishablePluginSurface = "npm" | "clawhub" | "both" | "clawhub-disabled";
|
||||
|
||||
type PublishablePluginFixtureOptions = {
|
||||
extensionId?: string;
|
||||
version: string;
|
||||
publishTo: PublishablePluginSurface;
|
||||
bundledDist?: boolean;
|
||||
dependency?: {
|
||||
packageName: string;
|
||||
version: string;
|
||||
requireLatest?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export function writePublishablePluginFixture(
|
||||
repoDir: string,
|
||||
options: PublishablePluginFixtureOptions,
|
||||
) {
|
||||
const extensionId = options.extensionId ?? "demo-plugin";
|
||||
const packageName = `@openclaw/${extensionId}`;
|
||||
const packageDir = join(repoDir, "extensions", extensionId);
|
||||
const publishToNpm = options.publishTo === "npm" || options.publishTo === "both";
|
||||
const publishToClawHub = options.publishTo === "clawhub" || options.publishTo === "both";
|
||||
const release = {
|
||||
...(publishToNpm ? { publishToNpm: true } : {}),
|
||||
...(publishToClawHub ? { publishToClawHub: true } : {}),
|
||||
...(options.publishTo === "clawhub-disabled" ? { publishToClawHub: false } : {}),
|
||||
...(options.dependency?.requireLatest
|
||||
? { requireLatestDependencies: [options.dependency.packageName] }
|
||||
: {}),
|
||||
};
|
||||
writeJsonFile(join(packageDir, "package.json"), {
|
||||
name: packageName,
|
||||
version: options.version,
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: "https://github.com/openclaw/openclaw",
|
||||
},
|
||||
...(options.dependency
|
||||
? { dependencies: { [options.dependency.packageName]: options.dependency.version } }
|
||||
: {}),
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
compat: { pluginApi: `>=${options.version}` },
|
||||
build: {
|
||||
openclawVersion: options.version,
|
||||
...(options.bundledDist ? { bundledDist: true } : {}),
|
||||
},
|
||||
install: { npmSpec: packageName },
|
||||
release,
|
||||
},
|
||||
});
|
||||
const exportName = extensionId.replaceAll(/[-.]/g, "_");
|
||||
writeFileSync(join(packageDir, "index.ts"), `export const ${exportName} = 1;\n`);
|
||||
writeFileSync(join(packageDir, "README.md"), "# Demo plugin\n");
|
||||
return { extensionId, packageDir, packageName };
|
||||
}
|
||||
@@ -31,7 +31,8 @@ import {
|
||||
OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
} from "../scripts/lib/plugin-npm-release.ts";
|
||||
import { runPluginClawHubReleaseCheck } from "../scripts/plugin-clawhub-release-check.ts";
|
||||
import { cleanupTempDirs, makeTempRepoRoot } from "./helpers/temp-repo.js";
|
||||
import { writePublishablePluginFixture } from "./helpers/publishable-plugin-fixture.js";
|
||||
import { cleanupTempDirs, makeTempRepoRoot, writeJsonFile } from "./helpers/temp-repo.js";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
@@ -2109,59 +2110,31 @@ function createTempPluginRepo(
|
||||
);
|
||||
writeFileSync(join(repoDir, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n");
|
||||
for (const currentExtensionId of extensionIds) {
|
||||
mkdirSync(join(repoDir, "extensions", currentExtensionId), { recursive: true });
|
||||
writeFileSync(
|
||||
join(repoDir, "extensions", currentExtensionId, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: `@openclaw/${currentExtensionId}`,
|
||||
version: "2026.4.1",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
...(options.requiredLatestDependencyVersion
|
||||
? {
|
||||
dependencies: {
|
||||
"demo-runtime": options.requiredLatestDependencyVersion,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...(options.includeClawHubContract === false
|
||||
? {}
|
||||
: {
|
||||
compat: {
|
||||
pluginApi: ">=2026.4.1",
|
||||
},
|
||||
build: {
|
||||
openclawVersion: "2026.4.1",
|
||||
},
|
||||
}),
|
||||
install: {
|
||||
npmSpec: `@openclaw/${currentExtensionId}`,
|
||||
const fixture = writePublishablePluginFixture(repoDir, {
|
||||
extensionId: currentExtensionId,
|
||||
version: "2026.4.1",
|
||||
publishTo: options.publishToClawHub === false ? "clawhub-disabled" : "clawhub",
|
||||
...(options.requiredLatestDependencyVersion
|
||||
? {
|
||||
dependency: {
|
||||
packageName: "demo-runtime",
|
||||
version: options.requiredLatestDependencyVersion,
|
||||
requireLatest: true,
|
||||
},
|
||||
release: {
|
||||
publishToClawHub: options.publishToClawHub ?? true,
|
||||
...(options.requiredLatestDependencyVersion
|
||||
? {
|
||||
requireLatestDependencies: ["demo-runtime"],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeFileSync(
|
||||
join(repoDir, "extensions", currentExtensionId, "index.ts"),
|
||||
`export const ${currentExtensionId.replaceAll(/[-.]/g, "_")} = 1;\n`,
|
||||
);
|
||||
writeFileSync(join(repoDir, "extensions", currentExtensionId, "README.md"), "# Demo plugin\n");
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
if (options.includeClawHubContract === false) {
|
||||
const manifestPath = join(fixture.packageDir, "package.json");
|
||||
const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as {
|
||||
openclaw?: { build?: unknown; compat?: unknown };
|
||||
};
|
||||
if (manifest.openclaw) {
|
||||
delete manifest.openclaw.compat;
|
||||
delete manifest.openclaw.build;
|
||||
}
|
||||
writeJsonFile(manifestPath, manifest);
|
||||
}
|
||||
}
|
||||
|
||||
git(repoDir, ["init", "-b", "main"]);
|
||||
|
||||
+23
-140
@@ -1,5 +1,5 @@
|
||||
// Plugin npm release tests validate plugin npm release artifacts.
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { bundledPluginFile, bundledPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
resolveSelectedPublishablePluginPackages,
|
||||
type PublishablePluginPackage,
|
||||
} from "../scripts/lib/plugin-npm-release.ts";
|
||||
import { writePublishablePluginFixture } from "./helpers/publishable-plugin-fixture.js";
|
||||
import { cleanupTempDirs, makeTempRepoRoot, writeJsonFile } from "./helpers/temp-repo.js";
|
||||
|
||||
type ExecFileSync = typeof import("node:child_process").execFileSync;
|
||||
@@ -169,12 +170,6 @@ function externalPluginContract(version: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function writePluginReadme(repoDir: string, extensionId: string): void {
|
||||
const packageDir = join(repoDir, "extensions", extensionId);
|
||||
mkdirSync(packageDir, { recursive: true });
|
||||
writeFileSync(join(packageDir, "README.md"), `# ${extensionId}\n`);
|
||||
}
|
||||
|
||||
describe("collectPublishablePluginPackageErrors", () => {
|
||||
it("accepts a valid publishable plugin package candidate", () => {
|
||||
expect(
|
||||
@@ -500,26 +495,9 @@ describe("collectPluginReleaseDependencyFreshnessErrors", () => {
|
||||
describe("collectPluginReleasePlan", () => {
|
||||
it("fails closed when the published-version lookup times out", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10"),
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
},
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
childProcessMock.execFileSyncOverride = ((command: string, args?: readonly string[]) => {
|
||||
expect(command).toBe("npm");
|
||||
@@ -542,20 +520,10 @@ describe("collectPluginReleasePlan", () => {
|
||||
describe("collectPublishablePluginPackages", () => {
|
||||
it("defers explicitly bundled plugins from npm and ClawHub release plans", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10",
|
||||
type: "module",
|
||||
repository: { type: "git", url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL },
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10"),
|
||||
build: { openclawVersion: "2026.4.10", bundledDist: true },
|
||||
install: { npmSpec: "@openclaw/demo-plugin" },
|
||||
release: { publishToClawHub: true, publishToNpm: true },
|
||||
},
|
||||
publishTo: "both",
|
||||
bundledDist: true,
|
||||
});
|
||||
|
||||
expect(collectPublishablePluginPackages(repoDir)).toStrictEqual([]);
|
||||
@@ -599,26 +567,9 @@ describe("collectPublishablePluginPackages", () => {
|
||||
|
||||
it("collects publishable npm plugins from extension package manifests", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10"),
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
},
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
|
||||
expect(collectPublishablePluginPackages(repoDir)).toEqual([
|
||||
@@ -637,18 +588,9 @@ describe("collectPublishablePluginPackages", () => {
|
||||
it("uses extended-stable for every publishable plugin at the exact root version", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
writeJsonFile(join(repoDir, "package.json"), { version: "2026.7.33" });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.7.33",
|
||||
type: "module",
|
||||
repository: { type: "git", url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL },
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.7.33"),
|
||||
install: { npmSpec: "@openclaw/demo-plugin" },
|
||||
release: { publishToNpm: true },
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
|
||||
expect(
|
||||
@@ -659,18 +601,9 @@ describe("collectPublishablePluginPackages", () => {
|
||||
it("rejects extended-stable plugins whose version differs from core", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
writeJsonFile(join(repoDir, "package.json"), { version: "2026.7.34" });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.7.33",
|
||||
type: "module",
|
||||
repository: { type: "git", url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL },
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.7.33"),
|
||||
install: { npmSpec: "@openclaw/demo-plugin" },
|
||||
release: { publishToNpm: true },
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
|
||||
expect(() =>
|
||||
@@ -680,29 +613,13 @@ describe("collectPublishablePluginPackages", () => {
|
||||
|
||||
it("collects exact release dependencies that must match npm latest", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
dependencies: {
|
||||
"demo-runtime": "1.2.3",
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10"),
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
requireLatestDependencies: ["demo-runtime"],
|
||||
},
|
||||
publishTo: "npm",
|
||||
dependency: {
|
||||
packageName: "demo-runtime",
|
||||
version: "1.2.3",
|
||||
requireLatest: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -727,26 +644,9 @@ describe("collectPublishablePluginPackages", () => {
|
||||
|
||||
it("does not validate unselected publishable plugin manifests", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10-beta.1",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10-beta.1"),
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
},
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
mkdirSync(join(repoDir, "extensions", "private-plugin"), { recursive: true });
|
||||
writeJsonFile(join(repoDir, "extensions", "private-plugin", "package.json"), {
|
||||
@@ -807,26 +707,9 @@ describe("collectPublishablePluginPackages", () => {
|
||||
|
||||
it("publishes alpha plugin packages to the alpha dist-tag", () => {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-release-");
|
||||
mkdirSync(join(repoDir, "extensions", "demo-plugin"), { recursive: true });
|
||||
writePluginReadme(repoDir, "demo-plugin");
|
||||
writeJsonFile(join(repoDir, "extensions", "demo-plugin", "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10-alpha.1",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
...externalPluginContract("2026.4.10-alpha.1"),
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
},
|
||||
},
|
||||
publishTo: "npm",
|
||||
});
|
||||
|
||||
expect(collectPublishablePluginPackages(repoDir)).toEqual([
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// Plugin release pretag pack check tests cover its script-local target and command routing.
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { OPENCLAW_PLUGIN_NPM_REPOSITORY_URL } from "../../scripts/lib/plugin-npm-release.ts";
|
||||
import {
|
||||
collectPluginReleasePretagPackTargets,
|
||||
runPluginReleasePretagPackCheck,
|
||||
} from "../../scripts/plugin-release-pretag-pack-check.ts";
|
||||
import { writePublishablePluginFixture } from "../helpers/publishable-plugin-fixture.js";
|
||||
import { cleanupTempDirs, makeTempRepoRoot, writeJsonFile } from "../helpers/temp-repo.js";
|
||||
|
||||
const { execFileSyncMock } = vi.hoisted(() => ({
|
||||
@@ -36,37 +35,11 @@ afterEach(() => {
|
||||
|
||||
function createDualPublishPluginRepo() {
|
||||
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-pretag-pack-");
|
||||
const packageDir = join(repoDir, "extensions", "demo-plugin");
|
||||
mkdirSync(packageDir, { recursive: true });
|
||||
writeJsonFile(join(repoDir, "package.json"), { name: "openclaw-test-root", type: "module" });
|
||||
writeJsonFile(join(packageDir, "package.json"), {
|
||||
name: "@openclaw/demo-plugin",
|
||||
writePublishablePluginFixture(repoDir, {
|
||||
version: "2026.4.10",
|
||||
type: "module",
|
||||
repository: {
|
||||
type: "git",
|
||||
url: OPENCLAW_PLUGIN_NPM_REPOSITORY_URL,
|
||||
},
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
compat: {
|
||||
pluginApi: ">=2026.4.10",
|
||||
},
|
||||
build: {
|
||||
openclawVersion: "2026.4.10",
|
||||
},
|
||||
install: {
|
||||
npmSpec: "@openclaw/demo-plugin",
|
||||
},
|
||||
release: {
|
||||
publishToClawHub: true,
|
||||
publishToNpm: true,
|
||||
},
|
||||
},
|
||||
publishTo: "both",
|
||||
});
|
||||
writeFileSync(join(packageDir, "README.md"), "# Demo plugin\n");
|
||||
writeFileSync(join(packageDir, "index.ts"), "export const demo = 1;\n");
|
||||
|
||||
return repoDir;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user