diff --git a/scripts/lib/run-extension-oxlint.mjs b/scripts/lib/run-extension-oxlint.mjs new file mode 100644 index 00000000000..6f6ffeec565 --- /dev/null +++ b/scripts/lib/run-extension-oxlint.mjs @@ -0,0 +1,91 @@ +import { spawnSync } from "node:child_process"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { + acquireLocalHeavyCheckLockSync, + applyLocalOxlintPolicy, +} from "./local-heavy-check-runtime.mjs"; + +export function runExtensionOxlint(params) { + const repoRoot = process.cwd(); + const oxlintPath = path.resolve("node_modules", ".bin", "oxlint"); + const releaseLock = acquireLocalHeavyCheckLockSync({ + cwd: repoRoot, + env: process.env, + toolName: params.toolName, + lockName: params.lockName, + }); + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), params.tempDirPrefix)); + const tempConfigPath = path.join(tempDir, "oxlint.json"); + + try { + const extensionFiles = params.roots.flatMap((root) => + collectTypeScriptFiles(path.resolve(repoRoot, root)), + ); + + if (extensionFiles.length === 0) { + console.error(params.emptyMessage); + process.exit(1); + } + + writeTempOxlintConfig(repoRoot, tempConfigPath); + + const baseArgs = ["-c", tempConfigPath, ...process.argv.slice(2), ...extensionFiles]; + const { args: finalArgs, env } = applyLocalOxlintPolicy(baseArgs, process.env); + const result = spawnSync(oxlintPath, finalArgs, { + stdio: "inherit", + env, + shell: process.platform === "win32", + }); + + if (result.error) { + throw result.error; + } + + process.exit(result.status ?? 1); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + releaseLock(); + } +} + +function writeTempOxlintConfig(repoRoot, configPath) { + const config = JSON.parse(fs.readFileSync(path.resolve(repoRoot, ".oxlintrc.json"), "utf8")); + + delete config.$schema; + + if (Array.isArray(config.ignorePatterns)) { + config.ignorePatterns = config.ignorePatterns.filter((pattern) => pattern !== "extensions/"); + if (config.ignorePatterns.length === 0) { + delete config.ignorePatterns; + } + } + + fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8"); +} + +function collectTypeScriptFiles(directoryPath) { + const entries = fs.readdirSync(directoryPath, { withFileTypes: true }); + const files = []; + + for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) { + const entryPath = path.join(directoryPath, entry.name); + if (entry.isDirectory()) { + files.push(...collectTypeScriptFiles(entryPath)); + continue; + } + + if (!entry.isFile()) { + continue; + } + + if (!entry.name.endsWith(".ts") && !entry.name.endsWith(".tsx")) { + continue; + } + + files.push(path.relative(process.cwd(), entryPath).split(path.sep).join("/")); + } + + return files; +} diff --git a/scripts/run-bundled-extension-oxlint.mjs b/scripts/run-bundled-extension-oxlint.mjs index b44eaa08401..ed0fbd5412d 100644 --- a/scripts/run-bundled-extension-oxlint.mjs +++ b/scripts/run-bundled-extension-oxlint.mjs @@ -1,88 +1,9 @@ -import { spawnSync } from "node:child_process"; -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import { - acquireLocalHeavyCheckLockSync, - applyLocalOxlintPolicy, -} from "./lib/local-heavy-check-runtime.mjs"; +import { runExtensionOxlint } from "./lib/run-extension-oxlint.mjs"; -const repoRoot = process.cwd(); -const oxlintPath = path.resolve("node_modules", ".bin", "oxlint"); -const releaseLock = acquireLocalHeavyCheckLockSync({ - cwd: repoRoot, - env: process.env, +runExtensionOxlint({ + roots: ["extensions"], toolName: "oxlint-bundled-extensions", lockName: "oxlint-bundled-extensions", + tempDirPrefix: "openclaw-bundled-extension-oxlint-", + emptyMessage: "No bundled extension files found.", }); - -const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-bundled-extension-oxlint-")); -const tempConfigPath = path.join(tempDir, "oxlint.json"); - -try { - const extensionFiles = collectTypeScriptFiles(path.resolve(repoRoot, "extensions")); - - if (extensionFiles.length === 0) { - console.error("No bundled extension files found."); - process.exit(1); - } - - writeTempOxlintConfig(tempConfigPath); - - const baseArgs = ["-c", tempConfigPath, ...process.argv.slice(2), ...extensionFiles]; - const { args: finalArgs, env } = applyLocalOxlintPolicy(baseArgs, process.env); - const result = spawnSync(oxlintPath, finalArgs, { - stdio: "inherit", - env, - shell: process.platform === "win32", - }); - - if (result.error) { - throw result.error; - } - - process.exit(result.status ?? 1); -} finally { - fs.rmSync(tempDir, { recursive: true, force: true }); - releaseLock(); -} - -function writeTempOxlintConfig(configPath) { - const config = JSON.parse(fs.readFileSync(path.resolve(repoRoot, ".oxlintrc.json"), "utf8")); - - delete config.$schema; - - if (Array.isArray(config.ignorePatterns)) { - config.ignorePatterns = config.ignorePatterns.filter((pattern) => pattern !== "extensions/"); - if (config.ignorePatterns.length === 0) { - delete config.ignorePatterns; - } - } - - fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8"); -} - -function collectTypeScriptFiles(directoryPath) { - const entries = fs.readdirSync(directoryPath, { withFileTypes: true }); - const files = []; - - for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) { - const entryPath = path.join(directoryPath, entry.name); - if (entry.isDirectory()) { - files.push(...collectTypeScriptFiles(entryPath)); - continue; - } - - if (!entry.isFile()) { - continue; - } - - if (!entry.name.endsWith(".ts") && !entry.name.endsWith(".tsx")) { - continue; - } - - files.push(path.relative(repoRoot, entryPath).split(path.sep).join("/")); - } - - return files; -} diff --git a/scripts/run-extension-channel-oxlint.mjs b/scripts/run-extension-channel-oxlint.mjs index 32a1d2c4a0f..1600454c9b0 100644 --- a/scripts/run-extension-channel-oxlint.mjs +++ b/scripts/run-extension-channel-oxlint.mjs @@ -1,91 +1,10 @@ -import { spawnSync } from "node:child_process"; -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; import { extensionChannelTestRoots } from "../vitest.channel-paths.mjs"; -import { - acquireLocalHeavyCheckLockSync, - applyLocalOxlintPolicy, -} from "./lib/local-heavy-check-runtime.mjs"; +import { runExtensionOxlint } from "./lib/run-extension-oxlint.mjs"; -const repoRoot = process.cwd(); -const oxlintPath = path.resolve("node_modules", ".bin", "oxlint"); -const releaseLock = acquireLocalHeavyCheckLockSync({ - cwd: repoRoot, - env: process.env, +runExtensionOxlint({ + roots: extensionChannelTestRoots, toolName: "oxlint-extension-channels", lockName: "oxlint-extension-channels", + tempDirPrefix: "openclaw-extension-channel-oxlint-", + emptyMessage: "No extension channel files found.", }); - -const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-extension-channel-oxlint-")); -const tempConfigPath = path.join(tempDir, "oxlint.json"); - -try { - const channelFiles = extensionChannelTestRoots.flatMap((root) => - collectTypeScriptFiles(path.resolve(repoRoot, root)), - ); - - if (channelFiles.length === 0) { - console.error("No extension channel files found."); - process.exit(1); - } - - writeTempOxlintConfig(tempConfigPath); - - const baseArgs = ["-c", tempConfigPath, ...process.argv.slice(2), ...channelFiles]; - const { args: finalArgs, env } = applyLocalOxlintPolicy(baseArgs, process.env); - const result = spawnSync(oxlintPath, finalArgs, { - stdio: "inherit", - env, - shell: process.platform === "win32", - }); - - if (result.error) { - throw result.error; - } - - process.exit(result.status ?? 1); -} finally { - fs.rmSync(tempDir, { recursive: true, force: true }); - releaseLock(); -} - -function writeTempOxlintConfig(configPath) { - const config = JSON.parse(fs.readFileSync(path.resolve(repoRoot, ".oxlintrc.json"), "utf8")); - - delete config.$schema; - - if (Array.isArray(config.ignorePatterns)) { - config.ignorePatterns = config.ignorePatterns.filter((pattern) => pattern !== "extensions/"); - if (config.ignorePatterns.length === 0) { - delete config.ignorePatterns; - } - } - - fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8"); -} - -function collectTypeScriptFiles(directoryPath) { - const entries = fs.readdirSync(directoryPath, { withFileTypes: true }); - const files = []; - - for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) { - const entryPath = path.join(directoryPath, entry.name); - if (entry.isDirectory()) { - files.push(...collectTypeScriptFiles(entryPath)); - continue; - } - - if (!entry.isFile()) { - continue; - } - - if (!entry.name.endsWith(".ts") && !entry.name.endsWith(".tsx")) { - continue; - } - - files.push(path.relative(repoRoot, entryPath).split(path.sep).join("/")); - } - - return files; -}