Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/codemod/batch-test/repos.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
[
{
"repo": "firebase/firebase-tools",
"repo": "KKonstantinov/firebase-tools-fork",
"ref": "main",
"packages": [
{
"dir": ".",
"sourceDir": "src/mcp",
"sourceDir": "src",
"checks": {
"typecheck": "npx tsc -p tsconfig.compile.json",
"typecheck": "npm run test:compile",
"build": null,
"test": null,
"lint": null
"test": "npx mocha 'src/mcp/onemcp/onemcp_server.spec.ts' 'src/mcp/tool.spec.ts' 'src/mcp/prompt.spec.ts'",
"lint": "ESLINT_USE_FLAT_CONFIG=false npx eslint --config .eslintrc.js --ext .ts,.js src/mcp"
}
}
]
Expand Down
52 changes: 33 additions & 19 deletions packages/codemod/src/bin/batchTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,28 @@ function detectPm(repoRoot: string): string {
return 'npm';
}

function installCommand(pm: string): string {
export function installCommand(pm: string, opts: { hasOwnPnpmWorkspace: boolean; packageDirs: string[] }): string {
if (pm !== 'pnpm') return `${pm} install --ignore-scripts`;
// pnpm walks up to find a workspace; clones live inside this SDK's pnpm workspace, so a plain
// `pnpm install` targets the OUTER workspace and never populates the clone's node_modules — every
// downstream check (tsc base config, tsup, vitest) then fails identically at baseline and post,
// masking real codemod signal.
// --ignore-workspace: treat the clone as a standalone project (not part of the SDK workspace).
// --no-frozen-lockfile: the codemod rewrites package.json to swap v1 → v2 deps, so the lockfile
// must be allowed to change. CI=true (set in shell()) otherwise defaults
// pnpm to a frozen lockfile and the post-codemod reinstall silently skips
// the new v2 deps, leaving the clone on v1.
// npm/yarn/bun key off a `workspaces` field in package.json (absent at this repo root), so they
// need no equivalent flags.
// --no-frozen-lockfile: the codemod rewrites package.json to swap v1 → v2 deps, so the lockfile must
// be allowed to change. CI=true (set in shell()) otherwise defaults pnpm to a frozen lockfile and the
// post-codemod reinstall silently skips the new v2 deps, leaving the clone on v1.
if (opts.hasOwnPnpmWorkspace) {
// The clone is its OWN pnpm workspace — pnpm-workspace.yaml defines catalog:/workspace: deps
// (e.g. mastra). `--ignore-workspace` would discard that file and pnpm would fail to resolve them
// (ERR_PNPM_CATALOG_ENTRY_NOT_FOUND_FOR_SPEC; unresolved workspace: links → repo skipped). We don't
// need it: the SDK workspace excludes the clones (`!packages/codemod/batch-test/**`) and pnpm uses
// the clone's own pnpm-workspace.yaml as the nearest root. Scope the install to the target packages
// and their dependencies (`<dir>...`) so a monorepo target installs only what the checks need (e.g.
// 2 of mastra's 161 projects) instead of the whole tree.
const filters = opts.packageDirs
.filter(dir => dir !== '.')
.map(dir => `--filter ${JSON.stringify(`./${dir}...`)}`)
.join(' ');
return `pnpm install --ignore-scripts --no-frozen-lockfile${filters ? ` ${filters}` : ''}`;
}
// Single-package clone with no workspace of its own: pnpm would walk up to the (clone-excluding) SDK
// workspace and never populate the clone's node_modules. `--ignore-workspace` treats it as standalone.
// npm/yarn/bun key off a `workspaces` field in package.json (absent at this repo root).
Comment thread
claude[bot] marked this conversation as resolved.
return 'pnpm install --ignore-scripts --ignore-workspace --no-frozen-lockfile';
}

Expand Down Expand Up @@ -643,18 +652,23 @@ function main(): void {
const pm = detectPm(clonePath);
console.log(` Package manager: ${pm}`);

// Step 3: Install
// Process packages
const packages: PackageEntry[] = entry.packages ?? [{ dir: '.', sourceDir: 'src' }];
const repoPkgResults: PackageReport[] = [];

// Step 3: Install. A clone that is its own pnpm workspace (catalog:/workspace: deps) must keep its
// pnpm-workspace.yaml — see installCommand. Computed once and reused for the post-codemod reinstall.
const installCmd = installCommand(pm, {
hasOwnPnpmWorkspace: existsSync(path.join(clonePath, 'pnpm-workspace.yaml')),
packageDirs: packages.map(p => p.dir)
});
console.log(' Installing dependencies...');
const installResult = shell(installCommand(pm), clonePath);
const installResult = shell(installCmd, clonePath);
if (installResult.exitCode !== 0) {
console.log(` ERROR: install failed, skipping\n ${installResult.stderr.split('\n')[0]}`);
continue;
}

// Process packages
const packages: PackageEntry[] = entry.packages ?? [{ dir: '.', sourceDir: 'src' }];
const repoPkgResults: PackageReport[] = [];

for (const pkg of packages) {
const sourceDir = pkg.sourceDir ?? 'src';
const fullPkgDir = path.join(clonePath, pkg.dir);
Expand Down Expand Up @@ -697,7 +711,7 @@ function main(): void {
if (rewrites > 0) console.log(` Pinned ${rewrites} deps to resolved published versions`);
}
console.log(' Re-installing dependencies...');
shell(installCommand(pm), clonePath);
shell(installCmd, clonePath);

// Step 7: Post-codemod checks
console.log(' Running post-codemod checks...');
Expand Down
Loading
Loading