Skip to content

fix(minimal): fix race when uploading to worktree - #806

Merged
twitchyliquid64 merged 1 commit into
mainfrom
tom/session-inner
Jul 17, 2026
Merged

fix(minimal): fix race when uploading to worktree#806
twitchyliquid64 merged 1 commit into
mainfrom
tom/session-inner

Conversation

@twitchyliquid64

@twitchyliquid64 twitchyliquid64 commented Jul 17, 2026

Copy link
Copy Markdown
Member

upload_workspace_files does not wait for the daemon to be done unpacking, which can lead to races when test / CI code expects it all to be hunky dory. Fixes some flakes in CI.

Summary by CodeRabbit

  • Bug Fixes
    • Improved workspace file uploads by detecting errors reported while the project archive is unpacked.
    • Uploads now wait for the remote operation to finish before reporting success, providing more reliable failure detection.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

upload_workspace_files now streams through a writable channel, waits for daemon completion, and reports unpack failures delivered through SSH extended data.

Changes

Workspace upload error handling

Layer / File(s) Summary
Upload streaming and unpack validation
crates/minimal/src/client.rs
The upload uses channel.make_writer(), waits for channel closure, inspects ext: 1 extended data, and returns daemon unpack errors when present.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • Issue 804 — The upload completion wait and extended-data error reporting address daemon unpack failures.

Suggested reviewers: 0chroma

Poem

I stream the tar through moonlit air,
Then wait until the daemon’s there.
If unpacking trips, I thump my feet,
And bring the error back complete.
Hop, hop—workspace files repeat!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing a race in workspace/worktree uploads by waiting for daemon unpack completion.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/minimal/src/client.rs`:
- Around line 222-228: Wrap the channel wait loop around channel.wait().await in
a timeout so stalled unpacking or an unclosed daemon channel cannot block
indefinitely. On timeout, drop the channel before returning or propagating the
timeout error, while preserving stderr collection and normal completion
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6f05d99-f98d-4f99-b1a0-bd1a6b6be08b

📥 Commits

Reviewing files that changed from the base of the PR and between e296663 and 5ff8327.

📒 Files selected for processing (1)
  • crates/minimal/src/client.rs

Comment on lines +222 to +228
// Wait for the channel to close to signal that unpacking is done.
let mut err = Vec::new();
while let Some(msg) = channel.wait().await {
if let russh::ChannelMsg::ExtendedData { data, ext: 1 } = msg {
err.extend_from_slice(&data);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file around the cited lines
sed -n '180,260p' crates/minimal/src/client.rs | cat -n

# Find timeout-related policy references in the repo
rg -n "upload|ssh|timeout|deadline|Duration::from|tokio::time::timeout" crates -g '!target' -g '!node_modules'

# Find the channel wait / close pattern elsewhere
rg -n "channel\.wait\(\)\.await|ChannelMsg::ExtendedData|Wait for the channel to close" crates -g '!target' -g '!node_modules'

Repository: gominimal/minimal

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for upload-specific timeout constants/policy in the minimal client and nearby modules
rg -n "UPLOAD_TIMEOUT|upload.*timeout|timeout.*upload|SSH.*timeout|ssh.*timeout|deadline.*upload|workspace file upload" crates/minimal crates/minimald crates -g '!target' -g '!node_modules'

# Inspect the top of the client file for constants and surrounding guidance
sed -n '1,140p' crates/minimal/src/client.rs | cat -n

# Inspect the upload caller to see whether it already wraps this in a timeout
sed -n '960,1010p' crates/minimal/src/lib.rs | cat -n

Repository: gominimal/minimal

Length of output: 8885


Bound the upload-completion wait. channel.wait().await can hang forever if unpacking stalls or the daemon never closes the channel; wrap this loop in a timeout and drop the channel on expiry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/minimal/src/client.rs` around lines 222 - 228, Wrap the channel wait
loop around channel.wait().await in a timeout so stalled unpacking or an
unclosed daemon channel cannot block indefinitely. On timeout, drop the channel
before returning or propagating the timeout error, while preserving stderr
collection and normal completion behavior.

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.

2 participants