Refactor deployment command for better error handling
- Add buffered error channel in NewDeployCommand to prevent goroutine leak - Replace direct error prints with error channel sends in HTTP request, TUI deployment, and progress bar TUI sections - Implement loop to handle errors from the new error channel - Adjust message printing format after successful deployment
- commit
- 10f32d8bddc8f5433b46b6bf97279ac48360730b
- author
- bnema · · 2023-11-13 16:35 UTC
- parent
- 14e5ea4
- signature
- unsigned
1 file · +23 -9
M internal/cli/cmd/deploy.go +23 -9
| @@ -65,6 +65,7 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||
| 65 | 65 | } | |
| 66 | 66 | ||
| 67 | 67 | progressCh := make(chan mvu.ProgressMsg) | |
| 68 | + | errCh := make(chan error, 1) // Buffer of 1 to prevent goroutine leak in case of non-blocking send | |
| 68 | 69 | ||
| 69 | 70 | // Create a progress function to update the progress bar | |
| 70 | 71 | progressReader := &mvu.ProgressReader{ | |
| @@ -87,9 +88,7 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||
| 87 | 88 | go func() { | |
| 88 | 89 | resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push") | |
| 89 | 90 | if err != nil { | |
| 90 | - | fmt.Println("Error sending HTTP request:", err) | |
| 91 | - | // Don't forget to close the channel if there's an error | |
| 92 | - | close(progressCh) | |
| 91 | + | errCh <- fmt.Errorf("error sending HTTP request: %w", err) | |
| 93 | 92 | return | |
| 94 | 93 | } | |
| 95 | 94 | ||
| @@ -116,28 +115,43 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||
| 116 | 115 | // Run the TUI program | |
| 117 | 116 | finalModel, err := mvu.RunDeploymentTUI(client, imageName, targetDomain, port) | |
| 118 | 117 | if err != nil { | |
| 119 | - | fmt.Println("Error running deployment TUI:", err) | |
| 118 | + | errCh <- fmt.Errorf("error running deployment TUI: %w", err) | |
| 120 | 119 | return | |
| 121 | 120 | } | |
| 122 | 121 | ||
| 123 | 122 | // Check if the deployment was successful | |
| 124 | 123 | if !finalModel.DeploymentDone { | |
| 125 | - | fmt.Println("Deployment failed check your configuration and try again.") | |
| 124 | + | errCh <- fmt.Errorf("deployment failed") | |
| 126 | 125 | return | |
| 127 | 126 | } | |
| 128 | 127 | ||
| 129 | 128 | // Print the final message | |
| 130 | - | color.Blue(" Deployment successful!") | |
| 131 | - | fmt.Println(" Your application is now available at:", targetDomain) | |
| 129 | + | color.Blue("Deployment successful!") | |
| 130 | + | fmt.Println("Your application is now available at:", targetDomain) | |
| 132 | 131 | close(progressCh) | |
| 133 | 132 | }() | |
| 134 | - | ||
| 135 | 133 | // Run the progress bar TUI | |
| 136 | 134 | m, err := mvu.RunProgressBarTUI(progressCh) | |
| 137 | 135 | if err != nil { | |
| 138 | - | fmt.Println("Error running progress bar TUI:", err) | |
| 136 | + | errCh <- fmt.Errorf("error running progress bar TUI: %w", err) | |
| 139 | 137 | return | |
| 140 | 138 | } | |
| 139 | + | done := false | |
| 140 | + | ||
| 141 | + | for !done { | |
| 142 | + | select { | |
| 143 | + | case err := <-errCh: | |
| 144 | + | if err != nil { | |
| 145 | + | fmt.Println(err) | |
| 146 | + | return | |
| 147 | + | } | |
| 148 | + | case <-time.After(1 * time.Second): | |
| 149 | + | // Check if the progress bar is done | |
| 150 | + | if m.Done { | |
| 151 | + | done = true | |
| 152 | + | } | |
| 153 | + | } | |
| 154 | + | } | |
| 141 | 155 | ||
| 142 | 156 | // Close the reader | |
| 143 | 157 | err = progressReader.Close() | |
| @@ -65,6 +65,7 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||||
| 65 | } | 65 | } | ||
| 66 | 66 | ||||
| 67 | progressCh := make(chan mvu.ProgressMsg) | 67 | progressCh := make(chan mvu.ProgressMsg) | ||
| 68 | + | errCh := make(chan error, 1) // Buffer of 1 to prevent goroutine leak in case of non-blocking send | |||
| 68 | 69 | ||||
| 69 | // Create a progress function to update the progress bar | 70 | // Create a progress function to update the progress bar | ||
| 70 | progressReader := &mvu.ProgressReader{ | 71 | progressReader := &mvu.ProgressReader{ | ||
| @@ -87,9 +88,7 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||||
| 87 | go func() { | 88 | go func() { | ||
| 88 | resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push") | 89 | resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push") | ||
| 89 | if err != nil { | 90 | if err != nil { | ||
| 90 | - | fmt.Println("Error sending HTTP request:", err) | 91 | + | errCh <- fmt.Errorf("error sending HTTP request: %w", err) |
| 91 | - | // Don't forget to close the channel if there's an error | |||
| 92 | - | close(progressCh) | |||
| 93 | return | 92 | return | ||
| 94 | } | 93 | } | ||
| 95 | 94 | ||||
| @@ -116,28 +115,43 @@ func NewDeployCommand(a *cli.App) *cobra.Command { | |||||
| 116 | // Run the TUI program | 115 | // Run the TUI program | ||
| 117 | finalModel, err := mvu.RunDeploymentTUI(client, imageName, targetDomain, port) | 116 | finalModel, err := mvu.RunDeploymentTUI(client, imageName, targetDomain, port) | ||
| 118 | if err != nil { | 117 | if err != nil { | ||
| 119 | - | fmt.Println("Error running deployment TUI:", err) | 118 | + | errCh <- fmt.Errorf("error running deployment TUI: %w", err) |
| 120 | return | 119 | return | ||
| 121 | } | 120 | } | ||
| 122 | 121 | ||||
| 123 | // Check if the deployment was successful | 122 | // Check if the deployment was successful | ||
| 124 | if !finalModel.DeploymentDone { | 123 | if !finalModel.DeploymentDone { | ||
| 125 | - | fmt.Println("Deployment failed check your configuration and try again.") | 124 | + | errCh <- fmt.Errorf("deployment failed") |
| 126 | return | 125 | return | ||
| 127 | } | 126 | } | ||
| 128 | 127 | ||||
| 129 | // Print the final message | 128 | // Print the final message | ||
| 130 | - | color.Blue(" Deployment successful!") | 129 | + | color.Blue("Deployment successful!") |
| 131 | - | fmt.Println(" Your application is now available at:", targetDomain) | 130 | + | fmt.Println("Your application is now available at:", targetDomain) |
| 132 | close(progressCh) | 131 | close(progressCh) | ||
| 133 | }() | 132 | }() | ||
| 134 | - | ||||
| 135 | // Run the progress bar TUI | 133 | // Run the progress bar TUI | ||
| 136 | m, err := mvu.RunProgressBarTUI(progressCh) | 134 | m, err := mvu.RunProgressBarTUI(progressCh) | ||
| 137 | if err != nil { | 135 | if err != nil { | ||
| 138 | - | fmt.Println("Error running progress bar TUI:", err) | 136 | + | errCh <- fmt.Errorf("error running progress bar TUI: %w", err) |
| 139 | return | 137 | return | ||
| 140 | } | 138 | } | ||
| 139 | + | done := false | |||
| 140 | + | ||||
| 141 | + | for !done { | |||
| 142 | + | select { | |||
| 143 | + | case err := <-errCh: | |||
| 144 | + | if err != nil { | |||
| 145 | + | fmt.Println(err) | |||
| 146 | + | return | |||
| 147 | + | } | |||
| 148 | + | case <-time.After(1 * time.Second): | |||
| 149 | + | // Check if the progress bar is done | |||
| 150 | + | if m.Done { | |||
| 151 | + | done = true | |||
| 152 | + | } | |||
| 153 | + | } | |||
| 154 | + | } | |||
| 141 | 155 | ||||
| 142 | // Close the reader | 156 | // Close the reader | ||
| 143 | err = progressReader.Close() | 157 | err = progressReader.Close() | ||