-
Notifications
You must be signed in to change notification settings - Fork 195
Improve UX for manual sites & functions deployment #2523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
ConsoleProject ID: Tip Cursor pagination performs better than offset pagination when loading further pages. |
|
🚅 Deployed to the console-pr-2523 environment in Imagine
|
WalkthroughThe pull request centralizes deployment handling by enhancing the uploader store and routing site/function deployments through it instead of calling the SDK directly. uploader.ts gains an admin-mode Functions client helper, an expanded uploadSiteDeployment signature (now accepts buildCommand, installCommand, outputDirectory) and a new uploadFunctionDeployment method. Both deployment paths forward options and use onProgress callbacks to update deployment progress/status in the uploader queue. Several UI pages were updated to call the uploader, defer navigation until upload completion, and perform cleanup on errors. A CSS z-index for layout-level progress bars was increased and analytics were added to deployment modals. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Areas requiring extra attention:
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte (1)
24-27: Fix file size limit units and error handling
maxSize: plan path converts MB→bytes, fallback path does not. Normalize to bytes for both.- Show the dynamic limit in the error instead of a hardcoded “10MB”.
- Handle
unknownincatch.$: maxSize = - isCloud && $currentPlan - ? $currentPlan.deploymentSize * 1000000 - : $consoleVariables._APP_COMPUTE_SIZE_LIMIT; // already in MB + isCloud && $currentPlan + ? $currentPlan.deploymentSize * 1_000_000 + : ($consoleVariables._APP_COMPUTE_SIZE_LIMIT ?? 0) * 1_000_000; // MB → bytes- } catch (e) { - error = e.message; - trackError(e, Submit.DeploymentCreate); + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + error = msg; + trackError(e, Submit.DeploymentCreate); }- } else if (reason === InvalidFileType.SIZE) { - error = 'File size exceeds 10MB'; + } else if (reason === InvalidFileType.SIZE) { + error = `File size exceeds ${readableMaxSize.value}${readableMaxSize.unit}`;Also applies to: 55-56, 45-47
src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte (1)
23-27: Normalize file size units, dynamic message, and error typingSame MB→bytes mismatch and static “10MB” string; also guard
unknownincatch.$: maxSize = - isCloud && $currentPlan?.deploymentSize - ? $currentPlan.deploymentSize * 1000000 - : $consoleVariables._APP_COMPUTE_SIZE_LIMIT; // already in MB + isCloud && $currentPlan?.deploymentSize + ? $currentPlan.deploymentSize * 1_000_000 + : ($consoleVariables._APP_COMPUTE_SIZE_LIMIT ?? 0) * 1_000_000; // MB → bytes- } else if (reason === InvalidFileType.SIZE) { - error = 'File size exceeds 10MB'; + } else if (reason === InvalidFileType.SIZE) { + error = `File size exceeds ${readableMaxSize.value}${readableMaxSize.unit}`;- } catch (e) { - error = e.message; + } catch (e) { + error = e instanceof Error ? e.message : String(e); trackError(e, Submit.DeploymentCreate); }Also applies to: 55-56, 45-47
src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte (1)
46-50: Normalize file size limit units (MB→bytes)Ensure fallback path is bytes like the plan path.
$: maxSize = isCloud && $currentPlan - ? $currentPlan.deploymentSize * 1000000 - : $regionalConsoleVariables._APP_COMPUTE_SIZE_LIMIT; // already in MB + ? $currentPlan.deploymentSize * 1_000_000 + : ($regionalConsoleVariables._APP_COMPUTE_SIZE_LIMIT ?? 0) * 1_000_000; // MB → bytessrc/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte (2)
169-173: Normalize file size limit units and messageSame MB→bytes normalization and dynamic error text.
$: maxSize = - isCloud && $currentPlan - ? $currentPlan.deploymentSize * 1000000 - : $regionalConsoleVariables._APP_COMPUTE_SIZE_LIMIT; // already in MB + isCloud && $currentPlan + ? $currentPlan.deploymentSize * 1_000_000 + : ($regionalConsoleVariables._APP_COMPUTE_SIZE_LIMIT ?? 0) * 1_000_000; // MB → bytes- } else if (reason === InvalidFileType.SIZE) { - addNotification({ - type: 'error', - message: 'File size exceeds 10MB' - }); + } else if (reason === InvalidFileType.SIZE) { + addNotification({ + type: 'error', + message: `File size exceeds ${readableMaxSize.value}${readableMaxSize.unit}` + });Also applies to: 145-148
1-1: Verify and fix repo-wide inconsistencies in file size limit logicThe verification confirms multiple issues that need addressing:
Unit mismatch in maxSize computation: Files calculate
maxSize = $currentPlan.deploymentSize * 1000000(bytes) but fall back to$regionalConsoleVariables._APP_COMPUTE_SIZE_LIMIT(already in MB). This creates inconsistent units depending on the code path.Hardcoded error messages misaligned with dynamic limits: Multiple files hardcode "File size exceeds 10MB" or "File size exceeds 5MB" in error messages, but
maxSizeis dynamically computed from plan data. Users see static messages that don't reflect the actual limit.Inconsistent error strings across codebase: Error messages vary ("exceeds 10MB", "exceeds 5MB", "exceeds the limit") across different pages, preventing centralized updates.
Affected files:
src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte(line 144, 166-169)src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte(line 23-26, 55)src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte(line 46-49, 145)src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte(line 24-27, 55)src/routes/(console)/organization-[organization]/domains/domain-[domain]/importRecordModal.svelte(line 47)Consolidate size limit constants, ensure byte conversion is applied uniformly, and use dynamic values in user-facing error messages.
src/lib/stores/uploader.ts (2)
120-168: Add error handling to update deployment status on failure.The method lacks error handling. If
createDeploymentthrows an error, the deployment's status will remain 'pending' in the uploader UI instead of being marked as 'failed'. This leaves users without visual feedback about the failure.Wrap the deployment call in a try-catch block:
update((n) => { n.isOpen = true; n.isCollapsed = false; n.files.unshift(newDeployment); return n; }); - const uploadedFile = await temporarySites( - page.params.region, - page.params.project - ).createDeployment({ - siteId, - code, - activate: true, - buildCommand, - installCommand, - outputDirectory, - onProgress: (progress) => { - newDeployment.$id = progress.$id; - newDeployment.progress = progress.progress; - newDeployment.status = progress.progress === 100 ? 'success' : 'pending'; - updateFile(progress.$id, newDeployment); - } - }); - newDeployment.$id = uploadedFile.$id; - newDeployment.progress = 100; - newDeployment.status = 'success'; - updateFile(newDeployment.$id, newDeployment); + try { + const uploadedFile = await temporarySites( + page.params.region, + page.params.project + ).createDeployment({ + siteId, + code, + activate: true, + buildCommand, + installCommand, + outputDirectory, + onProgress: (progress) => { + newDeployment.$id = progress.$id; + newDeployment.progress = progress.progress; + newDeployment.status = progress.progress === 100 ? 'success' : 'pending'; + updateFile(progress.$id, newDeployment); + } + }); + newDeployment.$id = uploadedFile.$id; + newDeployment.progress = 100; + newDeployment.status = 'success'; + updateFile(newDeployment.$id, newDeployment); + } catch (error) { + newDeployment.status = 'failed'; + newDeployment.error = error.message || 'Deployment failed'; + updateFile(newDeployment.$id, newDeployment); + throw error; + } },
169-208: Add error handling to update deployment status on failure.Similar to
uploadSiteDeployment, this method lacks error handling. IfcreateDeploymentthrows, the deployment status remains 'pending' instead of showing 'failed', leaving users without proper failure feedback.Wrap the deployment call in a try-catch block:
update((n) => { n.isOpen = true; n.isCollapsed = false; n.files.unshift(newDeployment); return n; }); - const uploadedFile = await temporaryFunctions( - page.params.region, - page.params.project - ).createDeployment({ - functionId, - code, - activate: true, - onProgress: (progress) => { - newDeployment.$id = progress.$id; - newDeployment.progress = progress.progress; - newDeployment.status = progress.progress === 100 ? 'success' : 'pending'; - updateFile(progress.$id, newDeployment); - } - }); - newDeployment.$id = uploadedFile.$id; - newDeployment.progress = 100; - newDeployment.status = 'success'; - updateFile(newDeployment.$id, newDeployment); + try { + const uploadedFile = await temporaryFunctions( + page.params.region, + page.params.project + ).createDeployment({ + functionId, + code, + activate: true, + onProgress: (progress) => { + newDeployment.$id = progress.$id; + newDeployment.progress = progress.progress; + newDeployment.status = progress.progress === 100 ? 'success' : 'pending'; + updateFile(progress.$id, newDeployment); + } + }); + newDeployment.$id = uploadedFile.$id; + newDeployment.progress = 100; + newDeployment.status = 'success'; + updateFile(newDeployment.$id, newDeployment); + } catch (error) { + newDeployment.status = 'failed'; + newDeployment.error = error.message || 'Deployment failed'; + updateFile(newDeployment.$id, newDeployment); + throw error; + } },
🧹 Nitpick comments (5)
src/routes/(console)/project-[region]-[project]/+layout.svelte (1)
126-133: Z-index bump: verify stacking order vs modals/side‑sheetsRaising to 100 may overlay unintended UI. Please confirm it:
- stays above content but below modal/backdrop layers,
- and doesn’t conflict with side‑sheet visibility rules.
If the design system exposes z‑index tokens, prefer a tokenized value (e.g., var(--z-overlay-progress)). Otherwise, add a brief comment documenting the chosen layer.
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte (1)
33-37: Non-blocking upload: guard against unhandled rejections and make intent explicit
try/catchwon’t catch async failures because the upload isn’t awaited. Keep it non-blocking but handle rejection and avoid awaiting UI:- uploader.uploadSiteDeployment({ - siteId: site.$id, - code: files[0], - }); - show = false; - invalidate(Dependencies.DEPLOYMENTS); - trackEvent(Submit.DeploymentCreate); + void uploader + .uploadSiteDeployment({ + siteId: site.$id, + code: files[0], + }) + .catch((e) => trackError(e, Submit.DeploymentCreate)); + show = false; + void invalidate(Dependencies.DEPLOYMENTS); + trackEvent(Submit.DeploymentCreate);Also, the pipeline flagged Prettier issues; please run Prettier to align formatting.
Also applies to: 39-40, 46-46
src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte (1)
96-103: Uploader flow looks good; consider avoiding store scan for resultNice switch to
uploader.uploadSiteDeployment(...)and success navigation. To reduce races when multiple uploads target the same resource, prefer using a direct return from the uploader (e.g., resolved payload includingdeploymentId) instead of scanning$uploader.filesbyresourceId.If the API can return
{ $id, resourceId, status }, you can:- const promise = uploader.uploadSiteDeployment({ + const promise = uploader.uploadSiteDeployment({ siteId: site.$id, code: files[0], buildCommand: buildCommand || undefined, installCommand: installCommand || undefined, outputDirectory: outputDirectory || undefined }); @@ - await promise; - const upload = $uploader.files.find((f) => f.resourceId === site.$id); + const upload = await promise; // use resolved return if availableAlso applies to: 113-121
src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte (1)
98-101: Uploader usage OK; prefer direct result over store scanAs with sites, avoid scanning
$uploader.filesbyresourceIdif the uploader promise can resolve to the upload entry (less race‑prone when multiple uploads exist).- const promise = uploader.uploadFunctionDeployment({ + const promise = uploader.uploadFunctionDeployment({ functionId: func.$id, code: files[0], }); @@ - await promise; - const upload = $uploader.files.find((f) => f.resourceId === func.$id); + const upload = await promise; // if API returns the upload entryAlso applies to: 113-121
src/lib/stores/uploader.ts (1)
120-208: Consider extracting common deployment logic to reduce duplication.Both
uploadSiteDeploymentanduploadFunctionDeploymentshare substantial logic (~80% overlap) for creating uploader entries, tracking progress, and updating status. Extracting this into a common helper would improve maintainability and ensure consistent behavior.Consider creating a generic helper:
const uploadDeployment = async <T>( deploymentFn: () => Promise<T>, resourceId: string, fileName: string, fileSize: number ) => { const newDeployment: UploaderFile = { $id: '', resourceId, name: fileName, size: fileSize, progress: 0, status: 'pending' }; update((n) => { n.isOpen = true; n.isCollapsed = false; n.files.unshift(newDeployment); return n; }); try { const result = await deploymentFn(); newDeployment.progress = 100; newDeployment.status = 'success'; updateFile(newDeployment.$id, newDeployment); return result; } catch (error) { newDeployment.status = 'failed'; newDeployment.error = error.message || 'Deployment failed'; updateFile(newDeployment.$id, newDeployment); throw error; } };Then simplify both methods to use this helper with their specific deployment logic.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/lib/stores/uploader.ts(4 hunks)src/routes/(console)/project-[region]-[project]/+layout.svelte(1 hunks)src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte(3 hunks)src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte(2 hunks)src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte(4 hunks)src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/stores/uploader.ts (1)
src/lib/stores/sdk.ts (1)
getApiEndpoint(47-59)
🪛 GitHub Actions: Tests
src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte
[warning] 1-1: Code style issues found by Prettier in this file. Run 'prettier --write' to fix.
src/lib/stores/uploader.ts
[warning] 1-1: Code style issues found by Prettier in this file. Run 'prettier --write' to fix.
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte
[warning] 1-1: Code style issues found by Prettier in this file. Run 'prettier --write' to fix.
src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte
[warning] 1-1: Code style issues found by Prettier in this file. Run 'prettier --write' to fix.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: e2e
🔇 Additional comments (6)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte (2)
16-16: Analytics import looks goodImporting and using Submit/trackEvent/trackError is consistent with the new flow.
1-1: Prettier formatting applied and verifiedThe file has been successfully formatted with Prettier and now passes CI formatting validation. No remaining issues.
src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte (1)
123-127: Great: queue cleanup on failureRemoving the in‑flight upload from the queue prevents stale UI.
src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte (1)
1-1: Prettier: fix style issues flagged by CIPrettier has been run on the file. Use the correct path with literal directory names:
npx prettier --write "src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte"src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte (1)
1-1: Prettier formatting changes confirmed and appliedThe Prettier execution successfully fixed style issues in the file. Changes include reformatting a chained method call from multi-line to single-line format, removing trailing commas, and cleaning up extra whitespace. The file is now compliant with Prettier standards and the CI should pass.
Commit these formatting changes to satisfy CI requirements.
src/lib/stores/uploader.ts (1)
35-40: LGTM!The
temporaryFunctionshelper follows the same pattern astemporaryStorageandtemporarySites, maintaining consistency across the codebase.
| trackEvent(Submit.FunctionCreate, { | ||
| source: 'repository', | ||
| runtime: runtime | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Analytics source seems wrong for manual upload
This page is “manual” but tracks { source: 'repository' }. Suggest ‘manual’ for consistency.
- trackEvent(Submit.FunctionCreate, {
- source: 'repository',
- runtime: runtime
- });
+ trackEvent(Submit.FunctionCreate, {
+ source: 'manual',
+ runtime
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| trackEvent(Submit.FunctionCreate, { | |
| source: 'repository', | |
| runtime: runtime | |
| }); | |
| trackEvent(Submit.FunctionCreate, { | |
| source: 'manual', | |
| runtime | |
| }); |
🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte
around lines 108 to 111, the analytics call uses source: 'repository' but this
is the manual upload page; change the tracked source value to 'manual' so the
trackEvent call reads source: 'manual' (preserve the rest of the payload and
surrounding code).
| uploader.uploadFunctionDeployment({ | ||
| functionId: $func.$id, | ||
| code: files[0], | ||
| }) | ||
| show = false; | ||
| files = undefined; | ||
| await invalidate(Dependencies.DEPLOYMENTS); | ||
| trackEvent(Submit.DeploymentCreate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make upload non‑blocking but safe; fix success message; add semicolon
- Without
await, use.catchto capture failures for analytics. - Add missing semicolon to satisfy Prettier/ASI.
- The success toast says “Deployment created successfully” before the upload completes; change to “Deployment upload started” or await completion.
- uploader.uploadFunctionDeployment({
- functionId: $func.$id,
- code: files[0],
- })
+ void uploader
+ .uploadFunctionDeployment({
+ functionId: $func.$id,
+ code: files[0],
+ })
+ .catch((e) => trackError(e, Submit.DeploymentCreate));
+ ;
show = false;
files = undefined;
await invalidate(Dependencies.DEPLOYMENTS);
- trackEvent(Submit.DeploymentCreate);
+ trackEvent(Submit.DeploymentCreate);
addNotification({
type: 'success',
- message: 'Deployment created successfully'
+ message: 'Deployment upload started'
});Also applies to: 41-43
🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte
around lines 32-39 and 41-43, make the upload non-blocking but safe: call
uploader.uploadFunctionDeployment(...) without await, attach a .catch(...) to
capture/log/track failures for analytics, and avoid showing a success toast
before completion by changing the message to "Deployment upload started"; also
add the missing semicolons to satisfy Prettier/ASI. Ensure you still clear
show/files and await invalidate(Dependencies.DEPLOYMENTS) (or otherwise refresh
UI), and duplicate the same non-blocking + .catch + toast + semicolon changes
for the other occurrence on lines 41-43.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte (1)
30-48: Critical: Upload is non-blocking but invalidation/notification happen prematurely.The upload call at line 32 is not awaited, so:
- Line 38 invalidates deployments before the upload completes
- Lines 40-43 show a success notification before the upload finishes
- The try-catch won't catch errors from the upload promise
This creates a race condition and misleads users about deployment status.
Apply this diff to fix the async flow:
async function create() { try { - uploader.uploadFunctionDeployment({ + await uploader.uploadFunctionDeployment({ functionId: $func.$id, code: files[0] }); show = false; files = undefined; await invalidate(Dependencies.DEPLOYMENTS); trackEvent(Submit.DeploymentCreate); addNotification({ type: 'success', message: 'Deployment created successfully' }); } catch (e) { error = e.message; trackError(e, Submit.DeploymentCreate); } }src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte (1)
105-108: Analytics source is incorrect for manual upload page.The analytics event tracks
source: 'repository'but this page handles manual file uploads, not repository-based deployments.Apply this diff:
trackEvent(Submit.FunctionCreate, { - source: 'repository', + source: 'manual', runtime: runtime });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/lib/stores/uploader.ts(4 hunks)src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte(3 hunks)src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte(2 hunks)src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/stores/uploader.ts (1)
src/lib/stores/sdk.ts (1)
getApiEndpoint(47-59)
🔇 Additional comments (4)
src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte (1)
96-118: Good async flow with proper await before navigation.The implementation correctly:
- Initiates the upload asynchronously (line 96)
- Shows an "upload started" notification immediately (lines 101-104)
- Awaits completion before checking status (line 110)
- Conditionally navigates based on success status (lines 113-118)
This provides good UX with immediate feedback while ensuring navigation only happens after successful upload.
src/lib/stores/uploader.ts (3)
35-40: LGTM: Consistent admin client helper.The
temporaryFunctionshelper follows the same pattern astemporaryStorageandtemporarySites, maintaining consistency across the codebase.
169-208: LGTM: Function deployment follows site deployment pattern.The implementation correctly mirrors the site deployment flow with proper progress tracking and status updates.
120-167: Verification complete: all call sites properly updated to use new signature.Found 2 call sites using
uploadSiteDeployment, both correctly updated:
- createManualDeploymentModal.svelte:33 passes
{ siteId, code }- create-site/manual/+page.svelte:96-102 passes all parameters including optional
buildCommand,installCommand, andoutputDirectorywith proper|| undefinedguardsThe API change is fully integrated across the codebase.
| onProgress: (progress) => { | ||
| newDeployment.$id = progress.$id; | ||
| newDeployment.progress = progress.progress; | ||
| newDeployment.status = progress.progress === 100 ? 'success' : 'pending'; | ||
| updateFile(progress.$id, newDeployment); | ||
| } | ||
| }); | ||
| newDeployment.$id = uploadedFile.$id; | ||
| newDeployment.progress = 100; | ||
| newDeployment.status = 'success'; | ||
| updateFile(newDeployment.$id, newDeployment); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Consider: Potential race between onProgress and final status update.
Lines 158-161 set status: 'success' when progress === 100, then lines 164-167 set it again after the promise resolves. If an error occurs between progress=100 and promise resolution, the status may incorrectly show 'success'.
However, if createDeployment throws on failure, the try-catch in the caller will handle it (though there's no try-catch here). Consider whether progress=100 truly indicates success or just upload completion.
Check if the SDK's createDeployment can fail after progress === 100:
🌐 Web query:
Does Appwrite's Sites.createDeployment or Functions.createDeployment throw errors after the upload progress reaches 100%, or does progress=100 guarantee success?
💡 Result:
Short answer: No — progress = 100 only means the upload finished from the client side. The deployment/build stage runs afterwards and can still fail. Appwrite exposes separate deployment/build status (ready/failed/in‑progress) and error codes for build failures, and you must check the deployment status (or API response) after upload to confirm success. [1][2][3]
Sources:
- Functions createDeployment (shows upload/deployment flow and build lifecycle). [1]
- Sites createVCS/createDeployment docs (deployment build can be activated/cancelled and has its own status). [2]
- Appwrite response/error codes (functions/build-related error codes such as build_in_progress / build_not_ready / failures). [3]
Fix premature success status update when progress reaches 100%.
The concern is valid: setting status: 'success' at line 160 when progress === 100 is incorrect. Appwrite's upload progress only indicates client-side upload completion; the deployment/build runs separately and can still fail afterwards. Remove the premature status: 'success' assignment from the onProgress handler (line 160). Only set status: 'success' after confirming the deployment actually succeeded—either by checking the returned deployment object's status field or by verifying the API response indicates a ready/successful state.
🤖 Prompt for AI Agents
In src/lib/stores/uploader.ts around lines 157 to 167, remove the premature
assignment that sets newDeployment.status = 'success' inside the onProgress
handler; keep updating newDeployment.$id and newDeployment.progress there and
call updateFile(progress.$id, newDeployment) but do not mark success based on
progress === 100. Instead, determine success only after the upload/deploy
response returns a confirmed success state (e.g., inspect the returned
uploadedFile or deployment object status/ready flag) and set
newDeployment.status = 'success' and call updateFile(...) at that point; if the
deployment fails, set an appropriate error/failed status based on the API
response.
Task: https://linear.app/appwrite/issue/SER-455/improve-ux-for-sitesfunction-deployment-from-uploaded-file
Summary by CodeRabbit
New Features
Style