feat(cli): poll for preview deployment and print URL
- commit
- 03239fa8554b7f367242d05dd5fbe51d4b698dea
- author
- brice · · 2026-03-18 18:43 UTC
- committer
- brice · · 2026-03-18 17:28 UTC
- parent
- ae4cf2c
- signature
- unsigned
1 file · +46 -9
M internal/adapters/in/cli/preview.go +46 -9
| @@ -84,7 +84,7 @@ func newPreviewCreateCmd() *cobra.Command { | |||
| 84 | 84 | return err | |
| 85 | 85 | } | |
| 86 | 86 | ||
| 87 | - | return printPreviewCreateSummary(out, name, ttl, noData) | |
| 87 | + | return waitForPreview(ctx, out, name, ttl, noData) | |
| 88 | 88 | }, | |
| 89 | 89 | } | |
| 90 | 90 | ||
| @@ -275,13 +275,8 @@ func buildAndPushPreview(ctx context.Context, out io.Writer, previewRef, preview | |||
| 275 | 275 | return nil | |
| 276 | 276 | } | |
| 277 | 277 | ||
| 278 | - | func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) error { | |
| 279 | - | if err := cliWriteLine(out, cliRenderSuccess("Push complete")); err != nil { | |
| 280 | - | return err | |
| 281 | - | } | |
| 282 | - | if err := cliWritef(out, "Preview %s will be created by the server's autopreview handler.\n", name); err != nil { | |
| 283 | - | return err | |
| 284 | - | } | |
| 278 | + | func waitForPreview(ctx context.Context, out io.Writer, name, ttl string, noData bool) error { | |
| 279 | + | // Print TTL/no-data info upfront | |
| 285 | 280 | if ttl != "" { | |
| 286 | 281 | if err := cliWritef(out, "Requested TTL: %s (server config controls actual TTL)\n", ttl); err != nil { | |
| 287 | 282 | return err | |
| @@ -292,7 +287,49 @@ func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) err | |||
| 292 | 287 | return err | |
| 293 | 288 | } | |
| 294 | 289 | } | |
| 295 | - | return nil | |
| 290 | + | ||
| 291 | + | client, isRemote := GetRemoteClient() | |
| 292 | + | if !isRemote { | |
| 293 | + | return cliWriteLine(out, cliRenderSuccess(fmt.Sprintf("Push complete. Preview %q will be created by the server (use --remote to poll status).", name))) | |
| 294 | + | } | |
| 295 | + | ||
| 296 | + | if err := cliWriteLine(out, "Waiting for preview deployment..."); err != nil { | |
| 297 | + | return err | |
| 298 | + | } | |
| 299 | + | ||
| 300 | + | // Poll every 2s for up to 3 minutes | |
| 301 | + | ticker := time.NewTicker(2 * time.Second) | |
| 302 | + | defer ticker.Stop() | |
| 303 | + | timeout := time.After(3 * time.Minute) | |
| 304 | + | ||
| 305 | + | for { | |
| 306 | + | select { | |
| 307 | + | case <-ctx.Done(): | |
| 308 | + | return ctx.Err() | |
| 309 | + | case <-timeout: | |
| 310 | + | return cliWriteLine(out, cliRenderInfo("Preview is still deploying. Check status with: gordon preview list --remote")) | |
| 311 | + | case <-ticker.C: | |
| 312 | + | p, err := client.GetPreview(ctx, name) | |
| 313 | + | if err != nil { | |
| 314 | + | continue // not found yet, keep polling | |
| 315 | + | } | |
| 316 | + | switch p.Status { | |
| 317 | + | case "running": | |
| 318 | + | scheme := "http" | |
| 319 | + | if p.HTTPS { | |
| 320 | + | scheme = "https" | |
| 321 | + | } | |
| 322 | + | previewURL := fmt.Sprintf("%s://%s", scheme, p.Domain) | |
| 323 | + | if err := cliWriteLine(out, cliRenderSuccess("Preview deployed")); err != nil { | |
| 324 | + | return err | |
| 325 | + | } | |
| 326 | + | return cliWriteLine(out, cliRenderMeta("URL:", previewURL)) | |
| 327 | + | case "failed": | |
| 328 | + | return fmt.Errorf("preview deployment failed") | |
| 329 | + | } | |
| 330 | + | // status is "deploying", keep polling | |
| 331 | + | } | |
| 332 | + | } | |
| 296 | 333 | } | |
| 297 | 334 | ||
| 298 | 335 | func detectGitBranch(ctx context.Context) (string, error) { | |
| @@ -84,7 +84,7 @@ func newPreviewCreateCmd() *cobra.Command { | |||||
| 84 | return err | 84 | return err | ||
| 85 | } | 85 | } | ||
| 86 | 86 | ||||
| 87 | - | return printPreviewCreateSummary(out, name, ttl, noData) | 87 | + | return waitForPreview(ctx, out, name, ttl, noData) |
| 88 | }, | 88 | }, | ||
| 89 | } | 89 | } | ||
| 90 | 90 | ||||
| @@ -275,13 +275,8 @@ func buildAndPushPreview(ctx context.Context, out io.Writer, previewRef, preview | |||||
| 275 | return nil | 275 | return nil | ||
| 276 | } | 276 | } | ||
| 277 | 277 | ||||
| 278 | - | func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) error { | 278 | + | func waitForPreview(ctx context.Context, out io.Writer, name, ttl string, noData bool) error { |
| 279 | - | if err := cliWriteLine(out, cliRenderSuccess("Push complete")); err != nil { | 279 | + | // Print TTL/no-data info upfront |
| 280 | - | return err | |||
| 281 | - | } | |||
| 282 | - | if err := cliWritef(out, "Preview %s will be created by the server's autopreview handler.\n", name); err != nil { | |||
| 283 | - | return err | |||
| 284 | - | } | |||
| 285 | if ttl != "" { | 280 | if ttl != "" { | ||
| 286 | if err := cliWritef(out, "Requested TTL: %s (server config controls actual TTL)\n", ttl); err != nil { | 281 | if err := cliWritef(out, "Requested TTL: %s (server config controls actual TTL)\n", ttl); err != nil { | ||
| 287 | return err | 282 | return err | ||
| @@ -292,7 +287,49 @@ func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) err | |||||
| 292 | return err | 287 | return err | ||
| 293 | } | 288 | } | ||
| 294 | } | 289 | } | ||
| 295 | - | return nil | 290 | + | |
| 291 | + | client, isRemote := GetRemoteClient() | |||
| 292 | + | if !isRemote { | |||
| 293 | + | return cliWriteLine(out, cliRenderSuccess(fmt.Sprintf("Push complete. Preview %q will be created by the server (use --remote to poll status).", name))) | |||
| 294 | + | } | |||
| 295 | + | ||||
| 296 | + | if err := cliWriteLine(out, "Waiting for preview deployment..."); err != nil { | |||
| 297 | + | return err | |||
| 298 | + | } | |||
| 299 | + | ||||
| 300 | + | // Poll every 2s for up to 3 minutes | |||
| 301 | + | ticker := time.NewTicker(2 * time.Second) | |||
| 302 | + | defer ticker.Stop() | |||
| 303 | + | timeout := time.After(3 * time.Minute) | |||
| 304 | + | ||||
| 305 | + | for { | |||
| 306 | + | select { | |||
| 307 | + | case <-ctx.Done(): | |||
| 308 | + | return ctx.Err() | |||
| 309 | + | case <-timeout: | |||
| 310 | + | return cliWriteLine(out, cliRenderInfo("Preview is still deploying. Check status with: gordon preview list --remote")) | |||
| 311 | + | case <-ticker.C: | |||
| 312 | + | p, err := client.GetPreview(ctx, name) | |||
| 313 | + | if err != nil { | |||
| 314 | + | continue // not found yet, keep polling | |||
| 315 | + | } | |||
| 316 | + | switch p.Status { | |||
| 317 | + | case "running": | |||
| 318 | + | scheme := "http" | |||
| 319 | + | if p.HTTPS { | |||
| 320 | + | scheme = "https" | |||
| 321 | + | } | |||
| 322 | + | previewURL := fmt.Sprintf("%s://%s", scheme, p.Domain) | |||
| 323 | + | if err := cliWriteLine(out, cliRenderSuccess("Preview deployed")); err != nil { | |||
| 324 | + | return err | |||
| 325 | + | } | |||
| 326 | + | return cliWriteLine(out, cliRenderMeta("URL:", previewURL)) | |||
| 327 | + | case "failed": | |||
| 328 | + | return fmt.Errorf("preview deployment failed") | |||
| 329 | + | } | |||
| 330 | + | // status is "deploying", keep polling | |||
| 331 | + | } | |||
| 332 | + | } | |||
| 296 | } | 333 | } | ||
| 297 | 334 | ||||
| 298 | func detectGitBranch(ctx context.Context) (string, error) { | 335 | func detectGitBranch(ctx context.Context) (string, error) { | ||