mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(scripts): preserve symlinked API barrels
This commit is contained in:
@@ -21,6 +21,17 @@ export type ExtensionWildcardReexportPolicy = {
|
||||
remediationMessage: string;
|
||||
};
|
||||
|
||||
async function isFileFollowingLinks(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
return (await fs.stat(filePath)).isFile();
|
||||
} catch (error) {
|
||||
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
||||
return false;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function listGuardedFiles(policy: ExtensionWildcardReexportPolicy) {
|
||||
const files: string[] = [];
|
||||
const recursive = policy.fileScope === "all-extension-api-files";
|
||||
@@ -39,7 +50,12 @@ async function listGuardedFiles(policy: ExtensionWildcardReexportPolicy) {
|
||||
await visit(filePath, depth + 1);
|
||||
continue;
|
||||
}
|
||||
if ((recursive || depth === 1) && entry.isFile() && guardedFileNames.has(entry.name)) {
|
||||
if (!guardedFileNames.has(entry.name) || (!recursive && depth !== 1)) {
|
||||
continue;
|
||||
}
|
||||
// The root-only SDK guard historically follows API barrel symlinks; the
|
||||
// recursive local-barrel guard intentionally retains Dirent semantics.
|
||||
if (recursive ? entry.isFile() : await isFileFollowingLinks(filePath)) {
|
||||
files.push(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
// Check Plugin Sdk Wildcard Reexports tests cover check plugin sdk wildcard reexports script behavior.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { copyFileSync, mkdirSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { findPluginSdkWildcardReexports } from "../../scripts/check-plugin-sdk-wildcard-reexports.mts";
|
||||
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
|
||||
|
||||
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
||||
|
||||
describe("check-plugin-sdk-wildcard-reexports", () => {
|
||||
it("flags wildcard re-exports from plugin-sdk subpaths", () => {
|
||||
@@ -34,4 +40,50 @@ describe("check-plugin-sdk-wildcard-reexports", () => {
|
||||
),
|
||||
).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it("follows extension-root API barrel symlinks", () => {
|
||||
const root = tempDirs.make("openclaw-plugin-sdk-wildcard-");
|
||||
const scriptsDir = path.join(root, "scripts");
|
||||
const scriptsLibDir = path.join(scriptsDir, "lib");
|
||||
const extensionDir = path.join(root, "extensions", "fixture");
|
||||
mkdirSync(scriptsLibDir, { recursive: true });
|
||||
mkdirSync(extensionDir, { recursive: true });
|
||||
writeFileSync(path.join(root, "package.json"), '{"type":"module"}\n');
|
||||
writeFileSync(path.join(root, "pnpm-workspace.yaml"), "packages: []\n");
|
||||
copyFileSync(
|
||||
new URL("../../scripts/check-plugin-sdk-wildcard-reexports.mts", import.meta.url),
|
||||
path.join(scriptsDir, "check-plugin-sdk-wildcard-reexports.mts"),
|
||||
);
|
||||
for (const fileName of ["extension-wildcard-reexport-scanner.mts", "repo-root.mjs"]) {
|
||||
copyFileSync(
|
||||
new URL(`../../scripts/lib/${fileName}`, import.meta.url),
|
||||
path.join(scriptsLibDir, fileName),
|
||||
);
|
||||
}
|
||||
writeFileSync(
|
||||
path.join(extensionDir, "actual-api.ts"),
|
||||
'export * from "openclaw/plugin-sdk/foo";\n',
|
||||
);
|
||||
symlinkSync("actual-api.ts", path.join(extensionDir, "api.ts"));
|
||||
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
"--import",
|
||||
import.meta.resolve("tsx"),
|
||||
path.join(scriptsDir, "check-plugin-sdk-wildcard-reexports.mts"),
|
||||
"--json",
|
||||
],
|
||||
{ cwd: root, encoding: "utf8" },
|
||||
);
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(JSON.parse(result.stdout)).toEqual([
|
||||
{
|
||||
file: "extensions/fixture/api.ts",
|
||||
line: 1,
|
||||
text: 'export * from "openclaw/plugin-sdk/foo";',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -969,6 +969,7 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
|
||||
it.each([
|
||||
"test/scripts/check-extension-package-tsc-boundary.test.ts",
|
||||
"test/scripts/check-plugin-sdk-wildcard-reexports.test.ts",
|
||||
"test/scripts/control-ui-i18n.test.ts",
|
||||
])("routes process-group test %s to the isolated tooling shard", (testFile) => {
|
||||
expectSingleVitestRunPlan(buildVitestRunPlans([testFile]), {
|
||||
@@ -1370,6 +1371,7 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
forwardedArgs: [],
|
||||
includePatterns: [
|
||||
"test/scripts/check-extension-package-tsc-boundary.test.ts",
|
||||
"test/scripts/check-plugin-sdk-wildcard-reexports.test.ts",
|
||||
"test/scripts/control-ui-i18n.test.ts",
|
||||
"test/scripts/openclaw-e2e-instance.test.ts",
|
||||
],
|
||||
@@ -1556,6 +1558,7 @@ describe("scripts/test-projects changed-target routing", () => {
|
||||
forwardedArgs: [],
|
||||
includePatterns: [
|
||||
"test/scripts/check-extension-package-tsc-boundary.test.ts",
|
||||
"test/scripts/check-plugin-sdk-wildcard-reexports.test.ts",
|
||||
"test/scripts/control-ui-i18n.test.ts",
|
||||
"test/scripts/openclaw-e2e-instance.test.ts",
|
||||
],
|
||||
|
||||
@@ -4,6 +4,7 @@ export const toolingIsolatedTestFiles = [
|
||||
"test/plugins/bundled-provider-auth-literal-parity.2.test.ts",
|
||||
"test/plugins/bundled-provider-auth-literal-parity.3.test.ts",
|
||||
"test/scripts/check-extension-package-tsc-boundary.test.ts",
|
||||
"test/scripts/check-plugin-sdk-wildcard-reexports.test.ts",
|
||||
"test/scripts/control-ui-i18n.test.ts",
|
||||
"test/scripts/openclaw-e2e-instance.test.ts",
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user