From 20357f41f55ce246220ec56ef257ea7d6ac82e3a Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 29 Jan 2026 17:09:02 +0000 Subject: [PATCH] fix(cli): revert findCodebase change that broke ../shared codebases (#7740) * fix(cli): revert findCodebase relative_path check that broke ../shared codebases The previous change added a check to ensure script paths start with the codebase's relative_path. However, this broke cases where relative_path uses parent directory references (e.g., "../shared") because: 1. path.join normalizes paths, so "/project/../shared/f/script.ts" becomes "/shared/f/script.ts" 2. FSFSElement strips the cwd prefix, resulting in "f/script.ts" 3. The check "f/script.ts".startsWith("../shared/") failed The original behavior was correct - relative_path indicates where to find codebase files, while includes/excludes patterns match against the normalized paths that get passed during sync. Fixes regression reported in #7729 comments. Co-Authored-By: Claude Opus 4.5 * test(cli): add preview test for codebase with imports Tests that codebase bundling correctly includes imported modules, which is the key functionality needed for ../shared codebases. The test creates a helper module and a main script that imports from it, then verifies the bundled script executes correctly. Co-Authored-By: Claude Opus 4.5 --------- Co-authored-by: Claude Opus 4.5 --- cli/src/commands/sync/sync.ts | 16 +------ cli/test/preview.test.ts | 79 +++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/cli/src/commands/sync/sync.ts b/cli/src/commands/sync/sync.ts index d2068ab23f..55543e7b4d 100644 --- a/cli/src/commands/sync/sync.ts +++ b/cli/src/commands/sync/sync.ts @@ -133,18 +133,6 @@ export function findCodebase( return; } for (const c of codebases) { - // First check if the path is within this codebase's relative_path - const codebasePath = c.relative_path.replaceAll("\\", "/"); - const normalizedPath = path.replaceAll("\\", "/"); - if (!normalizedPath.startsWith(codebasePath + "/") && normalizedPath !== codebasePath) { - continue; - } - - // Get the path relative to the codebase root for pattern matching - const relativePath = normalizedPath.startsWith(codebasePath + "/") - ? normalizedPath.substring(codebasePath.length + 1) - : normalizedPath; - let included = false; let excluded = false; if (c.includes == undefined || c.includes == null) { @@ -157,7 +145,7 @@ export function findCodebase( if (included) { break; } - if (minimatch(relativePath, r)) { + if (minimatch(path, r)) { included = true; } } @@ -165,7 +153,7 @@ export function findCodebase( c.excludes = [c.excludes]; } for (const r of c.excludes ?? []) { - if (minimatch(relativePath, r)) { + if (minimatch(path, r)) { excluded = true; } } diff --git a/cli/test/preview.test.ts b/cli/test/preview.test.ts index 96a1f22224..eeb3718309 100644 --- a/cli/test/preview.test.ts +++ b/cli/test/preview.test.ts @@ -306,6 +306,85 @@ export function main(name: string = "World") { sanitizeOps: false, }); +Deno.test({ + name: "script preview: codebase with imports (simulates ../shared layout)", + async fn() { + await withTestBackend(async (backend, tempDir) => { + // This test simulates a codebase that could be in a parent directory. + // The structure is: + // tempDir/ + // wmill.yaml (codebase at ".") + // f/ + // lib/ + // helper.ts (shared module) + // main_script.ts (imports helper) + // + // This tests that codebase bundling correctly includes imported modules, + // which is the key functionality needed for ../shared codebases during sync. + // Note: Preview requires valid windmill paths (u/, g/, f/), so we run + // from within the codebase directory. + + await createWmillConfig(tempDir, { + defaultTs: "bun", + codebases: [{ relative_path: ".", includes: ["**"] }], + }); + + // Create helper module + await Deno.mkdir(`${tempDir}/f/lib`, { recursive: true }); + await Deno.writeTextFile( + `${tempDir}/f/lib/helper.ts`, + `export function greet(name: string): string { + return \`Hello from shared codebase, \${name}!\`; +}` + ); + + // Create main script that imports the helper + await Deno.writeTextFile( + `${tempDir}/f/lib/main_script.ts`, + `import { greet } from "./helper"; + +export function main(name: string = "World") { + console.log("Running codebase script with imports"); + return greet(name); +}` + ); + + // Create script metadata + await Deno.writeTextFile( + `${tempDir}/f/lib/main_script.script.yaml`, + `summary: "Test script with imports" +description: "Test script that imports from helper module" +lock: "" +schema: + $schema: "https://json-schema.org/draft/2020-12/schema" + type: object + properties: + name: + type: string + default: "World" + required: [] +` + ); + + // Run preview - the script should be bundled with the helper module + const result = await backend.runCLICommand( + ["script", "preview", "f/lib/main_script.ts"], + tempDir + ); + + assertEquals(result.code, 0, `Preview failed: ${result.stderr}\n${result.stdout}`); + // The script should be bundled (includes the helper) and run successfully + assertStringIncludes( + result.stdout + result.stderr, + "Hello from shared codebase, World!", + `Expected codebase script output not found. Got: ${result.stdout}\n${result.stderr}` + ); + }); + }, + sanitizeResources: false, + sanitizeOps: false, +}); + // ============================================================================= // FLOW PREVIEW TESTS // =============================================================================