X Tutup
Skip to content

Commit 10ad854

Browse files
authored
Merge pull request cli#154 from github/jg/fix-ctx-error
ghcs create/ssh: fix ctx cancellation errors & fix todo for X11 forwarding
2 parents 45a9715 + 0f72e3d commit 10ad854

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

cmd/ghcs/create.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,16 @@ func create(opts *createOptions) error {
105105
return nil
106106
}
107107

108+
// showStatus polls the codespace for a list of post create states and their status. It will keep polling
109+
// until all states have finished. Once all states have finished, we poll once more to check if any new
110+
// states have been introduced and stop polling otherwise.
108111
func showStatus(ctx context.Context, log *output.Logger, apiClient *api.API, user *api.User, codespace *api.Codespace) error {
109112
var lastState codespaces.PostCreateState
110113
var breakNextState bool
111114

112115
finishedStates := make(map[string]bool)
113116
ctx, stopPolling := context.WithCancel(ctx)
117+
defer stopPolling()
114118

115119
poller := func(states []codespaces.PostCreateState) {
116120
var inProgress bool
@@ -153,7 +157,12 @@ func showStatus(ctx context.Context, log *output.Logger, apiClient *api.API, use
153157
}
154158
}
155159

156-
if err := codespaces.PollPostCreateStates(ctx, log, apiClient, user, codespace, poller); err != nil {
160+
err := codespaces.PollPostCreateStates(ctx, log, apiClient, user, codespace, poller)
161+
if err != nil {
162+
if errors.Is(err, context.Canceled) && breakNextState {
163+
return nil // we cancelled the context to stop polling, we can ignore the error
164+
}
165+
157166
return fmt.Errorf("failed to poll state changes from codespace: %v", err)
158167
}
159168

internal/codespaces/ssh.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ func NewRemoteCommand(ctx context.Context, tunnelPort int, destination, command
3232
// an interactive shell) over ssh.
3333
func newSSHCommand(ctx context.Context, port int, dst, command string) (*exec.Cmd, []string) {
3434
connArgs := []string{"-p", strconv.Itoa(port), "-o", "NoHostAuthenticationForLocalhost=yes"}
35-
// TODO(adonovan): eliminate X11 and X11Trust flags where unneeded.
36-
cmdArgs := append([]string{dst, "-X", "-Y", "-C"}, connArgs...) // X11, X11Trust, Compression
3735

36+
cmdArgs := []string{dst, "-C"} // Always use Compression
37+
if command == "" {
38+
// if we are in a shell send X11 and X11Trust
39+
cmdArgs = append(cmdArgs, "-X", "-Y")
40+
}
41+
42+
cmdArgs = append(cmdArgs, connArgs...)
3843
if command != "" {
3944
cmdArgs = append(cmdArgs, command)
4045
}

internal/codespaces/states.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ type PostCreateState struct {
3939
func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, user *api.User, codespace *api.Codespace, poller func([]PostCreateState)) error {
4040
token, err := apiClient.GetCodespaceToken(ctx, user.Login, codespace.Name)
4141
if err != nil {
42-
return fmt.Errorf("getting codespace token: %v", err)
42+
return fmt.Errorf("getting codespace token: %w", err)
4343
}
4444

4545
session, err := ConnectToLiveshare(ctx, log, apiClient, user.Login, token, codespace)
4646
if err != nil {
47-
return fmt.Errorf("connect to Live Share: %v", err)
47+
return fmt.Errorf("connect to Live Share: %w", err)
4848
}
4949

5050
// Ensure local port is listening before client (getPostCreateOutput) connects.
@@ -57,7 +57,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u
5757
log.Println("Fetching SSH Details...")
5858
remoteSSHServerPort, sshUser, err := session.StartSSHServer(ctx)
5959
if err != nil {
60-
return fmt.Errorf("error getting ssh server details: %v", err)
60+
return fmt.Errorf("error getting ssh server details: %w", err)
6161
}
6262

6363
tunnelClosed := make(chan error, 1) // buffered to avoid sender stuckness
@@ -75,12 +75,12 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u
7575
return ctx.Err()
7676

7777
case err := <-tunnelClosed:
78-
return fmt.Errorf("connection failed: %v", err)
78+
return fmt.Errorf("connection failed: %w", err)
7979

8080
case <-t.C:
8181
states, err := getPostCreateOutput(ctx, localPort, codespace, sshUser)
8282
if err != nil {
83-
return fmt.Errorf("get post create output: %v", err)
83+
return fmt.Errorf("get post create output: %w", err)
8484
}
8585

8686
poller(states)
@@ -96,13 +96,13 @@ func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Cod
9696
stdout := new(bytes.Buffer)
9797
cmd.Stdout = stdout
9898
if err := cmd.Run(); err != nil {
99-
return nil, fmt.Errorf("run command: %v", err)
99+
return nil, fmt.Errorf("run command: %w", err)
100100
}
101101
var output struct {
102102
Steps []PostCreateState `json:"steps"`
103103
}
104104
if err := json.Unmarshal(stdout.Bytes(), &output); err != nil {
105-
return nil, fmt.Errorf("unmarshal output: %v", err)
105+
return nil, fmt.Errorf("unmarshal output: %w", err)
106106
}
107107

108108
return output.Steps, nil

0 commit comments

Comments
 (0)
X Tutup