fix: stop the template builder build progress bar from looping - #27276
Merged
jeremyruppel merged 2 commits intoJul 16, 2026
Merged
Conversation
…erJob 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.
…ping 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
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
jeremyruppel
marked this pull request as ready for review
July 15, 2026 20:36
aslilac
approved these changes
Jul 15, 2026
aqandrew
approved these changes
Jul 15, 2026
jeremyruppel
deleted the
jeremy/devex-593-stop-the-build-progress-bar-from-looping-repeatedly
branch
July 16, 2026 13:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
The template builder's "Building your template" loader had a progress bar that
animated 0→100% every 5s with an infinite repeat, so it visibly restarted over
and over while a template built. It looked broken and was frustrating to watch.
This replaces the looping fill with a single ease-out fill that decelerates
toward 90% and holds until the request resolves and the loader unmounts.
Since the loader is intentionally indeterminate and no progress is streamed to
the browser, this also removes the now-dead
onUpdatecallback plumbing fromthe backend
waitForProvisionerJob(its only caller passednil).Resolves DEVEX-593.
Screen.Recording.2026-07-15.at.4.27.32.PM.mov
Commits
refactor(coderd): drop unused onUpdate callback from waitForProvisionerJobfix(site/src/pages/TemplateBuilder): stop build progress bar from loopingTesting
go build ./coderd/passes with the reducedwaitForProvisionerJobsignature.pages/TemplateBuilder/BuildingTemplateLoadershows the bar fillonce and hold, with no restart.
Implementation plan
DEVEX-593: Stop the build progress bar from looping repeatedly
Problem
While the template builder composes and imports a template, the FE shows
BuildingTemplateLoader. Its progress bar animates from 0% to 100% over 5swith
repeat: Number.POSITIVE_INFINITY, so it visibly restarts over and over.Users report this looks broken and is frustrating to watch while waiting.
Decision (scope)
Minimal fix only: stop the loop, plus remove the now-dead
onUpdateplumbing from the backend. Since the UI is intentionally indeterminate and no
progress signal is streamed, the callback serves no purpose and should be
deleted rather than left as dead code.
Why not "real sync" now
POST /api/v2/templatebuilder/compose/templateis a single blocking request.It composes, bundles, inserts the provisioner job, then calls
waitForProvisionerJob(jobCtx, provisionerJob.ID, nil)and only responds oncethe job completes.
onUpdatecallback runs server-side only. Nothing is streamed to thebrowser during the wait, so the FE has no progress signal to bind to.
(
pending -> running -> succeeded) and coarse log stages(
init/plan/graph/apply) exist. Real sync would require converting theendpoint to a streaming protocol (SSE/WebSocket) plus FE rework, which is
disproportionate for this 1-point ticket.
Keep polling (do not switch to pubsub-block)
The wait could technically block instead of poll: on completion
CompleteJobpublishes
ProvisionerJobLogsNotifyMessage{EndOfLogs: true}on the job logsnotify channel, so we could subscribe and wait for that message with the
context timeout as a fallback. We deliberately do not do that here: correctness
would require subscribe-before-completion plus an initial DB completion check to
avoid a race, and Postgres LISTEN/NOTIFY is at-most-once (can drop under load),
so a poll fallback would still be needed. The existing backoff poll
(100ms -> 200ms -> 500ms -> 1s) is simple and robust for a short-lived
synchronous request.
Approach
Replace the looping fill with a single, non-repeating ease-out fill that
decelerates and approaches (but never reaches) ~90%, holding there until the
request resolves and the loader unmounts. This reads as continuous forward
progress for an unknown-duration operation and never restarts. The floating-icon
animation is intentional ambient motion and is not in scope.
Out of scope
Generated by Coder Agents.