Skip to content

feat: add --examples and --example flags (#23) - #30

Merged
tbrandenburg merged 1 commit into
mainfrom
fix/issue-23-examples-parameter
Jun 3, 2026
Merged

feat: add --examples and --example flags (#23)#30
tbrandenburg merged 1 commit into
mainfrom
fix/issue-23-examples-parameter

Conversation

@tbrandenburg

Copy link
Copy Markdown
Owner

Summary

New users had no built-in way to discover working workflow examples or bootstrap a starter file. This PR adds a --examples flag to list available examples and --example NAME to print a specific runnable YAML to stdout, following the existing --schema / --version eager-callback pattern.

Root Cause

No discoverability mechanism existed for working workflow YAML. The #1 friction point (vars values are shell commands, not literals) had no inline documentation path.

Changes

File Change
src/flowsh_cli/examples.py New module — single source of truth for simple/medium/sophisticated examples
src/flowsh_cli/cli.py Added --examples (list index) and --example NAME (print YAML) flags
tests/test_workflow_to_harness.py Updated EXPECTED_HELP; added 5 new tests

Testing

  • Type check passes
  • Unit tests pass (104/104)
  • Lint passes
  • All three examples parse and dry-run cleanly
  • Unknown name returns exit 1 with helpful error

Validation

make qa
# 104 passed

Issue

Fixes #23

Implementation Details

Deviations from plan

  • Used two flags (--examples bool + --example NAME str) instead of a single optional-value --examples [name] flag — exactly as recommended in the investigation artifact, since Typer does not support optional-value options natively.

Automated implementation from investigation artifact

New users had no built-in way to discover working workflow examples or
bootstrap a starter file. Add two flags following the existing --schema
/ --version eager-callback pattern.

Changes:
- Add src/flowsh_cli/examples.py: single source of truth for three
  example tiers (simple, medium, sophisticated) with helpers
  examples_index() and example_yaml()
- Add --examples (bool) to cli.py: prints the index and exits
- Add --example NAME (str) to cli.py: prints the named YAML and exits,
  exits 1 with a clear error on unknown names
- Update EXPECTED_HELP constant and add 5 new tests covering listing,
  printing, parse validation, dry-run, and unknown-name error

Fixes #23
@tbrandenburg

Copy link
Copy Markdown
Owner Author

Automated Code Review

Summary

The implementation correctly follows the investigation artifact plan, using two flags (--examples / --example NAME) as recommended. All 104 tests pass and the new examples are validated via dry-run.

Findings

Strengths

  • examples.py is a clean single-source-of-truth module with no external dependencies — zero drift risk.
  • Callback pattern mirrors print_schema / print_version exactly; no new patterns introduced.
  • Medium YAML's colon-in-bash-string correctly handled with single-quoted YAML scalar (run: 'echo ... topic: $TOPIC').
  • Test coverage covers listing, printing, parse validation, dry-run, and error path for all three examples.

Suggestions (non-blocking)

  • src/flowsh_cli/examples.py:72examples_index() uses "\n".join(lines) with trailing \n items per entry; the final blank line depends on how the last entry ends. Consider "\n".join(lines).rstrip() + "\n" for deterministic trailing newline.
  • src/flowsh_cli/cli.py_ = examples and _ = example suppress usage; this matches the existing pattern for version/schema and is fine.

Security

No security concerns — new code is read-only data + print, no file I/O, no subprocess calls.

Checklist

  • Fix addresses root cause from investigation
  • Code follows codebase patterns exactly
  • Tests cover all specified cases (list, named, dry-run, unknown name)
  • No obvious bugs introduced

Self-reviewed by Claude — ready for human review

@tbrandenburg
tbrandenburg merged commit 72bbb54 into main Jun 3, 2026
1 check passed
@tbrandenburg

Copy link
Copy Markdown
Owner Author

PR #30 Review: feat: add --examples and --example flags (#23)

Note: This PR is already MERGED. This is a historical/post-merge review.

Author: tbrandenburg
Branch: fix/issue-23-examples-parameter → main
Additions: +200 lines across 3 files
Deletions: 0


Summary

This PR resolves issue #23 by adding two new CLI flags to the generate command:

  • --examples — prints an index of available named workflow examples and exits
  • --example NAME — prints a specific example's runnable YAML to stdout and exits

The implementation mirrors the existing --schema / --version eager-callback pattern exactly. A new examples.py module acts as the single source of truth for three tiered examples: simple, medium, and sophisticated.


Validation Results

Check Result Details
Lint (ruff check) PASS All checks passed
Format (ruff format) PASS 10 files already formatted
Syntax (py_compile) PASS No errors
Tests (pytest) PASS 104/104 passed (20.67s)
Build (uv build) PASS dist/flowsh_cli-0.6.0 built successfully

Issues Found

Severity Count
Critical 0
High 0
Medium 1
Low / Suggestions 2

Detailed Findings

Medium

M1 — examples_index() trailing newline is non-deterministic
src/flowsh_cli/examples.py:72

def examples_index() -> str:
    lines = ["Available examples (use --example <name> to print runnable YAML):\n"]
    for name, (desc, step_types, _) in EXAMPLES.items():
        lines.append(f"  {name:<14}{desc}")
        lines.append(f"  {'':14}Step types: {step_types}\n")
    return "\n".join(lines)

Each entry's second line ends with \n, so "\n".join(lines) produces "\n\n" between entries and a bare "\n" as the last character — which happens to be correct, but only because the last item in the dict ends with \n. This is fragile: if an entry is re-ordered or the trailing \n is dropped from an entry string, the output format silently changes.

Recommendation:

return "\n".join(lines).rstrip("\n") + "\n"

Or strip trailing \n from each entry string and rely solely on "\n".join() to insert separators.


Low / Suggestions

S1 — Tuple positional indexing on EXAMPLES values
src/flowsh_cli/examples.py:73, src/flowsh_cli/examples.py:88

The dict stores tuple[str, str, str] with positional semantics (desc, step_types, yaml). Positional access ([2]) works but is opaque. A NamedTuple or dataclass would be more readable and safer against accidental reordering, consistent with the project's strict-typing stance.

from typing import NamedTuple

class ExampleEntry(NamedTuple):
    description: str
    step_types: str
    yaml: str

EXAMPLES: dict[str, ExampleEntry] = { ... }

This is a non-blocking suggestion — the current form is concise and works fine for a static data module.

S2 — raise typer.Exit without parentheses in print_examples_index
src/flowsh_cli/cli.py:147

raise typer.Exit raises the class itself, not an instance. Python allows raising class objects (it instantiates them), and this matches the existing pattern for print_schema / print_version, so it is not a bug. However, raise typer.Exit() (with parentheses) is more explicit and conventional. Since the existing pattern is already in the codebase, this is informational only.


Strengths

  • Pattern fidelity. The callback pattern for print_examples_index and print_example is a letter-perfect copy of print_schema and print_version. No new patterns introduced — zero cognitive overhead.
  • Zero external dependencies. examples.py is pure Python data + string formatting. No I/O, no subprocess, no risk of runtime failure.
  • Correct two-flag design. Using --examples (bool) + --example NAME (str) instead of a single optional-value option is the right call since Typer does not natively support optional-value options. Documented explicitly as an intentional deviation.
  • Test coverage is thorough. Five tests cover the full contract: list output, named print, parse validation, dry-run for all three examples, and the error path for an unknown name. This is exactly what the feature requires.
  • Error path is clean. --example typo exits with code 1 and a helpful message naming available examples, matching the project's error-handling standards.
  • YAML content is correct. The medium example correctly single-quotes the bash string containing a colon (run: 'echo "... topic: $TOPIC"') to avoid YAML parsing ambiguity. The sophisticated example's for / parallel combination exercises all supported step types.

Recommendation

APPROVE (retrospective).

This is a clean, minimal, well-tested addition. It follows existing patterns exactly, introduces no new risk surface, and directly resolves the discoverability problem stated in issue #23. The one medium finding (trailing newline fragility) is worth addressing in a follow-up but does not affect current behavior or test results.


Review performed post-merge as historical analysis. All validation run on branch fix/issue-23-examples-parameter at commit 0342410.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an --examples parameter

1 participant