Fix guest session cwd preflight scripts

Guest session cwd and command preflight helpers were emitting literal
`\\n` separators, so the guest shell saw malformed one-line scripts and
could fail `preflight_cwd` even when `/root/repo` already existed.

Replace those builders with real newlines, and fix the nearby attach
helper commands that were making the same mistake.

Add a small daemon guest-SSH seam so workspace preparation and session
start can share a fake backend in tests, then cover the regression with
an end-to-end daemon test for `PrepareVMWorkspace` followed by
`StartGuestSession` on `/root/repo`.

Validation: `GOCACHE=/tmp/banger-gocache go test ./internal/daemon` and
`GOCACHE=/tmp/banger-gocache go test ./...`.
This commit is contained in:
Thales Maciel 2026-04-13 18:26:19 -03:00
parent 37c4c091ec
commit 5e26fd7544
No known key found for this signature in database
GPG key ID: 33112E6833C34679
4 changed files with 296 additions and 49 deletions

View file

@ -14,7 +14,6 @@ import (
"time"
"banger/internal/api"
"banger/internal/guest"
"banger/internal/model"
"banger/internal/system"
)
@ -77,10 +76,10 @@ func (d *Daemon) prepareVMWorkspaceLocked(ctx context.Context, vm model.VMRecord
return model.WorkspacePrepareResult{}, fmt.Errorf("workspace mode %q does not support git submodules in %s (%s); use --mode full_copy", mode, spec.RepoRoot, strings.Join(spec.Submodules, ", "))
}
address := net.JoinHostPort(vm.Runtime.GuestIP, "22")
if err := guest.WaitForSSH(ctx, address, d.config.SSHKeyPath, 250*time.Millisecond); err != nil {
if err := d.waitForGuestSSH(ctx, address, 250*time.Millisecond); err != nil {
return model.WorkspacePrepareResult{}, fmt.Errorf("guest ssh unavailable: %w", err)
}
client, err := guest.Dial(ctx, address, d.config.SSHKeyPath)
client, err := d.dialGuest(ctx, address)
if err != nil {
return model.WorkspacePrepareResult{}, fmt.Errorf("dial guest ssh: %w", err)
}
@ -179,7 +178,7 @@ func inspectWorkspaceRepo(ctx context.Context, rawPath, branchName, fromRef stri
}, nil
}
func importWorkspaceRepoToGuest(ctx context.Context, client *guest.Client, spec workspaceRepoSpec, guestPath string, mode model.WorkspacePrepareMode) error {
func importWorkspaceRepoToGuest(ctx context.Context, client guestSSHClient, spec workspaceRepoSpec, guestPath string, mode model.WorkspacePrepareMode) error {
switch mode {
case model.WorkspacePrepareModeFullCopy:
var copyLog bytes.Buffer