Skip to content

refactor(sdl): retire the sdl builder page and route users to configure - #3935

Open
baktun14 wants to merge 4 commits into
mainfrom
refactor/sdl-retire-builder-route-for-configure
Open

baktun14 wants to merge 4 commits into
mainfrom
refactor/sdl-retire-builder-route-for-configure

Conversation

@baktun14

Copy link
Copy Markdown
Contributor

Why

Closes CON-672

The SDL Builder predates the redesign and the Configure page replaces it. Two earlier pieces already landed — CON-681 (#3444) took the sidebar entry out and healed the pre-uact pricing crash, and CON-675 (#3443) brought Container-VM deployments to Configure — so what was left was retiring the routes themselves and re-pointing everything that still led to them.

/deploy-linux was already a client-side redirect shim, and its getServerSideProps still fetched a template it never used.

What

Edge redirects replace both pages. /sdl-builder and /deploy-linux become next.config.js entries, so an old bookmark gets a real 308 rather than a hydration-time bounce off a loading shell. A saved-template link carries its id across:

Request Lands on
/sdl-builder /new-deployment/configure
/sdl-builder?id=<uuid> /new-deployment/configure?userTemplateId=<uuid>
/sdl-builder?id= (empty) /new-deployment/configure
/deploy-linux /new-deployment/configure?vm=true

Verified against a production build — each returns 308 with exactly those destinations.

Configure can now open a user's own template. It could only resolve a templateId against the public gallery, so a saved template reached it by stuffing the SDL into an in-memory atom and hopping through the classic URL — which meant a middle-click or a new tab arrived with nothing to configure. The new ?userTemplateId= is backed by the existing GET /v1/user/template/{id}, which already refuses a template that isn't the caller's. That endpoint answers a non-owner with a 200 and an empty body rather than an error, so both it and a failed request land on the same "couldn't load the template" fallback. The two template sources are mutually exclusive and resolved at the parse boundary, and buildConfigureUrl forwards the id so the shallow URL rewrites during a configure session don't silently drop it.

Template saving is deferred to CON-673, not dropped. It's the one builder capability without a Configure equivalent yet, so nothing on its path was destroyed:

  • useSaveUserTemplate and the whole user-template API are untouched (the hook is spec-only until CON-673 — deliberate, not dead code).
  • create_sdl_template / update_sdl_template stay in the analytics union, marked dormant, so the tracking plan isn't churned twice.
  • SaveTemplateModal.tsx is deleted in eca7697 and cited on CON-673 as the reference for the behavior to rebuild — the title/visibility validation, the public-env warning, the sign-in gate, and the create-vs-Save-As ownership rule. It needs a DialogV2 rewrite against Configure's form state regardless, and keeping it unimported would have blocked removing sdlStore.sdlBuilderSdl and useFormPersist.
  • The template detail page keeps its Edit label and its click_edit_sdl_template event. It loads read-only for now and is accurate again once CON-673 lands — better than renaming the same button twice.

Worth a reviewer's attention

  • SimpleServiceFormControl is intentionally kept. It looks like a builder file and sits in components/sdl/, but the classic /new-deployment flow still uses it for repository and redeploy intents.
  • Deploy and Edit point at the same URL for one release. They diverge again when Edit gets a save action, so both stay rather than being collapsed now.
  • useReturnTo behavior change. A login returnTo still pointing at /deploy-linux now classifies as null instead of a deployment. Only affects links already in flight.
  • Analytics removed: preview_sdl, import_sdl and reset_sdl lost their only emitter with the builder. Unlike saving, the first two already have live equivalents on Configure (the SDL pane, and configure_sdl_imported). create_sdl_template_link and click_edit_sdl_template survive but now fire against Configure, so saved Amplitude charts may want updating.
  • permanent: true means a 308, which browsers cache hard — worth a fresh incognito window if you ever test a revert locally.
  • The two E2E specs went with the page rather than being ported. configure-deployment-flow.spec.ts already covers deploying from the form end to end, and build-template.spec.ts asserted builder component-set behavior with no Configure equivalent. configure-deployment-container-vm.spec.ts still covers the /deploy-linux entry.

Verification

Full deploy-web unit suite green (381 files / 3961 tests), lint clean, tsc --noEmit shows only the pre-existing spec baseline, and next build succeeds with both routes gone from the route table. Redirects probed against the built server as above.

The configure screen could only resolve a templateId against the public
gallery, so a user's own saved template had no way in beyond an in-memory
atom handoff. Add a userTemplateId entry backed by the existing private
user-template endpoint, which already answers with an empty body when the
template isn't the caller's to see - surfaced as the same fallback as a
failed fetch.

The two template sources are mutually exclusive and resolved at the parse
boundary, and buildConfigureUrl forwards the id so the shallow URL rewrites
during a configure session don't drop it.
The template detail page reached the deployment editor by writing the SDL
into an in-memory atom and pushing the classic URL, so a middle-click or a
new tab arrived with nothing to configure. Both Deploy and Edit now carry
the template in the URL itself.

Launch Container-VM and Run Custom Container get a handler each rather than
one parameterized by a page name, which was the last producer of the
deploy-linux page param.
Both pages ran on the pre-redesign builder machinery that the configure
page replaces; deploy-linux was already a client-side redirect shim whose
getServerSideProps still fetched a template it never used.

Edge redirects replace them, so the old URLs keep working for anyone
holding a bookmark - a saved-template link carries its id across to the
new userTemplateId param. The builder's own modals go with the page:
import and export already exist on configure, and preview is superseded by
the sdl pane. Template saving is the one capability without an equivalent
yet - useSaveUserTemplate and its two analytics events are kept for the
configure-side save that follows in CON-673.

SimpleServiceFormControl stays: the classic new-deployment flow still uses
it for repository and redeploy intents.

The e2e specs went with the page rather than being ported - the configure
flow spec already covers deploying from the form, and the other asserted
builder component-set behavior that has no configure equivalent.
The sdlBuilder and plainLinux url builders have no callers left, and the
page param they fed - along with the deploy-linux branch in
useNewDeploymentUrl - was the only reason newDeployment could resolve to
anything but /new-deployment.

The deploy-linux clause in the return-to classifier goes too. A login
returnTo still pointing there now classifies as null rather than a
deployment, which only affects links already in flight.
@baktun14
baktun14 requested a review from a team as a code owner September 12, 2026 14:16
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

On-demand reviews are free for the next 8 days. After that, they cost $0.25 per reviewed file.

Or wait 43 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available. Your 51 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: cf609b53-d166-465d-b28d-f00464c0ab8c

📥 Commits

Reviewing files that changed from the base of the PR and between ec579eb and b1d9888.

📒 Files selected for processing (35)
  • apps/deploy-web/next.config.js
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/ConfigureDeployment/ConfigureDeployment.spec.tsx
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/ConfigureDeployment/ConfigureDeployment.tsx
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/useDeploymentFlow/deploymentIntent.spec.ts
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/useDeploymentFlow/deploymentIntent.ts
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/useDeploymentFlow/useDeploymentFlow.spec.tsx
  • apps/deploy-web/src/components/deployments/ConfigureDeployment/useDeploymentFlow/useDeploymentFlow.ts
  • apps/deploy-web/src/components/new-deployment/RedirectDeployLinuxToConfigure/RedirectDeployLinuxToConfigure.spec.tsx
  • apps/deploy-web/src/components/new-deployment/RedirectDeployLinuxToConfigure/RedirectDeployLinuxToConfigure.tsx
  • apps/deploy-web/src/components/new-deployment/TemplateList.spec.tsx
  • apps/deploy-web/src/components/new-deployment/TemplateList.tsx
  • apps/deploy-web/src/components/sdl/ImportSdlModal.tsx
  • apps/deploy-web/src/components/sdl/PreviewSdl.tsx
  • apps/deploy-web/src/components/sdl/SaveTemplateModal.tsx
  • apps/deploy-web/src/components/sdl/SimpleSdlBuilderForm.tsx
  • apps/deploy-web/src/components/templates/UserTemplate.tsx
  • apps/deploy-web/src/components/user/UserProfile.tsx
  • apps/deploy-web/src/hooks/useFormPersist.spec.ts
  • apps/deploy-web/src/hooks/useFormPersist.tsx
  • apps/deploy-web/src/hooks/useNewDeploymentUrl/useNewDeploymentUrl.spec.ts
  • apps/deploy-web/src/hooks/useNewDeploymentUrl/useNewDeploymentUrl.ts
  • apps/deploy-web/src/hooks/useReturnTo/useReturnTo.ts
  • apps/deploy-web/src/pages/deploy-linux/index.tsx
  • apps/deploy-web/src/pages/sdl-builder/index.tsx
  • apps/deploy-web/src/queries/useTemplateQuery.spec.tsx
  • apps/deploy-web/src/queries/useTemplateQuery.tsx
  • apps/deploy-web/src/services/analytics/analytics.service.ts
  • apps/deploy-web/src/store/sdlStore.ts
  • apps/deploy-web/src/utils/sdl/data.spec.ts
  • apps/deploy-web/src/utils/sdl/data.ts
  • apps/deploy-web/src/utils/urlUtils.spec.ts
  • apps/deploy-web/src/utils/urlUtils.ts
  • apps/deploy-web/tests/ui/build-template.spec.ts
  • apps/deploy-web/tests/ui/pages/BuildTemplatePage.tsx
  • apps/deploy-web/tests/ui/sdl-builder-deployment.spec.ts

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.41%. Comparing base (ec579eb) to head (b1d9888).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ploy-web/src/components/templates/UserTemplate.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3935      +/-   ##
==========================================
+ Coverage   82.35%   82.41%   +0.05%     
==========================================
  Files        1280     1172     -108     
  Lines       35404    32513    -2891     
  Branches     8566     7977     -589     
==========================================
- Hits        29158    26796    -2362     
+ Misses       5515     5035     -480     
+ Partials      731      682      -49     
Flag Coverage Δ *Carryforward flag
api 92.76% <ø> (ø) Carriedforward from ec579eb
deploy-web 73.45% <96.87%> (+1.02%) ⬆️
log-collector ?
notifications 94.35% <ø> (ø) Carriedforward from ec579eb
provider-console 81.68% <ø> (ø) Carriedforward from ec579eb
provider-inventory ?
provider-proxy 88.61% <ø> (ø) Carriedforward from ec579eb
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...oyment/ConfigureDeployment/ConfigureDeployment.tsx 100.00% <100.00%> (ø)
...reDeployment/useDeploymentFlow/deploymentIntent.ts 100.00% <100.00%> (ø)
...eDeployment/useDeploymentFlow/useDeploymentFlow.ts 93.21% <ø> (ø)
...web/src/components/new-deployment/TemplateList.tsx 93.10% <100.00%> (+15.32%) ⬆️
...pps/deploy-web/src/components/user/UserProfile.tsx 0.00% <ø> (ø)
...c/hooks/useNewDeploymentUrl/useNewDeploymentUrl.ts 100.00% <ø> (ø)
...ps/deploy-web/src/hooks/useReturnTo/useReturnTo.ts 93.18% <100.00%> (ø)
apps/deploy-web/src/queries/useTemplateQuery.tsx 97.22% <100.00%> (+0.03%) ⬆️
...oy-web/src/services/analytics/analytics.service.ts 94.89% <ø> (ø)
apps/deploy-web/src/store/sdlStore.ts 100.00% <ø> (ø)
... and 3 more

... and 100 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. Because it retires two routes in favor of edge redirects, merges a new user-template resolution path into the shared ConfigureDeployment flow, and touches URL-building/analytics/persistence code used across many entry points, a human look would still be worthwhile.

What was reviewed: the new next.config.js redirects (including the has-query-based /sdl-builder?id= case and the empty-id fallback), the mutually-exclusive templateId/userTemplateId/vm parsing in deploymentIntent.ts, the merged template-fetch/error/loading logic in ConfigureDeployment.tsx (including the "200 with empty body" non-owner case surfaced via !userTemplateQuery.data?.sdl), and confirmed no dangling references to the deleted files/URL helpers (SimpleSdlBuilderForm, SaveTemplateModal, ImportSdlModal, PreviewSdl, RedirectDeployLinuxToConfigure, useFormPersist, UrlService.sdlBuilder/plainLinux) remain anywhere in apps/deploy-web/src or tests.

Extended reasoning...

Overview

This PR retires the classic /sdl-builder and /deploy-linux pages in apps/deploy-web, replacing them with next.config.js 308 redirects into the unified /new-deployment/configure flow. It introduces a userTemplateId search param, threaded through deploymentIntent.ts, urlUtils.ts, useNewDeploymentUrl.ts, UserTemplate.tsx, TemplateList.tsx, and useTemplateQuery.tsx, so a user's own saved template can be opened directly on Configure via GET /v1/user/template/{id}. It deletes several now-unreferenced builder-only components (SimpleSdlBuilderForm, SaveTemplateModal, ImportSdlModal, PreviewSdl, RedirectDeployLinuxToConfigure, useFormPersist), the sdlBuilderSdl atom, and a Playwright E2E suite (build-template.spec.ts), while updating the corresponding unit specs.

Security risks

No new security-sensitive surface is introduced. The userTemplateId resolution relies entirely on an existing, presumably-authorization-checked backend endpoint (GET /v1/user/template/{id}) that already refuses non-owned templates; the frontend simply treats a resulting empty body the same as a failed request (a generic "couldn't load" fallback), which does not leak any data. The redirects are static, server-side next.config.js entries with no user-controlled destination beyond a validated capture group.

Level of scrutiny

This is a large (35-file), cross-cutting refactor touching route removal, URL-building, analytics, persisted state, and a merged template-resolution code path used by multiple entry points (gallery templates, user templates, hardcoded templates, VM seeding, draft resumption). Even though the diff is mechanical in nature and well covered by updated unit specs, the number of interacting conditions in ConfigureDeployment.tsx (draft vs. hardcoded vs. gallery vs. user-template vs. VM) and the redirect ordering/precedence in next.config.js are exactly the kind of logic where a subtle regression is easy to introduce and easy for a human familiar with the product flows to catch quickly.

Other factors

Test coverage looks strong and consistent with repo conventions (setup-function pattern used throughout the touched specs, no stray beforeEach). I did not find dangling imports/references to any of the deleted files or removed UrlService helpers. The PR description also documents several deliberate, easy-to-second-guess tradeoffs (analytics events going dormant, useReturnTo classification change, template-saving deferred to a follow-up ticket) that a human reviewer with product context is better positioned to sign off on than an automated pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant