diff --git a/README.md b/README.md index aaf5ef5..84c9815 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ Add a local config and GitHub Actions workflow: npx @openclaw/plugin-inspector init --ci ``` +`init --ci` detects `packageManager` and common lockfiles. Pass +`--package-manager pnpm`, `npm`, `yarn`, or `bun` when you want to override it. + Or install it as a dev dependency: ```bash diff --git a/src/advanced.js b/src/advanced.js index 657fd51..0ffd2e7 100644 --- a/src/advanced.js +++ b/src/advanced.js @@ -138,6 +138,7 @@ export { buildPluginInspectorConfig, defaultInitConfigPath, defaultInitWorkflowPath, + detectPackageManager, renderGithubActionsWorkflow, writePluginInspectorInit, } from "./init.js"; diff --git a/src/cli.js b/src/cli.js index 68a455e..8c05832 100755 --- a/src/cli.js +++ b/src/cli.js @@ -95,7 +95,7 @@ async function runInit(commandArgs) { const pluginRoot = readFlag(commandArgs, "--plugin-root") ?? readFlag(commandArgs, "--root"); const configPath = readFlag(commandArgs, "--config") ?? undefined; const workflowPath = readFlag(commandArgs, "--workflow") ?? undefined; - const packageManager = readFlag(commandArgs, "--package-manager") ?? "npm"; + const packageManager = readFlag(commandArgs, "--package-manager") ?? undefined; const result = await writePluginInspectorInit({ pluginRoot, configPath, diff --git a/src/init.js b/src/init.js index e8cd212..c2cd6ab 100644 --- a/src/init.js +++ b/src/init.js @@ -9,6 +9,7 @@ export const defaultInitWorkflowPath = ".github/workflows/plugin-inspector.yml"; export async function writePluginInspectorInit(options = {}) { const pluginRoot = path.resolve(options.pluginRoot ?? options.cwd ?? process.cwd()); const configPath = path.resolve(pluginRoot, options.configPath ?? defaultInitConfigPath); + const packageManager = options.packageManager ?? (await detectPackageManager(pluginRoot)); const written = []; if (existsSync(configPath) && options.force !== true) { @@ -26,11 +27,11 @@ export async function writePluginInspectorInit(options = {}) { throw new Error(`${path.relative(pluginRoot, workflowPath)} already exists; pass --force to overwrite it`); } await mkdir(path.dirname(workflowPath), { recursive: true }); - await writeFile(workflowPath, renderGithubActionsWorkflow({ packageManager: options.packageManager }), "utf8"); + await writeFile(workflowPath, renderGithubActionsWorkflow({ packageManager }), "utf8"); written.push(workflowPath); } - return { pluginRoot, configPath, written }; + return { pluginRoot, configPath, packageManager, written }; } export async function buildPluginInspectorConfig(options = {}) { @@ -88,6 +89,29 @@ ${setup.corepack ? " - run: corepack enable\n" : ""} - run: ${setup.in `; } +export async function detectPackageManager(pluginRoot) { + const root = path.resolve(pluginRoot ?? process.cwd()); + const packageJson = await readJsonIfExists(path.join(root, "package.json")); + const packageManager = packageJson?.packageManager; + if (typeof packageManager === "string") { + const [name] = packageManager.split("@"); + if (["npm", "pnpm", "yarn", "bun"].includes(name)) { + return name; + } + } + + if (existsSync(path.join(root, "pnpm-lock.yaml"))) { + return "pnpm"; + } + if (existsSync(path.join(root, "yarn.lock"))) { + return "yarn"; + } + if (existsSync(path.join(root, "bun.lockb")) || existsSync(path.join(root, "bun.lock"))) { + return "bun"; + } + return "npm"; +} + function inferSourceRoot(packageJson) { const entrypoints = [ packageJson?.openclaw?.entrypoint, diff --git a/test/api.test.js b/test/api.test.js index a9d3640..6d7f505 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -135,6 +135,7 @@ test("public API can initialize plugin inspector files", async () => { const workflow = await readFile(path.join(pluginRoot, ".github", "workflows", "plugin-inspector.yml"), "utf8"); assert.equal(result.written.length, 2); + assert.equal(result.packageManager, "npm"); assert.equal(config.plugin.id, "weather"); assert.equal(config.capture.mockSdk, true); assert.match(workflow, /npx @openclaw\/plugin-inspector ci --no-openclaw --runtime --mock-sdk/); diff --git a/test/cli.test.js b/test/cli.test.js index dff38e0..b40f6c7 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -211,6 +211,20 @@ test("init command writes plugin config and CI workflow", async () => { assert.match(workflow, /pnpm dlx @openclaw\/plugin-inspector ci --no-openclaw --runtime --mock-sdk/); }); +test("init command detects plugin package managers", async () => { + const rootDir = await createCliPluginRoot("plugin-inspector-cli-init-pm-"); + const cliPath = path.resolve("src/cli.js"); + await writeFile(path.join(rootDir, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n", "utf8"); + + await execFileAsync(process.execPath, [cliPath, "init", "--plugin-root", rootDir, "--ci", "--force"]); + const workflow = await readFile(path.join(rootDir, ".github", "workflows", "plugin-inspector.yml"), "utf8"); + + assert.match(workflow, /cache: pnpm/); + assert.match(workflow, /corepack enable/); + assert.match(workflow, /pnpm install --frozen-lockfile/); + assert.match(workflow, /pnpm dlx @openclaw\/plugin-inspector ci --no-openclaw --runtime --mock-sdk/); +}); + async function createCliPluginRoot(prefix) { const rootDir = await mkdtemp(path.join(os.tmpdir(), prefix)); await mkdir(path.join(rootDir, "src"), { recursive: true });