fj run watch/view --exit-status to gate CI on run conclusion #135

Closed
opened 2026-06-11 00:57:41 +00:00 by stephen · 0 comments
Owner

Task

Add --exit-status to fj run watch and fj run view: when set, exit non-zero if the run's terminal conclusion is anything but success/skipped. Default stays 0 so existing piping is unaffected.

  • Key the exit status off the whole-run conclusion (view.state.run.status), not just the watched job 0, so a failure in job 1 is not reported as success. This mirrors the existing --log-failed "don't hide a failure behind a green job 0" reasoning at src/cli/workflow_run.rs:160.
  • Update docs/gh-to-fj.md:109 to map gh run watch --exit-status -> fj run watch --exit-status.

Source: rasterstate/fj#125.

Priority

p1. "Kick a workflow and gate the pipeline on green" is the core CI primitive: fj run watch "$RUN" --exit-status || exit 1. Today that || exit 1 is dead code, since watch returns Ok(()) on a failed run and the process exits 0, so the deploy proceeds on red. That is a silent correctness trap, not just a missing convenience, which is what makes it a blocker.

Reason

watch declares the run finished and returns Ok(()) regardless of conclusion (src/cli/workflow_run.rs:410); view likewise prints the summary and returns Ok(()) (:261-278). The process exit path returns 1 only on Err (src/main.rs:62-63), so a red run is indistinguishable from a green one to a script. The only workaround is fj run view N --json plus grepping .status/.jobs[].status, exactly the brittle scripting the --json work set out to remove.

Acceptance

  • fj run watch <run> --exit-status exits non-zero when the run's terminal conclusion is not success/skipped.
  • fj run view <run> --exit-status does the same over already-fetched data.
  • Exit status reflects the whole run's conclusion, not just job 0.
  • Default (no flag) still exits 0 on a finished run, preserving current piping.
  • docs/gh-to-fj.md records the flag.
  • Test coverage for success, failure, and cancelled terminal states driving the exit code.
  • cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all pass.

Dependencies

None directly. Distinct from rasterstate/fj#123 (failed API calls); this is a successful command observing a failed run. Pairs with rasterstate/fj#129 to make "trigger + gate" work end to end.

Size

S

## Task Add `--exit-status` to `fj run watch` and `fj run view`: when set, exit non-zero if the run's terminal conclusion is anything but `success`/`skipped`. Default stays `0` so existing piping is unaffected. - Key the exit status off the whole-run conclusion (`view.state.run.status`), not just the watched job 0, so a failure in job 1 is not reported as success. This mirrors the existing `--log-failed` "don't hide a failure behind a green job 0" reasoning at `src/cli/workflow_run.rs:160`. - Update `docs/gh-to-fj.md:109` to map `gh run watch --exit-status` -> `fj run watch --exit-status`. Source: rasterstate/fj#125. ## Priority p1. "Kick a workflow and gate the pipeline on green" is the core CI primitive: `fj run watch "$RUN" --exit-status || exit 1`. Today that `|| exit 1` is dead code, since `watch` returns `Ok(())` on a failed run and the process exits `0`, so the deploy proceeds on red. That is a silent correctness trap, not just a missing convenience, which is what makes it a blocker. ## Reason `watch` declares the run finished and returns `Ok(())` regardless of conclusion (`src/cli/workflow_run.rs:410`); `view` likewise prints the summary and returns `Ok(())` (`:261-278`). The process exit path returns `1` only on `Err` (`src/main.rs:62-63`), so a red run is indistinguishable from a green one to a script. The only workaround is `fj run view N --json` plus grepping `.status`/`.jobs[].status`, exactly the brittle scripting the `--json` work set out to remove. ## Acceptance - [ ] `fj run watch <run> --exit-status` exits non-zero when the run's terminal conclusion is not `success`/`skipped`. - [ ] `fj run view <run> --exit-status` does the same over already-fetched data. - [ ] Exit status reflects the whole run's conclusion, not just job 0. - [ ] Default (no flag) still exits `0` on a finished run, preserving current piping. - [ ] `docs/gh-to-fj.md` records the flag. - [ ] Test coverage for success, failure, and cancelled terminal states driving the exit code. - [ ] `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test --all` pass. ## Dependencies None directly. Distinct from rasterstate/fj#123 (failed API calls); this is a successful command observing a failed run. Pairs with rasterstate/fj#129 to make "trigger + gate" work end to end. ## Size S
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rasterstate/fj#135
No description provided.