Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion acceptance/sidecar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,11 @@ func TestSidecarsSshSyncFlags(t *testing.T) {
env := testenv.NewTestEnv(t)
env.CircleCIURL = srv.URL

result := binary.RunCLI(t, tt.args, env, env.HomeDir)
// sync runs git operations (branch detection) before opening SSH, so
// the working directory must be a git repo.
workDir := gitrepo.SetupGitRepo(t, "test-org", "test-repo")

result := binary.RunCLI(t, tt.args, env, workDir)

// Commands should fail at SSH key step, not at flag parsing
assert.Assert(t, result.ExitCode != 0, "expected non-zero exit (SSH fails)")
Expand Down
12 changes: 8 additions & 4 deletions internal/cmd/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ func newSidecarSyncCmd() *cobra.Command {
if err != nil {
return err
}
err = sidecar.Sync(cmd.Context(), client, sidecarID, identityFile, authSock, workdir, newStatusFunc(io))
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("sync: %w", err)
}
err = sidecar.Sync(cmd.Context(), client, sidecarID, identityFile, authSock, workdir, cwd, newStatusFunc(io))
if err != nil {
if _, ok := errors.AsType[*sidecar.RemoteBaseError](err); ok {
return &userError{
Expand Down Expand Up @@ -827,7 +831,7 @@ Example:

// Step 4: Sync files to sidecar.
if !skipSync {
if err := sidecarSetupSync(cmd.Context(), client, sidecarID, identityFile, authSock, status); err != nil {
if err := sidecarSetupSync(cmd.Context(), client, sidecarID, identityFile, authSock, dir, status); err != nil {
return err
}
}
Expand Down Expand Up @@ -917,11 +921,11 @@ func sidecarSetupEnsureSSHKey(identityFile string, status iostream.StatusFunc) e
func sidecarSetupSync(
ctx context.Context,
client *circleci.Client,
sidecarID, identityFile, authSock string,
sidecarID, identityFile, authSock, cwd string,
status iostream.StatusFunc,
) error {
status(iostream.LevelStep, "Syncing files to sidecar...")
err := sidecar.Sync(ctx, client, sidecarID, identityFile, authSock, "", status)
err := sidecar.Bootstrap(ctx, client, sidecarID, identityFile, authSock, "", cwd, status)
if err == nil {
return nil
}
Expand Down
26 changes: 24 additions & 2 deletions internal/gitutil/gitutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,39 @@ func MergeBase() (string, error) {
}
}

out, err = exec.Command("git", "rev-parse", "origin/HEAD").Output()
out, err = exec.Command("git", "merge-base", "HEAD", "origin/HEAD").Output()
if err != nil {
return "", fmt.Errorf("resolve remote base: no upstream tracking branch or origin/HEAD found")
}
sha := strings.TrimSpace(string(out))
if sha == "" {
return "", fmt.Errorf("resolve remote base: origin/HEAD is empty")
return "", fmt.Errorf("resolve remote base: could not determine merge-base with origin/HEAD")
}
return sha, nil
}

// HeadRef returns the SHA of the current HEAD commit in the repo at cwd.
func HeadRef(cwd string) (string, error) {
cmd := exec.Command("git", "rev-parse", "HEAD")
cmd.Dir = cwd
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("resolve HEAD: %w", err)
}
sha := strings.TrimSpace(string(out))
if sha == "" {
return "", fmt.Errorf("resolve HEAD: empty output")
}
return sha, nil
}

// IsAncestor returns true if candidate is an ancestor of head in the repo at cwd.
func IsAncestor(candidate, head, cwd string) bool {
cmd := exec.Command("git", "merge-base", "--is-ancestor", candidate, head)
cmd.Dir = cwd
return cmd.Run() == nil
}

// GeneratePatch generates a binary diff from the given base commit,
// including untracked files. It temporarily stages untracked files
// with git add -N and resets them after generating the diff.
Expand Down
8 changes: 5 additions & 3 deletions internal/sidecar/active.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (

// ActiveSidecar holds the currently active sidecar for a project.
type ActiveSidecar struct {
SidecarID string `json:"sidecar_id"`
Name string `json:"name,omitempty"`
Workspace string `json:"workspace,omitempty"`
SidecarID string `json:"sidecar_id"`
Name string `json:"name,omitempty"`
Workspace string `json:"workspace,omitempty"`
BaselineRef string `json:"baseline_ref,omitempty"` // commit SHA checked out on sidecar
BaselineBranch string `json:"baseline_branch,omitempty"` // local branch name at bootstrap time
}

// sidecarFileName returns the name of the sidecar state file. When sessionID
Expand Down
Loading