mirror of
https://github.com/bahdotsh/wrkflw.git
synced 2026-05-18 05:05:35 +02:00
A review pass over the screens-4-8 branch turned up three things that survived the last round. Dealing with them in one commit. It turns out the curl preview and the real dispatcher were computing the workflow URL segment *differently*. The preview stripped `.yml`/`.yaml` and url-encoded the full user input — subdir and all. The dispatcher ran `Path::new(name).file_stem()` (which drops the subdir) and then unconditionally re-appended `.yml`, turning a `ci.yaml` workflow into a `ci.yaml.yml` URL that has never worked. So the preview was lying about what Enter would send, the dispatcher had a latent `.yml.yml` bug for any input that already carried the extension, and `.yaml` files silently became `.yml` URLs on dispatch. Consolidate both paths behind a single `wrkflw_github::workflow_dispatch_path_segment` helper. Drops any subdir prefix, preserves an existing `.yml`/`.yaml`, appends `.yml` only when absent. The preview and the dispatcher now produce byte-identical URL segments for the same input — and the `.yaml.yml` footgun is gone as a side effect. The second one: `a` (select-all) and `r` (queue+run) were gated only on `!app.running`, not on the active tab. Pressing `a` on the DAG or Trigger or Secrets tabs — outside edit mode — would silently flip every workflow to `selected` behind the user's back. Same story for `r` queuing an execution. Add the tab gate. Please don't do that. The third one: `trigger_in_flight` was cleared by a trailing `store(false)` at the end of the spawned dispatch task. Fine on normal return. A panic inside reqwest or either SDK would skip right past it, strand the flag at `true`, and lock the Trigger tab into a permanent "already in flight" state until the TUI restarts. Wrap the flag in an `InFlightGuard` RAII so Drop is what actually clears it. Normal return, early return, *and* unwinding all land it back at `false`. While at it: dropped the `DEBUG: Shift+R pressed` log spam that was sprinkled through the reset handlers, deleted the now-dead `strip_yaml_suffix` helper, and cleaned up a stray `test_edge_cases.rs` debug script that had been sitting in the repo root. Eight new tests across the two crates cover the shared URL helper, the preview/dispatcher identity, \`.yaml\` round-trip, and the in-flight guard on both normal drop and \`catch_unwind\` panic paths. cargo fmt + clippy -D warnings + full workspace test suite clean.
Wrkflw Crates
This directory contains the Rust crates that make up the wrkflw workspace.
Crate Structure
| Crate | Purpose |
|---|---|
| wrkflw | CLI binary and library entry point |
| executor | Workflow execution engine (Docker, Podman, emulation) |
| parser | Workflow file parsing and JSON Schema validation |
| evaluator | Structural evaluation of workflow files |
| validators | Validation rules for jobs, steps, triggers, matrix |
| runtime | Container management and emulation runtime |
| ui | Terminal user interface (ratatui-based) |
| models | Shared data structures (ValidationResult, GitLab models) |
| matrix | Matrix expansion (include, exclude, fail-fast) |
| secrets | Secrets management with multiple providers and encryption |
| github | GitHub API integration (list/trigger workflows) |
| gitlab | GitLab API integration (trigger pipelines) |
| logging | Thread-safe in-memory logging for TUI/CLI |
| utils | Workflow file detection and fd redirection helpers |
Building
# Build everything
cargo build
# Build a specific crate
cargo build -p wrkflw-executor
Testing
# Run all tests
cargo test
# Run tests for a specific crate
cargo test -p wrkflw-executor
Each crate has its own Cargo.toml with dependencies managed through workspace inheritance in the root Cargo.toml.