flowsh-cli 0.7.2__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/PKG-INFO +3 -3
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/README.md +2 -2
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/pyproject.toml +1 -1
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/__init__.py +1 -1
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/cli.py +23 -3
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/examples.py +3 -0
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/models.py +5 -0
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/render.py +4 -3
- {flowsh_cli-0.7.2 → flowsh_cli-0.8.0}/src/flowsh_cli/__main__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowsh-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Generate Bash harness scripts from workflow YAML files.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -26,7 +26,7 @@ Use it when you want a small, reproducible way to encode a workflow once and rer
|
|
|
26
26
|
uvx flowsh-cli path/to/workflows.yml
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
That reads the workflow YAML at the path you provide and writes
|
|
29
|
+
That reads the workflow YAML at the path you provide and writes harness scripts to the current working directory.
|
|
30
30
|
|
|
31
31
|
In this repository, the example workflow file lives at `.made/workflows.yml`.
|
|
32
32
|
|
|
@@ -82,7 +82,7 @@ workflows:
|
|
|
82
82
|
run: echo "$ITEM"
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Harness paths are derived from workflow ids. `wf_example` becomes
|
|
85
|
+
Harness paths are derived from workflow ids. `wf_example` becomes `example.sh` in the current working directory.
|
|
86
86
|
|
|
87
87
|
## Step Types
|
|
88
88
|
|
|
@@ -10,7 +10,7 @@ Use it when you want a small, reproducible way to encode a workflow once and rer
|
|
|
10
10
|
uvx flowsh-cli path/to/workflows.yml
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
That reads the workflow YAML at the path you provide and writes
|
|
13
|
+
That reads the workflow YAML at the path you provide and writes harness scripts to the current working directory.
|
|
14
14
|
|
|
15
15
|
In this repository, the example workflow file lives at `.made/workflows.yml`.
|
|
16
16
|
|
|
@@ -66,7 +66,7 @@ workflows:
|
|
|
66
66
|
run: echo "$ITEM"
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
Harness paths are derived from workflow ids. `wf_example` becomes
|
|
69
|
+
Harness paths are derived from workflow ids. `wf_example` becomes `example.sh` in the current working directory.
|
|
70
70
|
|
|
71
71
|
## Step Types
|
|
72
72
|
|
|
@@ -91,6 +91,14 @@ def generate(
|
|
|
91
91
|
is_eager=True,
|
|
92
92
|
),
|
|
93
93
|
] = None,
|
|
94
|
+
output: Annotated[
|
|
95
|
+
Path | None,
|
|
96
|
+
typer.Option(
|
|
97
|
+
"--output",
|
|
98
|
+
metavar="PATH",
|
|
99
|
+
help="Write generated script to PATH. Only valid when generating a single workflow.",
|
|
100
|
+
),
|
|
101
|
+
] = None,
|
|
94
102
|
) -> None:
|
|
95
103
|
"""Generate Bash harnesses from workflow YAML."""
|
|
96
104
|
|
|
@@ -102,7 +110,14 @@ def generate(
|
|
|
102
110
|
try:
|
|
103
111
|
workflows = parse_workflows(workflow_yaml)
|
|
104
112
|
selected = select_workflows(workflows, workflow)
|
|
105
|
-
|
|
113
|
+
if output is not None and len(selected) != 1:
|
|
114
|
+
print(
|
|
115
|
+
"ERROR: --output requires exactly one workflow "
|
|
116
|
+
"(use --workflow or ensure the file contains only one workflow)",
|
|
117
|
+
file=sys.stderr,
|
|
118
|
+
)
|
|
119
|
+
raise typer.Exit(1)
|
|
120
|
+
write_harnesses(selected, dry_run=dry_run, force=force, output_path=output)
|
|
106
121
|
except WorkflowParseError as error:
|
|
107
122
|
print(f"ERROR: {error}", file=sys.stderr)
|
|
108
123
|
raise typer.Exit(1) from error
|
|
@@ -159,8 +174,13 @@ def print_example(value: str | None) -> None:
|
|
|
159
174
|
raise typer.Exit
|
|
160
175
|
|
|
161
176
|
|
|
162
|
-
def write_harnesses(
|
|
163
|
-
|
|
177
|
+
def write_harnesses(
|
|
178
|
+
workflows: list[Workflow], *, dry_run: bool, force: bool, output_path: Path | None = None
|
|
179
|
+
) -> None:
|
|
180
|
+
output_paths = [
|
|
181
|
+
(workflow, output_path if output_path is not None else harness_path(workflow))
|
|
182
|
+
for workflow in workflows
|
|
183
|
+
]
|
|
164
184
|
|
|
165
185
|
if dry_run:
|
|
166
186
|
for workflow, output_path in output_paths:
|
|
@@ -6,9 +6,12 @@ EXAMPLES: dict[str, tuple[str, str, str]] = {
|
|
|
6
6
|
"Vars + sequential bash steps",
|
|
7
7
|
"vars, bash",
|
|
8
8
|
"""\
|
|
9
|
+
description: Simple workflow examples for demonstration purposes
|
|
10
|
+
|
|
9
11
|
workflows:
|
|
10
12
|
- id: wf_simple
|
|
11
13
|
name: Simple example — vars and bash
|
|
14
|
+
description: Captures today's date and prints a greeting via sequential bash steps.
|
|
12
15
|
|
|
13
16
|
steps:
|
|
14
17
|
- type: vars
|
|
@@ -199,7 +199,11 @@ class WorkflowParam(StrictModel):
|
|
|
199
199
|
class Workflow(StrictModel):
|
|
200
200
|
id: str
|
|
201
201
|
name: str
|
|
202
|
+
description: str | None = None
|
|
202
203
|
params: list[WorkflowParam] = []
|
|
204
|
+
enabled: bool = True
|
|
205
|
+
schedule: str | None = None
|
|
206
|
+
shellScriptPath: str | None = None
|
|
203
207
|
steps: list[Step]
|
|
204
208
|
|
|
205
209
|
@field_validator("id")
|
|
@@ -227,6 +231,7 @@ class Workflow(StrictModel):
|
|
|
227
231
|
|
|
228
232
|
|
|
229
233
|
class WorkflowFile(StrictModel):
|
|
234
|
+
description: str | None = None
|
|
230
235
|
workflows: list[Workflow]
|
|
231
236
|
|
|
232
237
|
@field_validator("workflows")
|
|
@@ -16,7 +16,7 @@ from flowsh_cli.models import (
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def harness_path(workflow: Workflow) -> Path:
|
|
19
|
-
return Path(
|
|
19
|
+
return Path(f"{workflow.id.removeprefix('wf_')}.sh")
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def render_harness(workflow: Workflow) -> str:
|
|
@@ -326,8 +326,9 @@ def _render_step_body(step: Step) -> list[str]:
|
|
|
326
326
|
]
|
|
327
327
|
)
|
|
328
328
|
if step.expandPrompt:
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
_prompt_no_code = re.sub(r"```.*?```", "", step.prompt, flags=re.DOTALL)
|
|
330
|
+
braced = re.findall(r"\$\{([A-Z_][A-Z0-9_]*)\}", _prompt_no_code)
|
|
331
|
+
bare = re.findall(r"\$([A-Z_][A-Z0-9_]*)(?!\w)", _prompt_no_code)
|
|
331
332
|
seen: dict[str, None] = {}
|
|
332
333
|
for var in braced + bare:
|
|
333
334
|
seen[var] = None
|
|
File without changes
|