mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-30 08:16:49 +00:00
fix(cli): flow preview hub steps and windmill paths, trigger templates (#12075)
* fix(cli): drop deprecated and unused fields from trigger new templates Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): flow preview takes the windmill path and runs hub steps with --step Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): run a deployed script step with its deployed lock in flow preview --step Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(cli): flow preview --remote honors nonDottedPaths when resolving the folder Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
20def22897
commit
65f3c5ee5c
@@ -9,7 +9,7 @@ import { stringify as yamlStringify } from "yaml";
|
||||
import { yamlParseFile } from "../../utils/yaml.ts";
|
||||
import { readTextFile, validateRequiredArgs } from "../../utils/utils.ts";
|
||||
import * as wmill from "../../../gen/services.gen.ts";
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { existsSync, mkdirSync, statSync, writeFileSync } from "node:fs";
|
||||
import { buildFolderPath, getMetadataFileName, loadNonDottedPathsSetting } from "../../utils/resource_folders.ts";
|
||||
|
||||
import { requireLogin } from "../../core/auth.ts";
|
||||
@@ -651,6 +651,10 @@ async function preview(
|
||||
const cwdBeforeConfig = process.cwd();
|
||||
if (useLocalPathScripts) {
|
||||
opts = await mergeConfigWithConfigFile(opts);
|
||||
} else {
|
||||
// --remote skips the config read, but resolving the flow folder still
|
||||
// needs the configured suffix (nonDottedPaths).
|
||||
await loadNonDottedPathsSetting();
|
||||
}
|
||||
const workspace = await resolveWorkspace(opts);
|
||||
await requireLogin(opts);
|
||||
@@ -660,26 +664,7 @@ async function preview(
|
||||
const argPath = flowPath;
|
||||
flowPath = toSyncRootRelativePath(flowPath, cwdBeforeConfig);
|
||||
|
||||
// Normalize path - ensure it's a directory path to a .flow or __flow folder
|
||||
const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP)
|
||||
|| flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP);
|
||||
if (!isFlowDir) {
|
||||
// Check if it's a flow.yaml file
|
||||
if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
|
||||
// Use dirname so a bare "flow.yaml" (no parent dir) becomes "."
|
||||
// instead of "" — the latter, after appending SEP below, becomes "/"
|
||||
// and silently reads from filesystem root.
|
||||
flowPath = dirname(flowPath);
|
||||
} else {
|
||||
throw new Error(
|
||||
"Flow path must be a .flow/__flow directory or a flow.yaml file"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!flowPath.endsWith(SEP)) {
|
||||
flowPath += SEP;
|
||||
}
|
||||
flowPath = resolveFlowFolderArg(flowPath);
|
||||
|
||||
// The flow's windmill path (e.g. "f/cli_smoke/myrelflow"). It is what the
|
||||
// preview job runs under, and the anchor for relative-import resolution:
|
||||
@@ -852,20 +837,13 @@ async function previewStep(
|
||||
// Falls through here only when the deployed PathScript is what we want —
|
||||
// either --remote was passed, or no local file exists for this path.
|
||||
log.info(colors.yellow(`Previewing step '${stepId}' (script ${moduleValue.path})...`));
|
||||
const script = moduleValue.hash
|
||||
? await wmill.getScriptByHash({
|
||||
workspace: workspace.workspaceId,
|
||||
hash: moduleValue.hash,
|
||||
})
|
||||
: await wmill.getScriptByPath({
|
||||
workspace: workspace.workspaceId,
|
||||
path: moduleValue.path,
|
||||
});
|
||||
const script = await loadStepScript(workspace.workspaceId, moduleValue);
|
||||
jobId = await wmill.runScriptPreview({
|
||||
workspace: workspace.workspaceId,
|
||||
requestBody: {
|
||||
content: script.content,
|
||||
language: script.language as any,
|
||||
lock: script.lock,
|
||||
// Anchor to the script's own deployed path so its relative imports
|
||||
// resolve against the workspace tree (or temp_script_refs).
|
||||
path: moduleValue.path,
|
||||
@@ -916,6 +894,54 @@ async function previewStep(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a `flow preview` argument to its local flow folder, with a trailing
|
||||
* separator. Accepts the folder itself, its flow.yaml, or the flow's Windmill
|
||||
* path (`f/x/my_flow`), which other commands take without the folder suffix.
|
||||
*/
|
||||
export function resolveFlowFolderArg(flowPath: string): string {
|
||||
const withSep = (p: string) => (p.endsWith(SEP) ? p : p + SEP);
|
||||
const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP)
|
||||
|| flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP);
|
||||
if (isFlowDir) {
|
||||
return withSep(flowPath);
|
||||
}
|
||||
if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
|
||||
// dirname, so a bare "flow.yaml" becomes "." rather than "", which would
|
||||
// turn into "/" and read from the filesystem root.
|
||||
return withSep(dirname(flowPath));
|
||||
}
|
||||
const bare = flowPath.endsWith(SEP) ? flowPath.slice(0, -SEP.length) : flowPath;
|
||||
// The configured suffix first, then the other one: a workspace can hold both.
|
||||
const candidates = [...new Set([buildFolderPath(bare, "flow"), bare + ".flow", bare + "__flow"])];
|
||||
const found = candidates.find((c) => existsSync(c) && statSync(c).isDirectory());
|
||||
if (found) {
|
||||
return withSep(found);
|
||||
}
|
||||
throw new Error(
|
||||
`Flow path must be a .flow/__flow directory, a flow.yaml file, or the Windmill path of a local flow; found none of ${candidates.join(", ")}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the code and lockfile a `script` step runs, the way a whole-flow run
|
||||
* resolves them: hub paths (`hub/<id>/...`) from the hub, others from the
|
||||
* workspace.
|
||||
*/
|
||||
export async function loadStepScript(
|
||||
workspaceId: string,
|
||||
moduleValue: { path: string; hash?: string },
|
||||
): Promise<{ content: string; language: string; lock?: string }> {
|
||||
if (moduleValue.path.startsWith("hub/")) {
|
||||
const hub = await wmill.getHubScriptByPath({ path: moduleValue.path });
|
||||
return { content: hub.content, language: hub.language, lock: hub.lockfile };
|
||||
}
|
||||
const script = moduleValue.hash
|
||||
? await wmill.getScriptByHash({ workspace: workspaceId, hash: moduleValue.hash })
|
||||
: await wmill.getScriptByPath({ workspace: workspaceId, path: moduleValue.path });
|
||||
return { content: script.content, language: script.language, lock: script.lock };
|
||||
}
|
||||
|
||||
// Strip the `.flow`/`__flow` directory suffix to recover the flow's logical
|
||||
// Windmill path. Workspaces with nonDottedPaths use `__flow`; the default
|
||||
// uses `.flow`. A previous version used `indexOf(".flow")` which returned -1
|
||||
@@ -1204,7 +1230,7 @@ const command = new Command()
|
||||
.action(run as any)
|
||||
.command(
|
||||
"preview",
|
||||
"preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow)."
|
||||
"preview a local flow without deploying it. <flow_path> is the flow's Windmill path (f/x/my_flow), its .flow/__flow folder or its flow.yaml. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow)."
|
||||
)
|
||||
.arguments("<flow_path:string>")
|
||||
.option(
|
||||
|
||||
@@ -338,14 +338,14 @@ export async function pushNativeTrigger(
|
||||
}
|
||||
}
|
||||
|
||||
const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
// Scaffold only fields the backend reads: `mode` supersedes the deprecated `enabled`, and
|
||||
// `request_type` the deprecated `is_async`.
|
||||
export const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
http: {
|
||||
script_path: "",
|
||||
is_flow: false,
|
||||
route_path: "",
|
||||
http_method: "get",
|
||||
is_async: false,
|
||||
requires_auth: true,
|
||||
request_type: "sync",
|
||||
authentication_method: "none",
|
||||
is_static_website: false,
|
||||
@@ -360,7 +360,7 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
filters: [],
|
||||
can_return_message: false,
|
||||
can_return_error_result: false,
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
kafka: {
|
||||
script_path: "",
|
||||
@@ -369,7 +369,7 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
group_id: "",
|
||||
topics: [],
|
||||
filters: [],
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
nats: {
|
||||
script_path: "",
|
||||
@@ -377,7 +377,7 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
nats_resource_path: "",
|
||||
subjects: [],
|
||||
use_jetstream: false,
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
postgres: {
|
||||
script_path: "",
|
||||
@@ -385,21 +385,21 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
postgres_resource_path: "",
|
||||
publication_name: "",
|
||||
replication_slot_name: "",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
mqtt: {
|
||||
script_path: "",
|
||||
is_flow: false,
|
||||
mqtt_resource_path: "",
|
||||
subscribe_topics: [],
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
amqp: {
|
||||
script_path: "",
|
||||
is_flow: false,
|
||||
amqp_resource_path: "",
|
||||
queue_name: "",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
sqs: {
|
||||
script_path: "",
|
||||
@@ -407,7 +407,7 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
queue_url: "",
|
||||
aws_resource_path: "",
|
||||
aws_auth_resource_type: "credentials",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
gcp: {
|
||||
script_path: "",
|
||||
@@ -417,7 +417,7 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
subscription_id: "",
|
||||
delivery_type: "pull",
|
||||
subscription_mode: "create_update",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
azure: {
|
||||
script_path: "",
|
||||
@@ -426,13 +426,13 @@ const triggerTemplates: Record<TriggerType, Record<string, any>> = {
|
||||
azure_mode: "namespace_pull",
|
||||
scope_resource_id: "",
|
||||
subscription_name: "",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
email: {
|
||||
script_path: "",
|
||||
is_flow: false,
|
||||
local_part: "",
|
||||
enabled: false,
|
||||
mode: "disabled",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -8718,7 +8718,7 @@ flow related commands
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- \`-s --silent\` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- \`--tag <tag:string>\` - Override the worker tag the run is dispatched to (e.g. to route it to dev workers instead of the flow's default tag).
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. <flow_path> is the flow's Windmill path (f/x/my_flow), its .flow/__flow folder or its flow.yaml. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--remote\` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* `wmill flow preview` argument resolution and `--step` script loading.
|
||||
*/
|
||||
import { expect, test, describe, beforeEach, afterEach } from "bun:test";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import * as os from "node:os";
|
||||
import { mockServices } from "./mock_services.ts";
|
||||
|
||||
const calls: { fn: string; args: any }[] = [];
|
||||
mockServices({
|
||||
getHubScriptByPath: async (args: any) => {
|
||||
calls.push({ fn: "getHubScriptByPath", args });
|
||||
return {
|
||||
content: "export async function main() { return 'hub' }",
|
||||
language: "deno",
|
||||
lockfile: "hub-lock",
|
||||
};
|
||||
},
|
||||
getScriptByPath: async (args: any) => {
|
||||
calls.push({ fn: "getScriptByPath", args });
|
||||
return { content: "workspace code", language: "bun", lock: "ws-lock" };
|
||||
},
|
||||
getScriptByHash: async (args: any) => {
|
||||
calls.push({ fn: "getScriptByHash", args });
|
||||
return { content: "hashed code", language: "python3", lock: "hash-lock" };
|
||||
},
|
||||
});
|
||||
|
||||
const { resolveFlowFolderArg, loadStepScript } = await import(
|
||||
"../src/commands/flow/flow.ts"
|
||||
);
|
||||
const { setNonDottedPaths } = await import("../src/utils/resource_folders.ts");
|
||||
|
||||
const SEP = path.sep;
|
||||
|
||||
describe("resolveFlowFolderArg", () => {
|
||||
let root: string;
|
||||
let previousCwd: string;
|
||||
|
||||
beforeEach(() => {
|
||||
previousCwd = process.cwd();
|
||||
root = fs.realpathSync(
|
||||
fs.mkdtempSync(path.join(os.tmpdir(), "wmill_flow_preview_")),
|
||||
);
|
||||
fs.mkdirSync(path.join(root, "f", "t", "dotted.flow"), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, "f", "t", "nondotted__flow"), { recursive: true });
|
||||
process.chdir(root);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.chdir(previousCwd);
|
||||
fs.rmSync(root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
test("a Windmill path resolves to its local .flow folder", () => {
|
||||
expect(resolveFlowFolderArg(`f${SEP}t${SEP}dotted`)).toBe(
|
||||
`f${SEP}t${SEP}dotted.flow${SEP}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("a Windmill path resolves to a __flow folder when that is the one on disk", () => {
|
||||
expect(resolveFlowFolderArg(`f${SEP}t${SEP}nondotted`)).toBe(
|
||||
`f${SEP}t${SEP}nondotted__flow${SEP}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("when both folders exist, the configured suffix wins", () => {
|
||||
fs.mkdirSync(path.join(root, "f", "t", "both.flow"), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, "f", "t", "both__flow"), { recursive: true });
|
||||
try {
|
||||
setNonDottedPaths(true);
|
||||
expect(resolveFlowFolderArg(`f${SEP}t${SEP}both`)).toBe(
|
||||
`f${SEP}t${SEP}both__flow${SEP}`,
|
||||
);
|
||||
setNonDottedPaths(false);
|
||||
expect(resolveFlowFolderArg(`f${SEP}t${SEP}both`)).toBe(
|
||||
`f${SEP}t${SEP}both.flow${SEP}`,
|
||||
);
|
||||
} finally {
|
||||
setNonDottedPaths(false);
|
||||
}
|
||||
});
|
||||
|
||||
test("the folder and its flow.yaml keep resolving to the folder", () => {
|
||||
const folder = `f${SEP}t${SEP}dotted.flow${SEP}`;
|
||||
expect(resolveFlowFolderArg(`f${SEP}t${SEP}dotted.flow`)).toBe(folder);
|
||||
expect(resolveFlowFolderArg(folder)).toBe(folder);
|
||||
expect(resolveFlowFolderArg(`${folder}flow.yaml`)).toBe(folder);
|
||||
expect(resolveFlowFolderArg("flow.yaml")).toBe(`.${SEP}`);
|
||||
});
|
||||
|
||||
test("a Windmill path with no local flow folder is refused, naming what was looked for", () => {
|
||||
expect(() => resolveFlowFolderArg(`f${SEP}t${SEP}missing`)).toThrow(
|
||||
`found none of f${SEP}t${SEP}missing.flow, f${SEP}t${SEP}missing__flow`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadStepScript", () => {
|
||||
beforeEach(() => {
|
||||
calls.length = 0;
|
||||
});
|
||||
|
||||
test("a hub path is fetched from the hub, with the hub's lockfile", async () => {
|
||||
const script = await loadStepScript("ws", {
|
||||
path: "hub/29624/slack/send_message_to_channel",
|
||||
});
|
||||
expect(calls).toEqual([
|
||||
{
|
||||
fn: "getHubScriptByPath",
|
||||
args: { path: "hub/29624/slack/send_message_to_channel" },
|
||||
},
|
||||
]);
|
||||
expect(script).toEqual({
|
||||
content: "export async function main() { return 'hub' }",
|
||||
language: "deno",
|
||||
lock: "hub-lock",
|
||||
});
|
||||
});
|
||||
|
||||
test("a workspace path is fetched from the workspace, with its deployed lock", async () => {
|
||||
const script = await loadStepScript("ws", { path: "f/t/helper" });
|
||||
expect(calls).toEqual([
|
||||
{ fn: "getScriptByPath", args: { workspace: "ws", path: "f/t/helper" } },
|
||||
]);
|
||||
expect(script).toEqual({ content: "workspace code", language: "bun", lock: "ws-lock" });
|
||||
});
|
||||
|
||||
test("a pinned hash is fetched by hash", async () => {
|
||||
const script = await loadStepScript("ws", { path: "f/t/helper", hash: "abc" });
|
||||
expect(calls).toEqual([
|
||||
{ fn: "getScriptByHash", args: { workspace: "ws", hash: "abc" } },
|
||||
]);
|
||||
expect(script).toEqual({ content: "hashed code", language: "python3", lock: "hash-lock" });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* `wmill trigger new` scaffolds only fields the backend reads: `request_type`
|
||||
* rather than the deprecated `is_async`, no `requires_auth` (its column was
|
||||
* renamed to `authentication_method`), and `mode` rather than the deprecated
|
||||
* `enabled`.
|
||||
*/
|
||||
import { expect, test, describe } from "bun:test";
|
||||
import { triggerTemplates } from "../src/commands/trigger/trigger.ts";
|
||||
|
||||
describe("trigger new templates", () => {
|
||||
test("the http template has no is_async or requires_auth", () => {
|
||||
const http = triggerTemplates.http;
|
||||
expect(Object.keys(http)).not.toContain("is_async");
|
||||
expect(Object.keys(http)).not.toContain("requires_auth");
|
||||
expect(http.request_type).toBe("sync");
|
||||
expect(http.authentication_method).toBe("none");
|
||||
});
|
||||
|
||||
test("no template scaffolds the deprecated enabled field", () => {
|
||||
const withEnabled = Object.entries(triggerTemplates)
|
||||
.filter(([, template]) => "enabled" in template)
|
||||
.map(([kind]) => kind);
|
||||
expect(withEnabled).toEqual([]);
|
||||
});
|
||||
|
||||
test("templates that scaffolded a disabled trigger still do, through mode", () => {
|
||||
const modes = Object.fromEntries(
|
||||
Object.entries(triggerTemplates).map(([kind, t]) => [kind, t.mode]),
|
||||
);
|
||||
expect(modes).toEqual({
|
||||
http: undefined,
|
||||
websocket: "disabled",
|
||||
kafka: "disabled",
|
||||
nats: "disabled",
|
||||
postgres: "disabled",
|
||||
mqtt: "disabled",
|
||||
amqp: "disabled",
|
||||
sqs: "disabled",
|
||||
gcp: "disabled",
|
||||
azure: "disabled",
|
||||
email: "disabled",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -177,7 +177,7 @@ flow related commands
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- `-s --silent` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- `--tag <tag:string>` - Override the worker tag the run is dispatched to (e.g. to route it to dev workers instead of the flow's default tag).
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. <flow_path> is the flow's Windmill path (f/x/my_flow), its .flow/__flow folder or its flow.yaml. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--remote` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
|
||||
@@ -4048,7 +4048,7 @@ flow related commands
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- \`-s --silent\` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- \`--tag <tag:string>\` - Override the worker tag the run is dispatched to (e.g. to route it to dev workers instead of the flow's default tag).
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`flow preview <flow_path:string>\` - preview a local flow without deploying it. <flow_path> is the flow's Windmill path (f/x/my_flow), its .flow/__flow folder or its flow.yaml. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- \`-d --data <data:string>\` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- \`-s --silent\` - Do not output anything other then the final output. Useful for scripting.
|
||||
- \`--remote\` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
|
||||
@@ -182,7 +182,7 @@ flow related commands
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- `-s --silent` - Do not ouput anything other then the final output. Useful for scripting.
|
||||
- `--tag <tag:string>` - Override the worker tag the run is dispatched to (e.g. to route it to dev workers instead of the flow's default tag).
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `flow preview <flow_path:string>` - preview a local flow without deploying it. <flow_path> is the flow's Windmill path (f/x/my_flow), its .flow/__flow folder or its flow.yaml. Runs the flow definition from local files and uses local PathScripts by default. Pass --step <id> to run only one module in isolation (resolves nested steps inside branchone/branchall/forloopflow/whileloopflow plus the special preprocessor/failure modules; supported step types: rawscript, script, flow).
|
||||
- `-d --data <data:string>` - Inputs specified as a JSON string or a file using @<filename> or stdin using @-. A resource argument is the bare string $res:<path> as its whole value, and a variable argument is the bare string $var:<path> — not an object wrapper keyed on $res/$var, and not a plain path.
|
||||
- `-s --silent` - Do not output anything other then the final output. Useful for scripting.
|
||||
- `--remote` - Use deployed workspace scripts for PathScript steps instead of local files.
|
||||
|
||||
Reference in New Issue
Block a user