1
1
package command
2
2
3
3
import (
4
+ "context"
4
5
"errors"
5
6
"fmt"
6
7
"io"
@@ -89,7 +90,7 @@ func makeComposeUpCmd() *cobra.Command {
89
90
}
90
91
91
92
track .Evt ("Debug Prompted" , P ("loadErr" , loadErr ))
92
- return cli .InteractiveDebugForLoadError (ctx , client , project , loadErr )
93
+ return cli .InteractiveDebugForClientError (ctx , client , project , loadErr )
93
94
}
94
95
95
96
provider , err := newProvider (ctx , loader )
@@ -152,24 +153,8 @@ func makeComposeUpCmd() *cobra.Command {
152
153
}
153
154
154
155
deploy , project , err := cli .ComposeUp (ctx , project , client , provider , upload , mode .Value ())
155
-
156
156
if err != nil {
157
- if ! nonInteractive && strings .Contains (err .Error (), "maximum number of projects" ) {
158
- if projectName , err2 := provider .RemoteProjectName (cmd .Context ()); err2 == nil {
159
- term .Error ("Error:" , prettyError (err ))
160
- if _ , err := cli .InteractiveComposeDown (cmd .Context (), provider , projectName ); err != nil {
161
- term .Debug ("ComposeDown failed:" , err )
162
- printDefangHint ("To deactivate a project, do:" , "compose down --project-name " + projectName )
163
- } else {
164
- printDefangHint ("To try deployment again, do:" , "compose up" )
165
- }
166
- return nil
167
- }
168
- }
169
- if errors .Is (err , types .ErrComposeFileNotFound ) {
170
- printDefangHint ("To start a new project, do:" , "new" )
171
- }
172
- return err
157
+ return handleComposeUpErr (ctx , err , project , provider )
173
158
}
174
159
175
160
if len (deploy .Services ) == 0 {
@@ -188,39 +173,18 @@ func makeComposeUpCmd() *cobra.Command {
188
173
if deploy .Etag != "" {
189
174
tailSource = "deployment ID " + deploy .Etag
190
175
}
191
-
192
176
term .Info ("Tailing logs for" , tailSource , "; press Ctrl+C to detach:" )
193
177
194
178
tailOptions := newTailOptionsForDeploy (deploy .Etag , since , verbose )
195
179
serviceStates , err := cli .TailAndMonitor (ctx , project , provider , time .Duration (waitTimeout )* time .Second , tailOptions )
196
180
if err != nil {
197
- var errDeploymentFailed cliClient.ErrDeploymentFailed
198
- if errors .As (err , & errDeploymentFailed ) {
199
- // Tail got canceled because of deployment failure: prompt to show the debugger
200
- term .Warn (errDeploymentFailed )
201
- debugConfig := cli.DebugConfig {
202
- Deployment : deploy .Etag ,
203
- ModelId : modelId ,
204
- Project : project ,
205
- Provider : provider ,
206
- Since : since ,
207
- }
208
- if errDeploymentFailed .Service != "" {
209
- debugConfig .FailedServices = []string {errDeploymentFailed .Service }
210
- }
211
- if nonInteractive {
212
- printDefangHint ("To debug the deployment, do:" , debugConfig .String ())
213
- } else {
214
- track .Evt ("Debug Prompted" , P ("failedServices" , debugConfig .FailedServices ), P ("etag" , deploy .Etag ), P ("reason" , errDeploymentFailed ))
215
-
216
- // Call the AI debug endpoint using the original command context (not the tail ctx which is canceled)
217
- if nil != cli .InteractiveDebugDeployment (ctx , client , debugConfig ) {
218
- // don't show this defang hint if debugging was successful
219
- tailOptions := newTailOptionsForDeploy (deploy .Etag , since , true )
220
- printDefangHint ("To see the logs of the failed service, do:" , tailOptions .String ())
221
- }
222
- }
223
- }
181
+ handleTailAndMonitorErr (ctx , err , client , cli.DebugConfig {
182
+ Deployment : deploy .Etag ,
183
+ ModelId : modelId ,
184
+ Project : project ,
185
+ Provider : provider ,
186
+ Since : since ,
187
+ })
224
188
return err
225
189
}
226
190
@@ -253,6 +217,59 @@ func makeComposeUpCmd() *cobra.Command {
253
217
return composeUpCmd
254
218
}
255
219
220
+ func handleComposeUpErr (ctx context.Context , err error , project * compose.Project , provider cliClient.Provider ) error {
221
+ if errors .Is (err , types .ErrComposeFileNotFound ) {
222
+ // TODO: generate a compose file based on the current project
223
+ printDefangHint ("To start a new project, do:" , "new" )
224
+ }
225
+
226
+ if nonInteractive {
227
+ return err
228
+ }
229
+
230
+ if strings .Contains (err .Error (), "maximum number of projects" ) {
231
+ if projectName , err2 := provider .RemoteProjectName (ctx ); err2 == nil {
232
+ term .Error ("Error:" , prettyError (err ))
233
+ if _ , err := cli .InteractiveComposeDown (ctx , provider , projectName ); err != nil {
234
+ term .Debug ("ComposeDown failed:" , err )
235
+ printDefangHint ("To deactivate a project, do:" , "compose down --project-name " + projectName )
236
+ } else {
237
+ // TODO: actually do the "compose up" (because that's what the user intended in the first place)
238
+ printDefangHint ("To try deployment again, do:" , "compose up" )
239
+ }
240
+ return nil
241
+ }
242
+ return err
243
+ }
244
+
245
+ term .Error ("Error:" , prettyError (err ))
246
+ track .Evt ("Debug Prompted" , P ("composeErr" , err ))
247
+ return cli .InteractiveDebugForClientError (ctx , client , project , err )
248
+ }
249
+
250
+ func handleTailAndMonitorErr (ctx context.Context , err error , client * cliClient.GrpcClient , debugConfig cli.DebugConfig ) {
251
+ var errDeploymentFailed cliClient.ErrDeploymentFailed
252
+ if errors .As (err , & errDeploymentFailed ) {
253
+ // Tail got canceled because of deployment failure: prompt to show the debugger
254
+ term .Warn (errDeploymentFailed )
255
+ if errDeploymentFailed .Service != "" {
256
+ debugConfig .FailedServices = []string {errDeploymentFailed .Service }
257
+ }
258
+ if nonInteractive {
259
+ printDefangHint ("To debug the deployment, do:" , debugConfig .String ())
260
+ } else {
261
+ track .Evt ("Debug Prompted" , P ("failedServices" , debugConfig .FailedServices ), P ("etag" , debugConfig .Deployment ), P ("reason" , errDeploymentFailed ))
262
+
263
+ // Call the AI debug endpoint using the original command context (not the tail ctx which is canceled)
264
+ if nil != cli .InteractiveDebugDeployment (ctx , client , debugConfig ) {
265
+ // don't show this defang hint if debugging was successful
266
+ tailOptions := newTailOptionsForDeploy (debugConfig .Deployment , debugConfig .Since , true )
267
+ printDefangHint ("To see the logs of the failed service, do:" , tailOptions .String ())
268
+ }
269
+ }
270
+ }
271
+ }
272
+
256
273
func newTailOptionsForDeploy (deployment string , since time.Time , verbose bool ) cli.TailOptions {
257
274
return cli.TailOptions {
258
275
Deployment : deployment ,
@@ -438,7 +455,7 @@ func makeComposeConfigCmd() *cobra.Command {
438
455
}
439
456
440
457
track .Evt ("Debug Prompted" , P ("loadErr" , loadErr ))
441
- return cli .InteractiveDebugForLoadError (ctx , client , project , loadErr )
458
+ return cli .InteractiveDebugForClientError (ctx , client , project , loadErr )
442
459
}
443
460
444
461
provider , err := newProvider (ctx , loader )
0 commit comments