detached 03239fa

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 {
8484 return err
8585 }
8686
87- return printPreviewCreateSummary(out, name, ttl, noData)
87+ return waitForPreview(ctx, out, name, ttl, noData)
8888 },
8989 }
9090
@@ -275,13 +275,8 @@ func buildAndPushPreview(ctx context.Context, out io.Writer, previewRef, preview
275275 return nil
276276 }
277277
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
285280 if ttl != "" {
286281 if err := cliWritef(out, "Requested TTL: %s (server config controls actual TTL)\n", ttl); err != nil {
287282 return err
@@ -292,7 +287,49 @@ func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) err
292287 return err
293288 }
294289 }
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+ }
296333 }
297334
298335 func detectGitBranch(ctx context.Context) (string, error) {
@@ -84,7 +84,7 @@ func newPreviewCreateCmd() *cobra.Command {
84 return err84 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 nil275 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 err282 return err
@@ -292,7 +287,49 @@ func printPreviewCreateSummary(out io.Writer, name, ttl string, noData bool) err
292 return err287 return err
293 }288 }
294 }289 }
295- return nil290+
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) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close