From 62408619dccd3009e2741597010f9e32891234cb Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Wed, 15 Jul 2026 20:15:19 +0000 Subject: [PATCH 1/3] refactor(coderd): drop unused onUpdate callback from waitForProvisionerJob The template builder create-template flow was the only caller and always passed nil. The UI shows an indeterminate loader and no progress is streamed to the client, so the callback is dead code. Remove the parameter and its per-poll invocation; the function still polls and blocks until the job completes or the context expires. --- coderd/templatebuilder_handler.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/coderd/templatebuilder_handler.go b/coderd/templatebuilder_handler.go index 5d4e522ee44..bd931741f47 100644 --- a/coderd/templatebuilder_handler.go +++ b/coderd/templatebuilder_handler.go @@ -459,7 +459,7 @@ func (api *API) templateBuilderCreateTemplate(rw http.ResponseWriter, r *http.Re jobCtx, jobCancel := context.WithTimeout(ctx, templateBuilderCreateTemplateTimeout) defer jobCancel() - completedJob, err := api.waitForProvisionerJob(jobCtx, provisionerJob.ID, nil) + completedJob, err := api.waitForProvisionerJob(jobCtx, provisionerJob.ID) if err != nil { if errors.Is(err, context.DeadlineExceeded) { httpapi.Write(ctx, rw, http.StatusGatewayTimeout, codersdk.Response{ @@ -616,11 +616,9 @@ func (api *API) templateBuilderCreateTemplate(rw http.ResponseWriter, r *http.Re } // waitForProvisionerJob polls until the job completes or the context expires. -// If onUpdate is non-nil, it is called after each poll with the latest job state. func (api *API) waitForProvisionerJob( ctx context.Context, jobID uuid.UUID, - onUpdate func(database.ProvisionerJob), ) (database.ProvisionerJob, error) { initialIntervals := []time.Duration{ 100 * time.Millisecond, @@ -648,10 +646,6 @@ func (api *API) waitForProvisionerJob( return database.ProvisionerJob{}, xerrors.Errorf("get provisioner job: %w", err) } - if onUpdate != nil { - onUpdate(job) - } - if job.CompletedAt.Valid { return job, nil } From 02a94d4af59a46bfe7ddf3e7ab234ff379e52a8f Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Wed, 15 Jul 2026 20:15:49 +0000 Subject: [PATCH 2/3] fix(site/src/pages/TemplateBuilder): stop build progress bar from looping The progress bar animated 0-100% every 5s with an infinite repeat, so it visibly restarted over and over while a template built, making it look broken. Replace the looping fill with a single ease-out fill that decelerates toward 90% and holds until the request resolves and the loader unmounts. DEVEX-593 --- .../pages/TemplateBuilder/BuildingTemplateLoader.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/src/pages/TemplateBuilder/BuildingTemplateLoader.tsx b/site/src/pages/TemplateBuilder/BuildingTemplateLoader.tsx index 8b6c434aefb..55ddd7f9dec 100644 --- a/site/src/pages/TemplateBuilder/BuildingTemplateLoader.tsx +++ b/site/src/pages/TemplateBuilder/BuildingTemplateLoader.tsx @@ -29,8 +29,9 @@ const ICONS: FloatingIcon[] = [ /** * Full-area animated loader displayed while the template builder compose - * API call is in flight. Shows floating icon boxes, a progress bar, and - * an animated "Building your template..." label. + * API call is in flight. Shows floating icon boxes, an indeterminate progress + * bar that fills once and holds, and an animated "Building your template..." + * label. */ export const BuildingTemplateLoader: FC = () => { return ( @@ -74,11 +75,10 @@ export const BuildingTemplateLoader: FC = () => { From c98686b7d12ea2df308a6a936b4893be14e8f696 Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Wed, 15 Jul 2026 20:25:00 +0000 Subject: [PATCH 3/3] fix(site/src/pages/TemplateBuilder): keep loader mounted through navigation When the compose POST resolved, createMutation.isPending flipped to false in the same commit that navigated to the template files page, so the wizard form repainted for a frame before the route changed. Keep the loader mounted while the mutation is pending or succeeded so the form never reflashes during the transition. DEVEX-561 --- site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx b/site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx index 561653e0599..b8ed0727574 100644 --- a/site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx +++ b/site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx @@ -86,7 +86,7 @@ const TemplateBuilderPage: FC = () => { preselectedBase={preselectedBase} onCreateTemplate={handleCreate} createError={createMutation.error} - isCreating={createMutation.isPending} + isCreating={createMutation.isPending || createMutation.isSuccess} onClearCreateError={() => createMutation.reset()} />