-
Notifications
You must be signed in to change notification settings - Fork 1
Pipeline Design inline
Shipwright is a CLI orchestration tool with 100+ modular commands, each implemented as standalone bash scripts. The hello command is a simple demonstration command that:
- Outputs exactly "hello world" when invoked
- Provides
--helpand-hflags for usage information - Integrates with Shipwright's established command router pattern
- Must follow strict Bash 3.2 compatibility and error-handling conventions
Codebase Constraints:
- All commands follow the same modular script pattern in
scripts/ - Router dispatch in
scripts/swuses case statements withexec - Mandatory conventions:
set -euo pipefail,VERSIONconstant, ERR trap, no Bash 4.x+ features - Test files mirror command files (e.g.,
sw-hello.sh↔sw-hello-test.sh)
Chosen Approach: Implement hello command as a standalone modular script following Shipwright's established Command Router pattern.
┌─────────────────────────────────────────────────────────────┐
│ Router (scripts/sw) │
│ • Case statement dispatches "hello" to sw-hello.sh │
│ • Uses exec for subprocess execution │
└──────────────────────────┬──────────────────────────────────┘
│ exec → $SCRIPT_DIR/sw-hello.sh
│
┌──────────────────────────▼──────────────────────────────────┐
│ Hello Command (scripts/sw-hello.sh) │
│ • Parses args: --help, -h, or error on unknown args │
│ • Outputs: "hello world" or help text │
│ • Exit codes: 0 (success), 1 (error) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ Test Suite (scripts/sw-hello-test.sh) │
│ • 5 unit tests covering all code paths │
│ • Uses test-helpers.sh (assert_pass/assert_fail) │
│ • Verifies output, help, exit codes, invalid args │
└─────────────────────────────────────────────────────────────┘
Command Interface (bash):
# Input
$ shipwright hello [OPTIONS]
# Options
--help, -h Show usage information
<invalid> Exit with error code 1
# Output
STDOUT: "hello world" (on success)
STDOUT: <help text> (on --help or -h)
STDERR: <error message> (on invalid args)
# Exit Codes
0 Success
1 Invalid arguments or errorRouter Integration:
# In scripts/sw main() function, case statement:
case "$cmd" in
hello)
exec "$SCRIPT_DIR/sw-hello.sh" "$@"
;;
esacUser Input (CLI)
↓
scripts/sw router
├─ Parses command name: "hello"
├─ Loads SCRIPT_DIR
└─ exec → sw-hello.sh with all args
↓
sw-hello.sh
├─ Parses args (--help, -h, or error)
├─ Calls show_help() or main()
└─ Output to STDOUT
↓
User sees output / help / error
| Layer | Responsibility | Error Handling |
|---|---|---|
| Router | Command dispatch | If exec fails: bash returns non-zero (no cleanup needed) |
| Hello Script | Argument parsing, output | Invalid args → show help, exit 1 |
| Test Suite | Verify behavior | Test failures → exit 1, visible in npm test
|
Error Propagation:
- Invalid args at CLI →
show_help()+ exit 1 - Unknown flags → error message + exit 1
- Router exec failure → bash error (rare, caught by ERR trap)
Pros: Single file, no new files to maintain
Cons:
- Violates Shipwright's established 100+ command pattern
- Makes 617-line router harder to read and maintain
- Untestable in isolation
- Creates precedent for code bloat in router
Rejected. Architectural anti-pattern for this codebase.
Pros: Reusable logic if multiple commands need greeting functionality
Cons:
- Over-engineered for a single 67-line command
- Violates YAGNI (You Aren't Gonna Need It)
- Adds unnecessary abstraction layer
- Test setup becomes more complex
Rejected. Premature abstraction; no clear reuse case.
Pros: Type safety, modern language
Cons:
- Breaks from 100% bash codebase
- Requires build step and runtime (Node.js)
- Contradicts Shipwright's bash-only philosophy
- Incompatible with all existing Shipwright patterns
Rejected. Architectural mismatch; Shipwright is pure bash.
-
scripts/sw-hello.sh(67 lines)- Main command script
- Implements
main(),show_help() - Parses args and outputs "hello world"
- Follows script template (VERSION, ERR trap, Bash 3.2 compatible)
-
scripts/sw-hello-test.sh(66 lines)- Unit test suite with 5 tests
- Tests: exact output, help flags, exit codes, invalid args
- Uses
lib/test-helpers.shhelpers - Passes ✅ when
bash scripts/sw-hello-test.shruns
-
scripts/sw(2 lines added)- Router case statement
- Add between existing commands (alphabetically ordered)
- Pattern:
hello) exec "$SCRIPT_DIR/sw-hello.sh" "$@" ;;
-
Internal:
lib/test-helpers.sh(for test harness only, via sourcing) - External: None (bash stdlib only)
- No new npm packages required
| Risk | Severity | Mitigation |
|---|---|---|
| Router registration typo | Low | Manual verification + test execution |
| Output format mismatch | Low | Unit test verifies exact string match |
| Bash 3.2 compatibility | Very Low | No bash 4.x+ features (no ${var,,}, no associative arrays) |
| Exit code semantics | Very Low | Test suite covers both 0 (success) and 1 (error) paths |
| Help flag parsing | Very Low | Tests verify both --help and -h work |
- Script Syntax:
bash -n scripts/sw-hello.shsucceeds (no syntax errors) - Router Registration: Grep confirms
hello)case inscripts/swwith correct exec syntax - Test Suite Passes:
bash scripts/sw-hello-test.shoutputs 5/5 PASS - CLI Integration:
shipwright hellooutputs exactly "hello world\n" - CLI Alias Works:
sw hellooutputs exactly "hello world\n" - Help Flags:
shipwright hello --helpandshipwright hello -hshow usage (non-empty output) - Error Handling:
shipwright hello --invalidexits with code 1 - Bash Conventions Met:
- Script has
set -euo pipefail - Script has
VERSIONconstant matchingpackage.json - Script has ERR trap with proper error message
- No Bash 4.x+ features (case-insensitive expansion, associative arrays, etc.)
- Proper header comment block
- Script has
- Full Test Suite:
npm testpasses with no regressions (all 102 test suites) - Reproducibility: Second run of all validation steps produces identical results
Single Responsibility: Hello command is responsible only for:
- Parsing
--help/-hflags - Outputting "hello world" or help text
- Exit code semantics
Modularity: Command is isolated in its own script; changes to hello do not affect:
- Router logic
- Other commands
- Test harness
- Test helpers
Testability: Command can be tested without:
- Full Shipwright CLI
- Network calls
- External dependencies
- Mock binaries
Extensibility: If greeting commands multiply later (goodbye, greet <name>), they follow identical pattern — no refactoring of hello command needed.
Previous Iteration Failure: "output missing: intake" (14 occurrences, weight: 127834)
- Root cause: Test expected intake stage output; hello command didn't produce it
- Resolution: Hello command is a leaf command, not a pipeline stage — no intake output needed
- Design implication: Keep hello focused; don't conflate with pipeline machinery
Key Learning: Shipwright's distinction between:
-
Commands (leaf):
sw-hello.sh,sw-version.sh— standalone - Stages (composite): pipeline orchestration with intake/plan/build/test/etc.
This design respects that boundary.