-
Notifications
You must be signed in to change notification settings - Fork 1
feat(deploy) - add site deploy command #20
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
Conversation
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.0.3-pr.20.c1a0030Prefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.0.3-pr.20.c1a0030"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.0.3-pr.20.c1a0030"
}
}
Preview published to npm registry — try new features instantly! |
Pull Request Review: Site Deploy CommandOverviewThis PR adds a ✅ StrengthsArchitecture & Code Organization
User Experience
Code Quality
🐛 Bugs & IssuesCritical Issues1. Path Traversal Vulnerability ( const absolutePath = join(outputDir, relativePath);The code doesn't validate that the resolved path stays within Fix: Add path validation: import { resolve, relative } from "node:path";
async function readSiteFile(outputDir: string, relativePath: string): Promise<SiteFile> {
const absolutePath = resolve(outputDir, relativePath);
const normalizedBase = resolve(outputDir);
// Ensure the resolved path is within outputDir
const rel = relative(normalizedBase, absolutePath);
if (rel.startsWith('..') || path.isAbsolute(rel)) {
throw new Error(`Path traversal detected: ${relativePath}`);
}
// ... rest of implementation
}2. Missing Directory Existence Check ( const outputDir = resolve(project.root, project.site.outputDirectory);The code resolves the path but never checks if the directory exists before attempting to deploy. This will cause a confusing error later when globby tries to read from a non-existent directory. Fix: Add existence check after line 16: const outputDir = resolve(project.root, project.site.outputDirectory);
if (!(await pathExists(outputDir))) {
throw new Error(
`Output directory does not exist: ${project.site.outputDirectory}. Did you run the build command?`
);
}Medium Issues3. Unbounded Memory Usage ( const files: SiteFile[] = [];
// ... loads all files
files.push(file);For large sites (100MB+), this could cause memory issues. The async generator pattern is great, but it's not being used effectively. Consider: Either document this limitation or implement chunked uploads if the API supports it. 4. Missing Zod Validation ( Fix: Add validation when implementing the real API: export async function uploadSite(files: SiteFile[]): Promise<DeployResponse> {
const response = await base44Client.post("api/sites/deploy", { json: { files } });
const data = await response.json();
const result = DeployResponseSchema.safeParse(data);
if (!result.success) {
throw new Error(`Invalid API response: ${result.error.message}`);
}
return result.data;
}5. Arbitrary Delay in Production Code ( await new Promise((resolve) => setTimeout(resolve, 20));This 20ms delay per file is for demo purposes but shouldn't be in production code. It's easy to forget to remove. Recommendation: Add a clear TODO comment or remove it: // TODO: Remove this demo delay before production
await new Promise((resolve) => setTimeout(resolve, 20));Minor Issues6. Missing Newline at EOF ( 7. Inconsistent Error Handling 🔒 Security Concerns
⚡ Performance Considerations
🧪 Test CoverageMissing Tests: No tests were added for this feature. Critical paths that need testing:
Recommendation: Add tests in 📝 Suggested Improvements
SummaryThis is a solid first implementation that follows the project's patterns well. The main concerns are:
The code quality is good and the architecture is sound. With the security fixes applied, this will be a great addition to the CLI. Recommendation: Request changes for the critical security issue, then approve after fixes. |
Pull Request Review: Site Deploy CommandThank you for this contribution! This PR adds a solid foundation for site deployment functionality. Below is my detailed review covering code quality, potential issues, and recommendations. ✅ Strengths
🔧 Code Quality Issues1. Missing FormData compatibility for Node.js (src/core/site/api.ts:15)const formData = new FormData();
formData.append("file", archiveBuffer, "dist.tar.gz");Issue: Node.js doesn't have a native Fix: You'll need to either:
Priority: HIGH - This will likely fail at runtime 2. Incorrect import path (src/core/site/api.ts:1)import { getAppClient } from "@core/clients/index.js";Issue: Based on the codebase structure shown in AGENTS.md (line 34), the correct path should be Priority: HIGH - This is a compilation error 3. Incorrect AGENTS.md reference (AGENTS.md:66)The documentation says: But the function in Priority: LOW - Documentation accuracy 4. Missing error handling for tar creation (src/core/site/deploy.ts:34)await createArchive(siteOutputDir, archivePath);The Recommendation: Wrap in try-catch with a user-friendly error message 5. runTask callback signature not used (src/cli/commands/site/deploy.ts:28-36)const result = await runTask(
"Creating archive and deploying site...",
async () => {
return await deploySite(outputDir);
},Issue: The updated
Recommendation: Use the updateMessage callback for better UX 🐛 Potential Bugs1. Race condition in temp file cleanup (src/core/site/deploy.ts:36-37)} finally {
await deleteFile(archivePath);
}If Recommendation: Consider more robust cleanup or at least document this edge case 2. UUID toString() is redundant (src/core/site/deploy.ts:30)`base44-site-${getBase44ClientId()}-${randomUUID().toString()}.tar.gz`
Priority: LOW - Works but is redundant 🔒 Security Considerations1. Path traversal vulnerability check neededThe code resolves const outputDir = resolve(project.root, project.site.outputDirectory);Question: Is there validation elsewhere that Recommendation: Add validation to ensure the resolved path is within the project root 2. Temporary file naming includes client ID`base44-site-${getBase44ClientId()}-${randomUUID().toString()}.tar.gz`This exposes the client ID in the temp directory. While temp directories typically have restricted permissions, consider if this is necessary or if just the UUID would suffice. Priority: LOW - Mostly a privacy consideration ⚡ Performance Considerations1. No file size limitsThere's no check for the total size of files being deployed. Very large deployments could:
Recommendation: Add a size check or at least document expected limitations 2. No upload progress feedbackFor large sites, users might think the CLI is frozen during upload. Consider:
🧪 Test CoverageCRITICAL: No tests were added for the new functionality. Required tests:
Recommendation: Add test file at 📋 Missing Edge Cases
🎯 Recommendations SummaryMust Fix (Breaking Issues):
Should Fix (User Experience):
Nice to Have:
Overall AssessmentThis is a solid first implementation that follows the codebase conventions well. The architecture is clean and the code is generally well-structured. However, there are two critical issues that will prevent this from working:
Once these are fixed and tests are added, this will be ready to merge. Recommendation: Request changes for the must-fix items, then approve after fixes. 🤖 Generated with Claude Code |
PR Review: feat(deploy) - add site deploy commandSummaryThis PR adds a basic site deployment command that creates a tar.gz archive from a build output directory and uploads it to Base44 hosting. The implementation follows the established patterns in the codebase and includes good documentation. ✅ StrengthsCode Quality
Architecture
User Experience
🚨 Critical Issues1. Missing Authentication (CRITICAL)The deploy command does not require authentication, unlike entities push. This must be fixed. Location: src/cli/commands/site/deploy.ts:48 2. runTask Signature Breaking Change (HIGH)The runTask signature was changed to require an updateMessage callback parameter. This is a breaking change for existing code. Fix: Make the parameter optional or update all existing callers. 🔧 Medium Priority Issues3. Missing Error Handling for Archive CreationcreateArchive() does not wrap tar creation in try-catch. Users will get raw errors on failures. 4. UUID toString() is RedundantrandomUUID() already returns a string, toString() call is unnecessary. 5. Missing Newline at End of Filesrc/core/site/index.ts:4 is missing a newline at EOF.
|
Code Review: Site Deploy CommandThanks for this PR! The implementation is generally solid and follows the project's conventions well. Here are my findings across different areas: ✅ Positives
🐛 Issues Found1. Missing Authentication (Critical)Location: The deploy command doesn't require authentication, but it makes an API call to // Current
await runCommand(deployAction);
// Should be
await runCommand(deployAction, { requireAuth: true });2. Potential Resource Leak (Medium)Location: If } finally {
try {
await deleteFile(archivePath);
} catch {
// Ignore cleanup errors - the file is in tmpdir and will be cleaned up eventually
}
}3. Missing newline in index.ts (Minor)Location: File missing trailing newline (inconsistent with other files in codebase). 4. Unused runTask updateMessage parameter (Minor)Location: The PR updates async (updateMessage) => {
updateMessage("Creating archive...");
// create archive
updateMessage("Uploading to Base44...");
return await deploySite(outputDir);
}Or if not needed, remove the unused parameter. 5. API Error Handling (Medium)Location: The API call doesn't handle HTTP errors before attempting to parse JSON. If the server returns 4xx/5xx, this will fail cryptically. Consider: const response = await appClient.post("deploy-dist", {
body: formData,
});
if (!response.ok) {
throw new Error(`Deploy failed: ${response.statusText}`);
}
const result = DeployResponseSchema.parse(await response.json());🔒 Security Considerations
⚡ Performance Considerations
🧪 Test CoverageNo tests added for this feature. The codebase has at least one test file (
📝 Code Quality
🎯 RecommendationsMust Fix
Should Fix
Nice to Have
SummaryThis is a well-structured PR that adds useful functionality. The main issues are the missing authentication requirement and some error handling improvements. Once those are addressed, this will be ready to merge. Great work overall! The code is clean and follows the project's patterns nicely. 🎉 |
Pull Request Review: Site Deploy CommandSummaryThis PR adds a site deployment feature that creates a tar.gz archive of built files and uploads them to Base44 hosting. The implementation follows the established patterns in the codebase and is well-structured. Code Quality ✅Strengths:
Style:
Potential Issues 🔍1. runTask callback signature change (src/cli/utils/runTask.ts:30)The const result = await runTask(
"Creating archive and deploying site...",
async () => { // ❌ Doesn't accept updateMessage parameter
return await deploySite(outputDir);
},Impact: This works but misses an opportunity for progress feedback during long uploads. Recommendation: Consider either:
2. Missing newline at end of file (src/core/site/index.ts:4)The file is missing a trailing newline, which is a common convention. 3. Cleanup on error (src/core/site/deploy.ts:36-37)The try {
await createArchive(siteOutputDir, archivePath);
return await uploadSite(archivePath);
} finally {
await deleteFile(archivePath); // ❌ May fail if file was never created
}Impact: Low - 4. No size limits (src/core/site/deploy.ts)The deployment doesn't check the archive size before uploading. Very large sites could cause issues. Recommendation: Consider adding a size check and warning/error for archives over a certain threshold (e.g., 100MB). Performance Considerations ⚡1. Archive creation is synchronous-blockingThe Recommendation: Consider adding progress feedback using the 2. Memory usage for large filesThe entire archive is loaded into memory as a Buffer (src/core/site/api.ts:14) before uploading. const archiveBuffer = await readFile(archivePath); // Entire file in memory
const blob = new Blob([archiveBuffer], { type: "application/gzip" });Impact: For very large sites (100MB+), this could cause memory issues. Recommendation: If supporting large deployments, consider streaming the upload instead of buffering the entire file. However, this may require API changes, so it's fine to defer until needed. Security Concerns 🔒1. Path traversal validation ✅Good use of const outputDir = resolve(project.root, project.site.outputDirectory);Current risk: Low - Recommendation: If 2. Temporary file naming ✅Good use of const archivePath = join(
tmpdir(),
`base44-site-${getBase44ClientId()}-${randomUUID().toString()}.tar.gz`
);Note: The 3. API response validation ✅Excellent use of Zod schema validation on the API response to ensure data integrity. Test Coverage ❌Missing Tests:
Recommendation: Add Additional Recommendations 💡1. User feedback improvementsConsider using the const result = await runTask(
"Preparing deployment...",
async (updateMessage) => {
updateMessage("Creating archive...");
// archive creation
updateMessage("Uploading to Base44...");
return await deploySite(outputDir);
},2. Add deployment size informationShow the archive size before uploading for user awareness: log.info(`Archive size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`);3. Configuration validationConsider validating the output directory path in the config schema to catch issues early. 4. Documentation updateThe AGENTS.md was updated nicely, but consider updating README.md to document the new SummaryOverall: This is a solid implementation that follows best practices. The code is clean, well-organized, and follows the existing patterns in the codebase. Verdict: ✅ Approve with minor suggestions The issues identified are mostly minor improvements and missing tests. The core functionality is sound and ready to merge, but adding tests would significantly improve the quality. Priority fixes before merge:
Nice-to-have improvements:
|
PR Review: Site Deploy CommandThanks for implementing the site deployment feature! This is a solid implementation with good separation of concerns. StrengthsArchitecture and Code Organization
Security
Best Practices
Critical Issues1. Missing Error Handling in API Upload (src/core/site/api.ts:20-22)The uploadSite function does not handle HTTP errors. Unlike the entity push API pattern, this could throw unclear errors. Recommended: Add throwHttpErrors: false and check response.ok, following the pattern from src/core/resources/entity/api.ts:17-28 2. Missing Test CoverageNo tests are included for the new functionality. Tests should cover:
Suggested test file: tests/core/site.test.ts Other Issues3. Redundant UUID call (src/core/site/deploy.ts:30)randomUUID() already returns a string, so .toString() is redundant. 4. Missing Error Handling in Archive Creation (src/core/site/deploy.ts:45-52)The tarCreate function could fail but lacks explicit error handling. Add try-catch with validation that archive was created. 5. Progress Feedback Enhancement (src/cli/commands/site/deploy.ts:28-32)runTask now supports updateMessage parameter for progress updates. Consider using it for better user feedback during large deployments. 6. Missing Newline (src/core/site/index.ts:4)Index file missing trailing newline for consistency. 7. Performance: Large File Memory IssuesLoading entire archive into memory could be problematic for large sites. Consider streaming or document the limitation with size checks. SummaryWell-structured implementation following project conventions. Main concerns:
Recommendation: Request changes for error handling and tests before approval. |
This pr adds a basic site deploy command, it prompts the user to verify to path from which we upload, reads the files and mocks a call to the server.
Screen.Recording.2026-01-13.at.18.39.06.mov