Compare commits
2 Commits
v1.683.2
...
fix/inline
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aac43977e | ||
|
|
05d4d6dd48 |
@@ -29,7 +29,10 @@ import { FlowFile } from "./flow.ts";
|
||||
import { FlowValue } from "../../../gen/types.gen.ts";
|
||||
import { replaceInlineScripts } from "../../../windmill-utils-internal/src/inline-scripts/replacer.ts";
|
||||
import { workspaceDependenciesLanguages } from "../../utils/script_common.ts";
|
||||
import { extractNameFromFolder, getFolderSuffix } from "../../utils/resource_folders.ts";
|
||||
import {
|
||||
extractNameFromFolder,
|
||||
getNonDottedPaths,
|
||||
} from "../../utils/resource_folders.ts";
|
||||
|
||||
const TOP_HASH = "__flow_hash";
|
||||
async function generateFlowHash(
|
||||
@@ -157,7 +160,9 @@ export async function generateFlowLockInternal(
|
||||
filteredDeps
|
||||
);
|
||||
|
||||
const lockAssigner = newPathAssigner(opts.defaultTs ?? "bun");
|
||||
const lockAssigner = newPathAssigner(opts.defaultTs ?? "bun", {
|
||||
skipInlineScriptSuffix: getNonDottedPaths(),
|
||||
});
|
||||
const inlineScripts = extractInlineScriptsForFlows(
|
||||
flowValue.value.modules,
|
||||
{},
|
||||
|
||||
@@ -1768,6 +1768,66 @@ excludes: []
|
||||
});
|
||||
});
|
||||
|
||||
test("Integration: Sync pull with nonDottedPaths uses non-dotted inline script filenames", async () => {
|
||||
await withTestBackend(async (backend, tempDir) => {
|
||||
// Push a flow using default dotted paths
|
||||
await writeFile(
|
||||
`${tempDir}/wmill.yaml`,
|
||||
`defaultTs: bun
|
||||
includes:
|
||||
- "**"
|
||||
excludes: []
|
||||
`,
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const uniqueId = Date.now();
|
||||
const flowName = `f/test/nondot_pull_inline_${uniqueId}`;
|
||||
const flowFixture = createFlowFixture(flowName);
|
||||
await mkdir(`${tempDir}/f/test/nondot_pull_inline_${uniqueId}${getFolderSuffix("flow")}`, { recursive: true });
|
||||
for (const file of Object.values(flowFixture)) {
|
||||
await writeFile(`${tempDir}/${file.path}`, file.content, "utf-8");
|
||||
}
|
||||
|
||||
const pushResult = await backend.runCLICommand(
|
||||
["sync", "push", "--yes", "--includes", `f/test/nondot_pull_inline_${uniqueId}*/**`],
|
||||
tempDir,
|
||||
);
|
||||
expect(pushResult.code).toEqual(0);
|
||||
|
||||
// Pull into a fresh directory with nonDottedPaths enabled
|
||||
const tempDir2 = await mkdtemp(join(tmpdir(), "wmill_nondot_inline_"));
|
||||
try {
|
||||
await writeFile(
|
||||
`${tempDir2}/wmill.yaml`,
|
||||
`defaultTs: bun
|
||||
nonDottedPaths: true
|
||||
includes:
|
||||
- "**"
|
||||
excludes: []
|
||||
`,
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const pullResult = await backend.runCLICommand(["sync", "pull", "--yes"], tempDir2);
|
||||
expect(pullResult.code).toEqual(0);
|
||||
|
||||
// Verify pulled files use non-dotted inline script naming
|
||||
const files = await listFilesRecursive(tempDir2);
|
||||
const flowFiles = files.filter((f) => f.includes(`nondot_pull_inline_${uniqueId}`));
|
||||
|
||||
expect(flowFiles.length > 0).toBeTruthy();
|
||||
// Should use __flow folder, not .flow
|
||||
expect(flowFiles.some((f) => f.includes("__flow/"))).toBeTruthy();
|
||||
// No files should have .inline_script. in their name
|
||||
const dottedInlineFiles = flowFiles.filter((f) => f.includes(".inline_script."));
|
||||
expect(dottedInlineFiles.length).toEqual(0);
|
||||
} finally {
|
||||
await cleanupTempDir(tempDir2);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
// ws_error_handler_muted Persistence Tests
|
||||
// =============================================================================
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { expect, test, describe } from "bun:test";
|
||||
import { withTestBackend } from "./test_backend.ts";
|
||||
import { addWorkspace } from "../workspace.ts";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
||||
import {
|
||||
createLocalScript,
|
||||
createLocalFlow,
|
||||
@@ -19,7 +19,12 @@ import {
|
||||
/**
|
||||
* Helper to set up a workspace with wmill.yaml
|
||||
*/
|
||||
async function setupWorkspace(backend: any, tempDir: string, workspaceName: string) {
|
||||
async function setupWorkspace(
|
||||
backend: any,
|
||||
tempDir: string,
|
||||
workspaceName: string,
|
||||
nonDottedPaths = false
|
||||
) {
|
||||
const testWorkspace = {
|
||||
remote: backend.baseUrl,
|
||||
workspaceId: backend.workspace,
|
||||
@@ -29,11 +34,88 @@ async function setupWorkspace(backend: any, tempDir: string, workspaceName: stri
|
||||
await addWorkspace(testWorkspace, { force: true, configDir: backend.testConfigDir });
|
||||
|
||||
await writeFile(`${tempDir}/wmill.yaml`, `defaultTs: bun
|
||||
includes:
|
||||
${nonDottedPaths ? "nonDottedPaths: true\n" : ""}includes:
|
||||
- "**"
|
||||
excludes: []`, "utf-8");
|
||||
}
|
||||
|
||||
async function createLocalNonDottedFlow(tempDir: string, name: string) {
|
||||
const flowDir = `${tempDir}/f/test/${name}__flow`;
|
||||
await mkdir(flowDir, { recursive: true });
|
||||
|
||||
await writeFile(
|
||||
`${flowDir}/a.ts`,
|
||||
`export async function main() {\n return "Hello from flow ${name}";\n}`,
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
await writeFile(
|
||||
`${flowDir}/flow.yaml`,
|
||||
`summary: "${name} flow"
|
||||
description: "A flow for testing"
|
||||
value:
|
||||
modules:
|
||||
- id: a
|
||||
value:
|
||||
type: rawscript
|
||||
content: "!inline a.ts"
|
||||
language: bun
|
||||
input_transforms: {}
|
||||
schema:
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema"
|
||||
type: object
|
||||
properties: {}
|
||||
required: []
|
||||
`,
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
async function createLocalNonDottedApp(tempDir: string, name: string) {
|
||||
const appDir = `${tempDir}/f/test/${name}__app`;
|
||||
await mkdir(appDir, { recursive: true });
|
||||
|
||||
await writeFile(
|
||||
`${appDir}/app.yaml`,
|
||||
`summary: "${name} app"
|
||||
value:
|
||||
type: app
|
||||
grid:
|
||||
- id: button1
|
||||
data:
|
||||
type: buttoncomponent
|
||||
componentInput:
|
||||
type: runnable
|
||||
runnable:
|
||||
type: runnableByName
|
||||
inlineScript:
|
||||
content: |
|
||||
export async function main() {
|
||||
return "hello from app";
|
||||
}
|
||||
language: bun
|
||||
hiddenInlineScripts: []
|
||||
css: {}
|
||||
norefreshbar: false
|
||||
policy:
|
||||
on_behalf_of: null
|
||||
on_behalf_of_email: null
|
||||
triggerables: {}
|
||||
execution_mode: viewer
|
||||
`,
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
async function fileExists(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await stat(filePath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Main test: processes scripts, flows, and apps together
|
||||
// =============================================================================
|
||||
@@ -156,6 +238,87 @@ describe("generate-metadata flags", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("--lock-only preserves non-dotted flow filenames", async () => {
|
||||
await withTestBackend(async (backend, tempDir) => {
|
||||
await setupWorkspace(backend, tempDir, "lock_only_non_dotted_test", true);
|
||||
|
||||
await createLocalNonDottedFlow(tempDir, "my_flow");
|
||||
|
||||
const result = await backend.runCLICommand(
|
||||
["generate-metadata", "--yes", "--lock-only"],
|
||||
tempDir,
|
||||
"lock_only_non_dotted_test"
|
||||
);
|
||||
|
||||
expect(result.code).toEqual(0);
|
||||
|
||||
const flowDir = `${tempDir}/f/test/my_flow__flow`;
|
||||
const flowYaml = await readFile(`${flowDir}/flow.yaml`, "utf-8");
|
||||
|
||||
expect(flowYaml).toContain("!inline a.ts");
|
||||
expect(flowYaml).toContain("!inline a.lock");
|
||||
expect(flowYaml).not.toContain(".inline_script.");
|
||||
expect(await fileExists(`${flowDir}/a.lock`)).toEqual(true);
|
||||
expect(await fileExists(`${flowDir}/a.inline_script.ts`)).toEqual(false);
|
||||
expect(await fileExists(`${flowDir}/a.inline_script.lock`)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
test("generate-metadata preserves non-dotted flow inline script filenames", async () => {
|
||||
await withTestBackend(async (backend, tempDir) => {
|
||||
await setupWorkspace(backend, tempDir, "full_gen_non_dotted_flow_test", true);
|
||||
|
||||
await createLocalNonDottedFlow(tempDir, "my_flow");
|
||||
|
||||
const result = await backend.runCLICommand(
|
||||
["generate-metadata", "--yes"],
|
||||
tempDir,
|
||||
"full_gen_non_dotted_flow_test"
|
||||
);
|
||||
|
||||
expect(result.code).toEqual(0);
|
||||
|
||||
const flowDir = `${tempDir}/f/test/my_flow__flow`;
|
||||
const flowYaml = await readFile(`${flowDir}/flow.yaml`, "utf-8");
|
||||
|
||||
// Inline script references should use non-dotted naming
|
||||
expect(flowYaml).toContain("!inline a.ts");
|
||||
expect(flowYaml).toContain("!inline a.lock");
|
||||
expect(flowYaml).not.toContain(".inline_script.");
|
||||
expect(await fileExists(`${flowDir}/a.ts`)).toEqual(true);
|
||||
expect(await fileExists(`${flowDir}/a.lock`)).toEqual(true);
|
||||
expect(await fileExists(`${flowDir}/a.inline_script.ts`)).toEqual(false);
|
||||
expect(await fileExists(`${flowDir}/a.inline_script.lock`)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
test("generate-metadata uses non-dotted app inline script filenames", async () => {
|
||||
await withTestBackend(async (backend, tempDir) => {
|
||||
await setupWorkspace(backend, tempDir, "non_dotted_app_gen_test", true);
|
||||
|
||||
await createLocalNonDottedApp(tempDir, "my_app");
|
||||
|
||||
const result = await backend.runCLICommand(
|
||||
["generate-metadata", "--yes"],
|
||||
tempDir,
|
||||
"non_dotted_app_gen_test"
|
||||
);
|
||||
|
||||
expect(result.code).toEqual(0);
|
||||
|
||||
const appDir = `${tempDir}/f/test/my_app__app`;
|
||||
const appYaml = await readFile(`${appDir}/app.yaml`, "utf-8");
|
||||
|
||||
// Inline script references should use non-dotted naming
|
||||
expect(appYaml).not.toContain(".inline_script.");
|
||||
// Verify no dotted inline script files were created
|
||||
const { readdir: readdirAsync } = await import("node:fs/promises");
|
||||
const files = await readdirAsync(appDir);
|
||||
const dottedFiles = files.filter((f: string) => f.includes(".inline_script."));
|
||||
expect(dottedFiles.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
test("--schema-only only processes scripts (skips flows and apps)", async () => {
|
||||
await withTestBackend(async (backend, tempDir) => {
|
||||
await setupWorkspace(backend, tempDir, "schema_only_test");
|
||||
|
||||
Reference in New Issue
Block a user