fix(git): stream push output to avoid spurious 30s timeout (#963)#1531
fix(git): stream push output to avoid spurious 30s timeout (#963)#1531ousamabenyounes wants to merge 1 commit into
Conversation
📊 Automated PR Analysis
SummaryFixes a critical timeout issue where Review Checklist
Linked issues: #963 Analyzed automatically by wshm · This is an automated analysis, not a human review. |
689e2e4 to
f579fa8
Compare
|
Hello @ousamabenyounes , thanks for addressing this. The fix is not correct because loose of filtering, to fix this we need to use run_streaming + FilterMode::Streaming existing infrastructure that has been added in 0.37.0 for streaming commands. |
## Problem (rtk-ai#963) `rtk git push` reportedly times out: users see `bash tool terminated command after exceeding timeout 30000 ms` while plain `git push` to the same remote completes fine. P1-critical because every Claude Code git push goes through rtk. ## Root cause `run_push` used `cmd.stdin(Stdio::inherit()).output()`. `Command::output()` captures both stdout and stderr until the child exits. Git push prints its progress (`Counting objects` / `Compressing objects` / `Writing objects`) to stderr and may prompt for SSH passphrases or HTTPS credentials. With stderr captured, Claude Code's bash tool saw zero output for 30+ seconds and killed the command — exactly the 30000 ms message in the issue. ## Fix Rewrite `run_push` on top of the streaming infrastructure that already exists for this exact purpose (`stream::run_streaming` + `FilterMode::Streaming`, added in 0.37.0). A custom `GitPushStreamFilter` implements `StreamFilter`: - `feed_line` drops the high-volume progress phases (Enumerating / Counting / Compressing / Writing objects, Delta compression, Total) and passes every other line through (remote: messages, To <url>, ref updates, errors). Lines flow to the terminal as git emits them, so the bash tool never sees a 30s silence. - `on_exit` appends a compact `ok <ref>` / `ok (up-to-date)` summary on success, preserving the token-saving payoff of the previous filter. - Stdin is inherited (StdinMode::Inherit) so SSH passphrase and HTTPS credential prompts still reach the user. Tracking now records the actual raw output and the filtered output (rather than empty strings). ## Test plan - [x] `cargo fmt --all -- --check` - [x] `cargo clippy --all-targets -- -D warnings` — clean - [x] `cargo test --all` — 1876 passed, 0 failed, 6 ignored - Six new unit tests cover: progress-prefix drop, up-to-date summary, remote message passthrough, no-summary-on-failure, first-ref-wins, verbose-output token savings (>=40% on a representative payload). - End-to-end behaviour cannot be exercised hermetically (the bug is wall-clock + stream buffering against a real network remote), but the underlying `run_streaming` path is already covered by existing tests in `src/core/stream.rs`. ## Notes - Behaviour change: users now see git's native output line-by-line (with progress phases stripped) plus a final `ok <ref>` summary, instead of just the compact summary. This matches plain `git push` more closely and is what the issue reporter expects. - No regression for other filters: `run_pull`, `run_fetch`, `run_clone` are untouched; only `run_push` is modified. Closes rtk-ai#963 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Vibe Coded by Ousama Ben Younes_ _Developed With Ora Studio (Claude Code)_ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f579fa8 to
a402997
Compare
|
Thanks for the steer @aeppling — rewritten on top of
Six new unit tests in
|
Problem (#963)
`rtk git push` reportedly times out: users see `bash tool terminated command after exceeding timeout 30000 ms` while plain `git push` to the same remote completes fine. P1-critical because every Claude Code git push goes through rtk.
Root cause
`run_push` used `cmd.stdin(Stdio::inherit()).output()`. `Command::output()` captures both stdout and stderr until the child exits.
Git push prints its progress (`Counting objects` / `Compressing objects` / `Writing objects`) to stderr and may prompt for SSH passphrases or HTTPS credentials. With stderr captured nothing reached the terminal until the process finished, so:
The original code traded interactivity for a one-line compact summary (`ok master`). Push output is small — a handful of lines — so the saving was negligible while the cost (timeout, hidden prompts) was severe.
Fix
Inherit all three streams and use `cmd.status()` instead of `.output()`. Progress and auth prompts now flow through in real time, the bash tool keeps seeing output, and the exit code propagates via the existing `exit_code_from_status` helper. Tracking still records the invocation; raw/filtered token counts deliberately collapse to 0 because we don't capture.
Test plan
Notes
Closes #963
🤖 Generated with Claude Code
Vibe Coded by Ousama Ben Younes
Developed With Ora Studio (Claude Code)