From 9e3b955163375652b959fe1f3a63d6d234c86dbb Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Tue, 1 Mar 2022 22:38:35 +0000 Subject: [PATCH 01/18] Add cs jupyter --- pkg/cmd/codespace/jupyter.go | 122 +++++++++++++++++++++++++++++++++++ pkg/cmd/codespace/root.go | 1 + pkg/liveshare/session.go | 26 ++++++++ 3 files changed, 149 insertions(+) create mode 100644 pkg/cmd/codespace/jupyter.go diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go new file mode 100644 index 000000000..64be1c356 --- /dev/null +++ b/pkg/cmd/codespace/jupyter.go @@ -0,0 +1,122 @@ +package codespace + +import ( + "context" + "fmt" + "net" + "strings" + + "github.com/cli/cli/v2/internal/codespaces" + "github.com/cli/cli/v2/pkg/liveshare" + "github.com/spf13/cobra" +) + +type jupyterOptions struct { + codespace string + debug bool + debugFile string + stdio bool +} + +func newJupyterCmd(app *App) *cobra.Command { + var opts jupyterOptions + + jupyterCmd := &cobra.Command{ + Use: "jupyter", + Short: "Open a codespace in JupyterLab", + Args: noArgsConstraint, + RunE: func(cmd *cobra.Command, args []string) error { + return app.Jupyter(cmd.Context(), opts) + }, + } + + return jupyterCmd +} + +func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { + // TODO: Whatever it takes to call StartJupyterServer + // That returns the port and server url + + // TODO: Share this code with ssh.go and logs.go + // We're all doing the same thing: starting agent session + + // Ensure all child tasks (e.g. port forwarding) terminate before return. + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + codespace, err := getOrChooseCodespace(ctx, a.apiClient, opts.codespace) + if err != nil { + return fmt.Errorf("get or choose codespace: %w", err) + } + + // While connecting, ensure in the background that the user has keys installed. + // That lets us report a more useful error message if they don't. + authkeys := make(chan error, 1) + go func() { + authkeys <- checkAuthorizedKeys(ctx, a.apiClient) + }() + + liveshareLogger := noopLogger() + if opts.debug { + debugLogger, err := newFileLogger(opts.debugFile) + if err != nil { + return fmt.Errorf("error creating debug logger: %w", err) + } + defer safeClose(debugLogger, &err) + + liveshareLogger = debugLogger.Logger + a.errLogger.Printf("Debug file located at: %s", debugLogger.Name()) + } + + session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) + if err != nil { + if authErr := <-authkeys; authErr != nil { + return authErr + } + return fmt.Errorf("error connecting to codespace: %w", err) + } + defer safeClose(session, &err) + + a.StartProgressIndicatorWithLabel("Fetching Jupyter Details") + remoteJupyterPort, jupyterServerUrl, err := session.StartJupyterServer(ctx) + a.StopProgressIndicator() + if err != nil { + return fmt.Errorf("error getting jupyter server details: %w", err) + } + + localJupyterServerPort := 0 + // localSSHServerPort := opts.serverPort + // usingCustomPort := localSSHServerPort != 0 // suppress log of command line in Shell + + // Ensure local port is listening before client (Shell) connects. + // Unless the user specifies a server port, localSSHServerPort is 0 + // and thus the client will pick a random port. + listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", localJupyterServerPort)) + if err != nil { + return err + } + defer listen.Close() + localJupyterServerPort = listen.Addr().(*net.TCPAddr).Port + + tunnelClosed := make(chan error, 1) + go func() { + fwd := liveshare.NewPortForwarder(session, "jupyter", remoteJupyterPort, true) + + // TODO: Cancel context when browser closes + tunnelClosed <- fwd.ForwardToListener(ctx, listen) // always non-nil + }() + + // Launch browser and connect to JupyterLab + targetUrl := strings.Replace(jupyterServerUrl, fmt.Sprintf("%d", remoteJupyterPort), fmt.Sprintf("%d", localJupyterServerPort), 1) + err = a.browser.Browse(targetUrl) + if err != nil { + return err + } + + select { + case err := <-tunnelClosed: + return fmt.Errorf("tunnel closed: %w", err) + case <-ctx.Done(): + return nil // success + } +} diff --git a/pkg/cmd/codespace/root.go b/pkg/cmd/codespace/root.go index 5b2c0d8fc..cf72b6a56 100644 --- a/pkg/cmd/codespace/root.go +++ b/pkg/cmd/codespace/root.go @@ -13,6 +13,7 @@ func NewRootCmd(app *App) *cobra.Command { root.AddCommand(newCodeCmd(app)) root.AddCommand(newCreateCmd(app)) root.AddCommand(newDeleteCmd(app)) + root.AddCommand(newJupyterCmd(app)) root.AddCommand(newListCmd(app)) root.AddCommand(newLogsCmd(app)) root.AddCommand(newPortsCmd(app)) diff --git a/pkg/liveshare/session.go b/pkg/liveshare/session.go index b4bc3c16f..57d8e658a 100644 --- a/pkg/liveshare/session.go +++ b/pkg/liveshare/session.go @@ -104,6 +104,32 @@ func (s *Session) StartSSHServer(ctx context.Context) (int, string, error) { return port, response.User, nil } +// StartJupyterServer starts a Juypyter server in the container and returns +// the port on which it listens and the server URL. +func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { + var response struct { + Result bool `json:"result"` + Message string `json:"message"` + Port string `json:"port"` + ServerUrl string `json:"serverUrl"` + } + + if err := s.rpc.do(ctx, "IJupyterServerHostService.GetRunningServers", []string{}, &response); err != nil { + return 0, "", err + } + + if !response.Result { + return 0, "", fmt.Errorf("failed to start jupyter server: %s", response.Message) + } + + port, err := strconv.Atoi(response.Port) + if err != nil { + return 0, "", fmt.Errorf("failed to parse port: %w", err) + } + + return port, response.ServerUrl, nil +} + // heartbeat runs until context cancellation, periodically checking whether there is a // reason to keep the connection alive, and if so, notifying the Live Share host to do so. // Heartbeat ensures it does not send more than one request every "interval" to ratelimit From 3582090fb858d54072b76efb59bb58d993d44b70 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 3 Mar 2022 01:21:35 +0000 Subject: [PATCH 02/18] Fix RPC call --- pkg/liveshare/session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/liveshare/session.go b/pkg/liveshare/session.go index 57d8e658a..898c3b942 100644 --- a/pkg/liveshare/session.go +++ b/pkg/liveshare/session.go @@ -114,7 +114,7 @@ func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { ServerUrl string `json:"serverUrl"` } - if err := s.rpc.do(ctx, "IJupyterServerHostService.GetRunningServers", []string{}, &response); err != nil { + if err := s.rpc.do(ctx, "IJupyterServerHostService.getRunningServers", []string{}, &response); err != nil { return 0, "", err } From aea8a0e0213448db161bfc4e67d0df97ff326b21 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 3 Mar 2022 01:32:12 +0000 Subject: [PATCH 03/18] Clean up code --- pkg/cmd/codespace/jupyter.go | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 64be1c356..484ab7577 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -34,11 +34,7 @@ func newJupyterCmd(app *App) *cobra.Command { } func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { - // TODO: Whatever it takes to call StartJupyterServer - // That returns the port and server url - - // TODO: Share this code with ssh.go and logs.go - // We're all doing the same thing: starting agent session + // TODO: Share liveshare setup code with ssh.go and logs.go // Ensure all child tasks (e.g. port forwarding) terminate before return. ctx, cancel := context.WithCancel(ctx) @@ -78,36 +74,30 @@ func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { defer safeClose(session, &err) a.StartProgressIndicatorWithLabel("Fetching Jupyter Details") - remoteJupyterPort, jupyterServerUrl, err := session.StartJupyterServer(ctx) + jupyterServerPort, jupyterServerUrl, err := session.StartJupyterServer(ctx) a.StopProgressIndicator() if err != nil { return fmt.Errorf("error getting jupyter server details: %w", err) } - localJupyterServerPort := 0 - // localSSHServerPort := opts.serverPort - // usingCustomPort := localSSHServerPort != 0 // suppress log of command line in Shell - // Ensure local port is listening before client (Shell) connects. - // Unless the user specifies a server port, localSSHServerPort is 0 - // and thus the client will pick a random port. - listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", localJupyterServerPort)) + // The client picks a random port when jupyterDestPort is 0. + jupyterDestPort := 0 + listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", jupyterDestPort)) if err != nil { return err } defer listen.Close() - localJupyterServerPort = listen.Addr().(*net.TCPAddr).Port + jupyterDestPort = listen.Addr().(*net.TCPAddr).Port tunnelClosed := make(chan error, 1) go func() { - fwd := liveshare.NewPortForwarder(session, "jupyter", remoteJupyterPort, true) - - // TODO: Cancel context when browser closes + fwd := liveshare.NewPortForwarder(session, "jupyter", jupyterServerPort, true) tunnelClosed <- fwd.ForwardToListener(ctx, listen) // always non-nil }() - // Launch browser and connect to JupyterLab - targetUrl := strings.Replace(jupyterServerUrl, fmt.Sprintf("%d", remoteJupyterPort), fmt.Sprintf("%d", localJupyterServerPort), 1) + // Preserve the server URL's token + targetUrl := strings.Replace(jupyterServerUrl, fmt.Sprintf("%d", jupyterServerPort), fmt.Sprintf("%d", jupyterDestPort), 1) err = a.browser.Browse(targetUrl) if err != nil { return err From fba5fb4eec946f8806d2e170d6733d1ae577821d Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Fri, 4 Mar 2022 00:54:15 +0000 Subject: [PATCH 04/18] Refactor liveshare setup to a new function --- pkg/cmd/codespace/common.go | 32 ++++++++++++++++++++++++++++++++ pkg/cmd/codespace/jupyter.go | 32 +++----------------------------- pkg/cmd/codespace/logs.go | 13 ++----------- pkg/cmd/codespace/ports.go | 6 +++--- pkg/cmd/codespace/ssh.go | 28 +++------------------------- 5 files changed, 43 insertions(+), 68 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index d21f9ff6c..575b95853 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -15,8 +15,10 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/AlecAivazis/survey/v2/terminal" + "github.com/cli/cli/v2/internal/codespaces" "github.com/cli/cli/v2/internal/codespaces/api" "github.com/cli/cli/v2/pkg/iostreams" + "github.com/cli/cli/v2/pkg/liveshare" "github.com/spf13/cobra" "golang.org/x/term" ) @@ -59,6 +61,36 @@ func (a *App) StopProgressIndicator() { a.io.StopProgressIndicator() } +func startSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, func(*error), error) { + // While connecting, ensure in the background that the user has keys installed. + // That lets us report a more useful error message if they don't. + authkeys := make(chan error, 1) + go func() { + authkeys <- checkAuthorizedKeys(ctx, a.apiClient) + }() + + liveshareLogger := noopLogger() + if debug { + debugLogger, err := newFileLogger(debugFile) + if err != nil { + return nil, nil, fmt.Errorf("error creating debug logger: %w", err) + } + defer safeClose(debugLogger, &err) + + liveshareLogger = debugLogger.Logger + a.errLogger.Printf("Debug file located at: %s", debugLogger.Name()) + } + + session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) + if err != nil { + if authErr := <-authkeys; authErr != nil { + return nil, nil, authErr + } + return nil, nil, fmt.Errorf("error connecting to codespace: %w", err) + } + return session, func(e *error) { safeClose(session, e) }, nil +} + //go:generate moq -fmt goimports -rm -skip-ensure -out mock_api.go . apiClient type apiClient interface { GetUser(ctx context.Context) (*api.User, error) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 484ab7577..88f0f0097 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -6,7 +6,6 @@ import ( "net" "strings" - "github.com/cli/cli/v2/internal/codespaces" "github.com/cli/cli/v2/pkg/liveshare" "github.com/spf13/cobra" ) @@ -15,7 +14,6 @@ type jupyterOptions struct { codespace string debug bool debugFile string - stdio bool } func newJupyterCmd(app *App) *cobra.Command { @@ -34,8 +32,6 @@ func newJupyterCmd(app *App) *cobra.Command { } func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { - // TODO: Share liveshare setup code with ssh.go and logs.go - // Ensure all child tasks (e.g. port forwarding) terminate before return. ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -45,33 +41,11 @@ func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { return fmt.Errorf("get or choose codespace: %w", err) } - // While connecting, ensure in the background that the user has keys installed. - // That lets us report a more useful error message if they don't. - authkeys := make(chan error, 1) - go func() { - authkeys <- checkAuthorizedKeys(ctx, a.apiClient) - }() - - liveshareLogger := noopLogger() - if opts.debug { - debugLogger, err := newFileLogger(opts.debugFile) - if err != nil { - return fmt.Errorf("error creating debug logger: %w", err) - } - defer safeClose(debugLogger, &err) - - liveshareLogger = debugLogger.Logger - a.errLogger.Printf("Debug file located at: %s", debugLogger.Name()) - } - - session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) + session, closeSession, err := startSession(ctx, codespace, a, opts.debug, opts.debugFile) if err != nil { - if authErr := <-authkeys; authErr != nil { - return authErr - } - return fmt.Errorf("error connecting to codespace: %w", err) + return err } - defer safeClose(session, &err) + defer closeSession(&err) a.StartProgressIndicatorWithLabel("Fetching Jupyter Details") jupyterServerPort, jupyterServerUrl, err := session.StartJupyterServer(ctx) diff --git a/pkg/cmd/codespace/logs.go b/pkg/cmd/codespace/logs.go index d0a0c233b..b1173debe 100644 --- a/pkg/cmd/codespace/logs.go +++ b/pkg/cmd/codespace/logs.go @@ -41,20 +41,11 @@ func (a *App) Logs(ctx context.Context, codespaceName string, follow bool) (err return fmt.Errorf("get or choose codespace: %w", err) } - authkeys := make(chan error, 1) - go func() { - authkeys <- checkAuthorizedKeys(ctx, a.apiClient) - }() - - session, err := codespaces.ConnectToLiveshare(ctx, a, noopLogger(), a.apiClient, codespace) + session, closeSession, err := startSession(ctx, codespace, a, false, "") if err != nil { - return fmt.Errorf("connecting to codespace: %w", err) - } - defer safeClose(session, &err) - - if err := <-authkeys; err != nil { return err } + defer closeSession(&err) // Ensure local port is listening before client (getPostCreateOutput) connects. listen, err := net.Listen("tcp", "127.0.0.1:0") // arbitrary port diff --git a/pkg/cmd/codespace/ports.go b/pkg/cmd/codespace/ports.go index 094833e30..ad60eeecd 100644 --- a/pkg/cmd/codespace/ports.go +++ b/pkg/cmd/codespace/ports.go @@ -57,11 +57,11 @@ func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdu devContainerCh := getDevContainer(ctx, a.apiClient, codespace) - session, err := codespaces.ConnectToLiveshare(ctx, a, noopLogger(), a.apiClient, codespace) + session, closeSession, err := startSession(ctx, codespace, a, false, "") if err != nil { - return fmt.Errorf("error connecting to codespace: %w", err) + return err } - defer safeClose(session, &err) + defer closeSession(&err) a.StartProgressIndicatorWithLabel("Fetching ports") ports, err := session.GetSharedServers(ctx) diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 726f2152f..b70f33eb1 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -116,38 +116,16 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e ctx, cancel := context.WithCancel(ctx) defer cancel() - // While connecting, ensure in the background that the user has keys installed. - // That lets us report a more useful error message if they don't. - authkeys := make(chan error, 1) - go func() { - authkeys <- checkAuthorizedKeys(ctx, a.apiClient) - }() - codespace, err := getOrChooseCodespace(ctx, a.apiClient, opts.codespace) if err != nil { return fmt.Errorf("get or choose codespace: %w", err) } - liveshareLogger := noopLogger() - if opts.debug { - debugLogger, err := newFileLogger(opts.debugFile) - if err != nil { - return fmt.Errorf("error creating debug logger: %w", err) - } - defer safeClose(debugLogger, &err) - - liveshareLogger = debugLogger.Logger - a.errLogger.Printf("Debug file located at: %s", debugLogger.Name()) - } - - session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) + session, closeSession, err := startSession(ctx, codespace, a, opts.debug, opts.debugFile) if err != nil { - if authErr := <-authkeys; authErr != nil { - return authErr - } - return fmt.Errorf("error connecting to codespace: %w", err) + return err } - defer safeClose(session, &err) + defer closeSession(&err) a.StartProgressIndicatorWithLabel("Fetching SSH Details") remoteSSHServerPort, sshUser, err := session.StartSSHServer(ctx) From 9fd5923b9b929b032bc4156b709eb3e46699ac45 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 14:40:42 -0500 Subject: [PATCH 05/18] Clean up Jupyter code --- pkg/cmd/codespace/jupyter.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 88f0f0097..6ad52824c 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -38,7 +38,7 @@ func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { codespace, err := getOrChooseCodespace(ctx, a.apiClient, opts.codespace) if err != nil { - return fmt.Errorf("get or choose codespace: %w", err) + return err } session, closeSession, err := startSession(ctx, codespace, a, opts.debug, opts.debugFile) @@ -47,31 +47,29 @@ func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { } defer closeSession(&err) - a.StartProgressIndicatorWithLabel("Fetching Jupyter Details") - jupyterServerPort, jupyterServerUrl, err := session.StartJupyterServer(ctx) + a.StartProgressIndicatorWithLabel("Starting JupyterLab on codespace") + serverPort, serverUrl, err := session.StartJupyterServer(ctx) a.StopProgressIndicator() if err != nil { return fmt.Errorf("error getting jupyter server details: %w", err) } - // Ensure local port is listening before client (Shell) connects. - // The client picks a random port when jupyterDestPort is 0. - jupyterDestPort := 0 - listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", jupyterDestPort)) + // Pass 0 to pick a random port + listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", 0)) if err != nil { return err } defer listen.Close() - jupyterDestPort = listen.Addr().(*net.TCPAddr).Port + destPort := listen.Addr().(*net.TCPAddr).Port tunnelClosed := make(chan error, 1) go func() { - fwd := liveshare.NewPortForwarder(session, "jupyter", jupyterServerPort, true) + fwd := liveshare.NewPortForwarder(session, "jupyter", serverPort, true) tunnelClosed <- fwd.ForwardToListener(ctx, listen) // always non-nil }() - // Preserve the server URL's token - targetUrl := strings.Replace(jupyterServerUrl, fmt.Sprintf("%d", jupyterServerPort), fmt.Sprintf("%d", jupyterDestPort), 1) + // Server URL contains an authentication token that must be preserved + targetUrl := strings.Replace(serverUrl, fmt.Sprintf("%d", serverPort), fmt.Sprintf("%d", destPort), 1) err = a.browser.Browse(targetUrl) if err != nil { return err From 33a1b95dbf06b0a42ee2fcf2bc0e5f4ba64d3d6f Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 14:55:29 -0500 Subject: [PATCH 06/18] Fix name of RPC service --- pkg/liveshare/session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/liveshare/session.go b/pkg/liveshare/session.go index 898c3b942..660a9e89c 100644 --- a/pkg/liveshare/session.go +++ b/pkg/liveshare/session.go @@ -114,7 +114,7 @@ func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { ServerUrl string `json:"serverUrl"` } - if err := s.rpc.do(ctx, "IJupyterServerHostService.getRunningServers", []string{}, &response); err != nil { + if err := s.rpc.do(ctx, "IJupyterServerHostService.getRunningServer", []string{}, &response); err != nil { return 0, "", err } From 9874d57d62ab67df77e6fed79e960ba7dd5df133 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 14:55:40 -0500 Subject: [PATCH 07/18] Print JupyterLab URL --- pkg/cmd/codespace/jupyter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 6ad52824c..4cfe17151 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -75,6 +75,8 @@ func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { return err } + fmt.Println(targetUrl) + select { case err := <-tunnelClosed: return fmt.Errorf("tunnel closed: %w", err) From ee1625add21df01d3b85f595d0e3e88476a56501 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 15:26:06 -0500 Subject: [PATCH 08/18] Fix -c option --- pkg/cmd/codespace/jupyter.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 4cfe17151..e49bb5de1 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -10,38 +10,34 @@ import ( "github.com/spf13/cobra" ) -type jupyterOptions struct { - codespace string - debug bool - debugFile string -} - func newJupyterCmd(app *App) *cobra.Command { - var opts jupyterOptions + var codespace string jupyterCmd := &cobra.Command{ Use: "jupyter", Short: "Open a codespace in JupyterLab", Args: noArgsConstraint, RunE: func(cmd *cobra.Command, args []string) error { - return app.Jupyter(cmd.Context(), opts) + return app.Jupyter(cmd.Context(), codespace) }, } + jupyterCmd.Flags().StringVarP(&codespace, "codespace", "c", "", "Name of the codespace") + return jupyterCmd } -func (a *App) Jupyter(ctx context.Context, opts jupyterOptions) error { +func (a *App) Jupyter(ctx context.Context, codespaceName string) error { // Ensure all child tasks (e.g. port forwarding) terminate before return. ctx, cancel := context.WithCancel(ctx) defer cancel() - codespace, err := getOrChooseCodespace(ctx, a.apiClient, opts.codespace) + codespace, err := getOrChooseCodespace(ctx, a.apiClient, codespaceName) if err != nil { return err } - session, closeSession, err := startSession(ctx, codespace, a, opts.debug, opts.debugFile) + session, closeSession, err := startSession(ctx, codespace, a, false, "") if err != nil { return err } From e8e9b586700a791df93dfedd27ad106e45ced7bb Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 16:12:44 -0500 Subject: [PATCH 09/18] Clean up errors --- pkg/cmd/codespace/jupyter.go | 2 +- pkg/liveshare/session.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index e49bb5de1..a044bd229 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -47,7 +47,7 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { serverPort, serverUrl, err := session.StartJupyterServer(ctx) a.StopProgressIndicator() if err != nil { - return fmt.Errorf("error getting jupyter server details: %w", err) + return err } // Pass 0 to pick a random port diff --git a/pkg/liveshare/session.go b/pkg/liveshare/session.go index 2feb33da9..94ab02b23 100644 --- a/pkg/liveshare/session.go +++ b/pkg/liveshare/session.go @@ -77,12 +77,12 @@ func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { } if !response.Result { - return 0, "", fmt.Errorf("failed to start jupyter server: %s", response.Message) + return 0, "", fmt.Errorf("failed to start JupyterLab: %s", response.Message) } port, err := strconv.Atoi(response.Port) if err != nil { - return 0, "", fmt.Errorf("failed to parse port: %w", err) + return 0, "", err } return port, response.ServerUrl, nil From 322fae53b1112a9e969716b4db605cab58c60370 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 16:14:29 -0500 Subject: [PATCH 10/18] Clean up more errors --- pkg/cmd/codespace/common.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 47f9044d4..01023d924 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -73,7 +73,7 @@ func startSession(ctx context.Context, codespace *api.Codespace, a *App, debug b if debug { debugLogger, err := newFileLogger(debugFile) if err != nil { - return nil, nil, fmt.Errorf("error creating debug logger: %w", err) + return nil, nil, err } defer safeClose(debugLogger, &err) @@ -86,7 +86,7 @@ func startSession(ctx context.Context, codespace *api.Codespace, a *App, debug b if authErr := <-authkeys; authErr != nil { return nil, nil, authErr } - return nil, nil, fmt.Errorf("error connecting to codespace: %w", err) + return nil, nil, err } return session, func(e *error) { safeClose(session, e) }, nil } From 4452f378198a44139044989da6e66fe8923e28bd Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 14 Apr 2022 17:10:11 -0500 Subject: [PATCH 11/18] Clarify session helper --- pkg/cmd/codespace/common.go | 3 ++- pkg/cmd/codespace/jupyter.go | 4 ++-- pkg/cmd/codespace/logs.go | 4 ++-- pkg/cmd/codespace/ports.go | 4 ++-- pkg/cmd/codespace/ssh.go | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 01023d924..74043e946 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -61,7 +61,8 @@ func (a *App) StopProgressIndicator() { a.io.StopProgressIndicator() } -func startSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, func(*error), error) { +// Connects to a codespace using Live Share and returns that session along with a function to end it +func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, func(*error), error) { // While connecting, ensure in the background that the user has keys installed. // That lets us report a more useful error message if they don't. authkeys := make(chan error, 1) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index a044bd229..c86c19568 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -37,11 +37,11 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { return err } - session, closeSession, err := startSession(ctx, codespace, a, false, "") + session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer closeSession(&err) + defer endSession(&err) a.StartProgressIndicatorWithLabel("Starting JupyterLab on codespace") serverPort, serverUrl, err := session.StartJupyterServer(ctx) diff --git a/pkg/cmd/codespace/logs.go b/pkg/cmd/codespace/logs.go index 71c289e3c..4a4152717 100644 --- a/pkg/cmd/codespace/logs.go +++ b/pkg/cmd/codespace/logs.go @@ -41,11 +41,11 @@ func (a *App) Logs(ctx context.Context, codespaceName string, follow bool) (err return err } - session, closeSession, err := startSession(ctx, codespace, a, false, "") + session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer closeSession(&err) + defer endSession(&err) // Ensure local port is listening before client (getPostCreateOutput) connects. listen, err := net.Listen("tcp", "127.0.0.1:0") // arbitrary port diff --git a/pkg/cmd/codespace/ports.go b/pkg/cmd/codespace/ports.go index eba7731fd..e70b66921 100644 --- a/pkg/cmd/codespace/ports.go +++ b/pkg/cmd/codespace/ports.go @@ -55,11 +55,11 @@ func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdu devContainerCh := getDevContainer(ctx, a.apiClient, codespace) - session, closeSession, err := startSession(ctx, codespace, a, false, "") + session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer closeSession(&err) + defer endSession(&err) a.StartProgressIndicatorWithLabel("Fetching ports") ports, err := session.GetSharedServers(ctx) diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 6b060acb9..4aad28974 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -121,11 +121,11 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e return err } - session, closeSession, err := startSession(ctx, codespace, a, opts.debug, opts.debugFile) + session, endSession, err := startLiveShareSession(ctx, codespace, a, opts.debug, opts.debugFile) if err != nil { return err } - defer closeSession(&err) + defer endSession(&err) a.StartProgressIndicatorWithLabel("Fetching SSH Details") remoteSSHServerPort, sshUser, err := session.StartSSHServer(ctx) From 3216d1bb3aa3af4b703988bf4da06a37a670b6e9 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 21 Apr 2022 14:29:30 -0700 Subject: [PATCH 12/18] Remove function return --- pkg/cmd/codespace/common.go | 10 +++++----- pkg/cmd/codespace/jupyter.go | 4 ++-- pkg/cmd/codespace/logs.go | 4 ++-- pkg/cmd/codespace/ports.go | 4 ++-- pkg/cmd/codespace/ssh.go | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 74043e946..04a7b62ec 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -62,7 +62,7 @@ func (a *App) StopProgressIndicator() { } // Connects to a codespace using Live Share and returns that session along with a function to end it -func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, func(*error), error) { +func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, error) { // While connecting, ensure in the background that the user has keys installed. // That lets us report a more useful error message if they don't. authkeys := make(chan error, 1) @@ -74,7 +74,7 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App if debug { debugLogger, err := newFileLogger(debugFile) if err != nil { - return nil, nil, err + return nil, err } defer safeClose(debugLogger, &err) @@ -85,11 +85,11 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) if err != nil { if authErr := <-authkeys; authErr != nil { - return nil, nil, authErr + return nil, authErr } - return nil, nil, err + return nil, err } - return session, func(e *error) { safeClose(session, e) }, nil + return session, nil } //go:generate moq -fmt goimports -rm -skip-ensure -out mock_api.go . apiClient diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index c86c19568..defb8330a 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -37,11 +37,11 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { return err } - session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") + session, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer endSession(&err) + defer session.Close() a.StartProgressIndicatorWithLabel("Starting JupyterLab on codespace") serverPort, serverUrl, err := session.StartJupyterServer(ctx) diff --git a/pkg/cmd/codespace/logs.go b/pkg/cmd/codespace/logs.go index 4a4152717..5bd4b2c5c 100644 --- a/pkg/cmd/codespace/logs.go +++ b/pkg/cmd/codespace/logs.go @@ -41,11 +41,11 @@ func (a *App) Logs(ctx context.Context, codespaceName string, follow bool) (err return err } - session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") + session, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer endSession(&err) + defer session.Close() // Ensure local port is listening before client (getPostCreateOutput) connects. listen, err := net.Listen("tcp", "127.0.0.1:0") // arbitrary port diff --git a/pkg/cmd/codespace/ports.go b/pkg/cmd/codespace/ports.go index e70b66921..cbe4e8389 100644 --- a/pkg/cmd/codespace/ports.go +++ b/pkg/cmd/codespace/ports.go @@ -55,11 +55,11 @@ func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdu devContainerCh := getDevContainer(ctx, a.apiClient, codespace) - session, endSession, err := startLiveShareSession(ctx, codespace, a, false, "") + session, err := startLiveShareSession(ctx, codespace, a, false, "") if err != nil { return err } - defer endSession(&err) + defer session.Close() a.StartProgressIndicatorWithLabel("Fetching ports") ports, err := session.GetSharedServers(ctx) diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 4aad28974..2549a8b06 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -121,11 +121,11 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e return err } - session, endSession, err := startLiveShareSession(ctx, codespace, a, opts.debug, opts.debugFile) + session, err := startLiveShareSession(ctx, codespace, a, opts.debug, opts.debugFile) if err != nil { return err } - defer endSession(&err) + defer session.Close() a.StartProgressIndicatorWithLabel("Fetching SSH Details") remoteSSHServerPort, sshUser, err := session.StartSSHServer(ctx) From f21faca03e8190327a9516a79d2ee3e2f2432790 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 21 Apr 2022 14:56:55 -0700 Subject: [PATCH 13/18] Resolve feedback --- pkg/cmd/codespace/jupyter.go | 4 ++-- pkg/liveshare/session.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index defb8330a..eef785731 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -47,7 +47,7 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { serverPort, serverUrl, err := session.StartJupyterServer(ctx) a.StopProgressIndicator() if err != nil { - return err + return fmt.Errorf("failed to start JupyterLab server: %w", err) } // Pass 0 to pick a random port @@ -71,7 +71,7 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { return err } - fmt.Println(targetUrl) + fmt.Fprintln(a.io.Out, targetUrl) select { case err := <-tunnelClosed: diff --git a/pkg/liveshare/session.go b/pkg/liveshare/session.go index 94ab02b23..e2648c1c8 100644 --- a/pkg/liveshare/session.go +++ b/pkg/liveshare/session.go @@ -73,7 +73,7 @@ func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { } if err := s.rpc.do(ctx, "IJupyterServerHostService.getRunningServer", []string{}, &response); err != nil { - return 0, "", err + return 0, "", fmt.Errorf("failed to invoke JupyterLab RPC: %w", err) } if !response.Result { @@ -82,7 +82,7 @@ func (s *Session) StartJupyterServer(ctx context.Context) (int, string, error) { port, err := strconv.Atoi(response.Port) if err != nil { - return 0, "", err + return 0, "", fmt.Errorf("failed to parse JupyterLab port: %w", err) } return port, response.ServerUrl, nil From fce69a53505132a0e309c2981db405796c9c0670 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 21 Apr 2022 15:03:07 -0700 Subject: [PATCH 14/18] Add context to errors --- pkg/cmd/codespace/common.go | 6 +++--- pkg/cmd/codespace/jupyter.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 04a7b62ec..15a86445b 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -74,7 +74,7 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App if debug { debugLogger, err := newFileLogger(debugFile) if err != nil { - return nil, err + return nil, fmt.Errorf("couldn't create file logger: %w", err) } defer safeClose(debugLogger, &err) @@ -85,9 +85,9 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) if err != nil { if authErr := <-authkeys; authErr != nil { - return nil, authErr + return nil, fmt.Errorf("failed to connect to Live Share: %w", authErr) } - return nil, err + return nil, fmt.Errorf("failed to connect to Live Share: %w", err) } return session, nil } diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index eef785731..280eeb410 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -68,7 +68,7 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { targetUrl := strings.Replace(serverUrl, fmt.Sprintf("%d", serverPort), fmt.Sprintf("%d", destPort), 1) err = a.browser.Browse(targetUrl) if err != nil { - return err + return fmt.Errorf("failed to open JupyterLab in browser: %w", err) } fmt.Fprintln(a.io.Out, targetUrl) From 6ddd3360d8d5ba0d75c1954fd01f9ab0b78acab8 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 28 Apr 2022 18:10:14 +0000 Subject: [PATCH 15/18] Update auth error message --- pkg/cmd/codespace/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 15a86445b..6eaf04a32 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -85,7 +85,7 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) if err != nil { if authErr := <-authkeys; authErr != nil { - return nil, fmt.Errorf("failed to connect to Live Share: %w", authErr) + return nil, fmt.Errorf("failed to fetch authorization keys: %w", authErr) } return nil, fmt.Errorf("failed to connect to Live Share: %w", err) } From ceba2c896b88eb6ad66629498c4f961454c94cdb Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 28 Apr 2022 18:38:46 +0000 Subject: [PATCH 16/18] Use safeClose instead of Close --- pkg/cmd/codespace/jupyter.go | 4 ++-- pkg/cmd/codespace/logs.go | 2 +- pkg/cmd/codespace/ports.go | 2 +- pkg/cmd/codespace/ssh.go | 7 +++---- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/codespace/jupyter.go b/pkg/cmd/codespace/jupyter.go index 280eeb410..77bedb301 100644 --- a/pkg/cmd/codespace/jupyter.go +++ b/pkg/cmd/codespace/jupyter.go @@ -27,7 +27,7 @@ func newJupyterCmd(app *App) *cobra.Command { return jupyterCmd } -func (a *App) Jupyter(ctx context.Context, codespaceName string) error { +func (a *App) Jupyter(ctx context.Context, codespaceName string) (err error) { // Ensure all child tasks (e.g. port forwarding) terminate before return. ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -41,7 +41,7 @@ func (a *App) Jupyter(ctx context.Context, codespaceName string) error { if err != nil { return err } - defer session.Close() + defer safeClose(session, &err) a.StartProgressIndicatorWithLabel("Starting JupyterLab on codespace") serverPort, serverUrl, err := session.StartJupyterServer(ctx) diff --git a/pkg/cmd/codespace/logs.go b/pkg/cmd/codespace/logs.go index 5bd4b2c5c..b3289de41 100644 --- a/pkg/cmd/codespace/logs.go +++ b/pkg/cmd/codespace/logs.go @@ -45,7 +45,7 @@ func (a *App) Logs(ctx context.Context, codespaceName string, follow bool) (err if err != nil { return err } - defer session.Close() + defer safeClose(session, &err) // Ensure local port is listening before client (getPostCreateOutput) connects. listen, err := net.Listen("tcp", "127.0.0.1:0") // arbitrary port diff --git a/pkg/cmd/codespace/ports.go b/pkg/cmd/codespace/ports.go index cbe4e8389..9bbe28f79 100644 --- a/pkg/cmd/codespace/ports.go +++ b/pkg/cmd/codespace/ports.go @@ -59,7 +59,7 @@ func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdu if err != nil { return err } - defer session.Close() + defer safeClose(session, &err) a.StartProgressIndicatorWithLabel("Fetching ports") ports, err := session.GetSharedServers(ctx) diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 2549a8b06..633bbe252 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -125,7 +125,7 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e if err != nil { return err } - defer session.Close() + defer safeClose(session, &err) a.StartProgressIndicatorWithLabel("Fetching SSH Details") remoteSSHServerPort, sshUser, err := session.StartSSHServer(ctx) @@ -187,11 +187,10 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e } } -func (a *App) printOpenSSHConfig(ctx context.Context, opts sshOptions) error { +func (a *App) printOpenSSHConfig(ctx context.Context, opts sshOptions) (err error) { ctx, cancel := context.WithCancel(ctx) defer cancel() - var err error var csList []*api.Codespace if opts.codespace == "" { a.StartProgressIndicatorWithLabel("Fetching codespaces") @@ -232,7 +231,7 @@ func (a *App) printOpenSSHConfig(ctx context.Context, opts sshOptions) error { if err != nil { result.err = fmt.Errorf("error connecting to codespace: %w", err) } else { - defer session.Close() + defer safeClose(session, &err) _, result.user, err = session.StartSSHServer(ctx) if err != nil { From 8aa132e6c6798a7906b382f6177af314e993efa0 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 28 Apr 2022 18:42:05 +0000 Subject: [PATCH 17/18] Use named return values --- pkg/cmd/codespace/common.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 6eaf04a32..001a7b7a4 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -62,7 +62,7 @@ func (a *App) StopProgressIndicator() { } // Connects to a codespace using Live Share and returns that session along with a function to end it -func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (*liveshare.Session, error) { +func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (session *liveshare.Session, err error) { // While connecting, ensure in the background that the user has keys installed. // That lets us report a more useful error message if they don't. authkeys := make(chan error, 1) @@ -82,14 +82,14 @@ func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App a.errLogger.Printf("Debug file located at: %s", debugLogger.Name()) } - session, err := codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) + session, err = codespaces.ConnectToLiveshare(ctx, a, liveshareLogger, a.apiClient, codespace) if err != nil { if authErr := <-authkeys; authErr != nil { return nil, fmt.Errorf("failed to fetch authorization keys: %w", authErr) } return nil, fmt.Errorf("failed to connect to Live Share: %w", err) } - return session, nil + return } //go:generate moq -fmt goimports -rm -skip-ensure -out mock_api.go . apiClient From 3526d25a1e5e1728fb9b8e92da32c6d12f1c75f6 Mon Sep 17 00:00:00 2001 From: JP Ungaretti Date: Thu, 28 Apr 2022 20:55:43 +0000 Subject: [PATCH 18/18] Remove mention of function --- pkg/cmd/codespace/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/codespace/common.go b/pkg/cmd/codespace/common.go index 001a7b7a4..b86151093 100644 --- a/pkg/cmd/codespace/common.go +++ b/pkg/cmd/codespace/common.go @@ -61,7 +61,7 @@ func (a *App) StopProgressIndicator() { a.io.StopProgressIndicator() } -// Connects to a codespace using Live Share and returns that session along with a function to end it +// Connects to a codespace using Live Share and returns that session func startLiveShareSession(ctx context.Context, codespace *api.Codespace, a *App, debug bool, debugFile string) (session *liveshare.Session, err error) { // While connecting, ensure in the background that the user has keys installed. // That lets us report a more useful error message if they don't.