feat: add MongoDB full instance backup and restore - #152
feat: add MongoDB full instance backup and restore#152Prathamesh-chougale-17 wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds MongoDB Full Instance backup and restore support across the runner, adapters, API routes, UI, Prisma schema, and documentation - introducing a backward-compatible backupScope concept defaulting to Selected Databases.
Changes:
- Add MongoDB
backupScope(Selected Databases vs Full Instance) with DB schema + job validation and UI controls. - Implement Full Instance dump/restore behavior using native
mongodump/mongorestorearchive handling with sidecar-driven safety gates. - Extend analyze/restore APIs and broaden unit test coverage around scope behavior and error handling.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/services/restore-pipeline.test.ts | Adds restore pipeline tests ensuring Full Instance restores ignore mapping and fail closed when metadata is missing or mismatched. |
| tests/unit/services/job-service.test.ts | Updates job creation expectations to include default backupScope. |
| tests/unit/runner/steps/02-dump.test.ts | Adds test ensuring stale DB selections are ignored for Full Instance metadata generation. |
| tests/unit/lib/storage-analyze-route.test.ts | Adds test to detect Full Instance MongoDB backups via metadata sidecar. |
| tests/unit/lib/jobs-route-errors.test.ts | Adds API route tests verifying ValidationError handling and preserving 409 duplicate-name behavior. |
| tests/unit/adapters/database/mongodb/restore.test.ts | Adds restore tests for Full Instance (no namespace filters) and privileged credentials usage. |
| tests/unit/adapters/database/mongodb/dump.test.ts | Adds dump tests for Full Instance single-archive behavior and legacy URI path stripping. |
| tests/unit/adapters/database/mongodb/args.test.ts | Adds unit tests for buildFullInstanceConnectionArgs URI rewriting rules. |
| src/services/restore/types.ts | Extends restore input to include optional MongoDB backupScope hint from analyzer/UI. |
| src/services/restore/pipeline.ts | Enforces sidecar verification for Full Instance restores and disables mapping/renaming for confirmed Full Instance archives. |
| src/services/jobs/job-service.ts | Persists backupScope on jobs and validates Full Instance constraints (MongoDB-only, no directory sources). |
| src/lib/runner/steps/03-upload.ts | Writes MongoDB backupScope into backup metadata sidecar during upload. |
| src/lib/runner/steps/02-dump.ts | Threads job backupScope into MongoDB dump config and clears DB selection for Full Instance dumps. |
| src/lib/core/mongodb-backup-scope.ts | Introduces MongoDB backup scope enum + normalization helper. |
| src/lib/core/interfaces.ts | Extends BackupMetadata to optionally include MongoDB backupScope. |
| src/lib/adapters/database/mongodb/restore.ts | Adds backupScope handling, improves credential selection for command args, and uses AdapterError on failures. |
| src/lib/adapters/database/mongodb/dump.ts | Implements Full Instance dump path using native mongodump --archive with validation for empty output. |
| src/lib/adapters/database/mongodb/args.ts | Adds URI rewriting helper to remove path DB while preserving authSource semantics for Full Instance dumps. |
| src/components/dashboard/jobs/job-form.tsx | Adds MongoDB Backup Scope selector, validation, and hides DB picker for Full Instance. |
| src/app/dashboard/storage/restore/restore-client.tsx | Plumbs analyzed backupScope into restore requests and disables mapping/renaming UI for Full Instance restores with stronger warnings. |
| src/app/api/storage/[id]/restore/route.ts | Parses and validates MongoDB backupScope in restore requests. |
| src/app/api/storage/[id]/analyze/route.ts | Surfaces backupScope: FULL_INSTANCE from metadata sidecar to drive restore UI behavior. |
| src/app/api/jobs/route.ts | Validates backupScope on create and maps service-layer ValidationError to 400. |
| src/app/api/jobs/[id]/route.ts | Validates optional backupScope on update and maps service-layer ValidationError to 400. |
| prisma/schema.prisma | Adds backupScope column to Job model with default SELECTED_DATABASES. |
| prisma/migrations/20260819090000_add_mongodb_backup_scope/migration.sql | Adds the Job backupScope column in SQLite. |
| docs/user-guide/sources/mongodb.md | Documents new scopes, Full Instance behavior, and destructive restore safety considerations. |
| docs/changelog.md | Adds vNEXT entry for MongoDB Full Instance backup/restore feature. |
Suppressed comments (1)
src/services/restore/pipeline.ts:462
- This decompression guard runs for any truthy
compressionMeta, including'NONE', which unnecessarily sets the stage to DECOMPRESSING and logs a decompression step even thoughgetDecompressionStream('NONE')returns null. Guard against'NONE'here as well to keep stages/logs accurate even if future code paths setcompressionMetato'NONE'.
if (compressionMeta) {
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (!seekableArchive && metadata.compression) { | ||
| compressionMeta = metadata.compression; | ||
| log(`Detected ${compressionMeta} compression.`, 'info'); | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (1)
Dockerfile:335
- The Docker build check that imports server external packages does not await
Promise.all(...), so Node can exit before anyimport()runs. This can silently skip the verification that the standalone output contains the required dependencies.
RUN node --check custom-server.js && \
prisma --version && \
node -e 'Promise.all(["@aws-sdk/lib-storage", "@microsoft/microsoft-graph-client", "dockerode", "dropbox", "googleapis", "mssql", "ssh2", "ssh2-sftp-client"].map(async (dependency) => { try { await import(dependency); console.log(`${dependency}: available`) } catch (error) { console.error(`${dependency}: ${error.code ?? error.message}`); process.exitCode = 1 } }))' && \
node -e 'require("@prisma/client"); require("sharp")' && \
| const metadata = JSON.parse(metaContent) as BackupMetadata; | ||
| const parsedMetadataScope = MongoDBBackupScopeSchema.safeParse(metadata.backupScope); | ||
| const metadataScope = parsedMetadataScope.success | ||
| ? parsedMetadataScope.data | ||
| : "SELECTED_DATABASES"; | ||
|
|
||
| if (fullInstanceExpected && metadataScope !== "FULL_INSTANCE") { | ||
| throw new RestoreError( | ||
| "The selected file is not confirmed as a MongoDB Full Instance backup. The restore was stopped before changing the target.", | ||
| { executionId, sourcePath: file }, | ||
| ); | ||
| } | ||
| backupScope = metadataScope === "FULL_INSTANCE" ? "FULL_INSTANCE" : undefined; | ||
|
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
src/services/jobs/job-service.ts:367
- In updateJob, destination validation currently only runs when sourceId or sources are included. A request that updates destinations only will skip validateJobDestinations, allowing invalid or empty destination updates to bypass server-side validation.
if (sourceId !== undefined || sources !== undefined) {
await this.validateJobSources(id, sourceId !== undefined ? (sourceId || null) : undefined, sources);
await this.validateJobDestinations(destinations);
}
if (sourceId !== undefined || sources !== undefined || backupScope !== undefined) {
Dockerfile:335
- This Docker build check starts an async Promise.all without awaiting it. Node may exit before the imports resolve, so missing dependencies might not fail the image build as intended.
RUN node --check custom-server.js && \
prisma --version && \
node -e 'Promise.all(["@aws-sdk/lib-storage", "@microsoft/microsoft-graph-client", "dockerode", "dropbox", "googleapis", "mssql", "ssh2", "ssh2-sftp-client"].map(async (dependency) => { try { await import(dependency); console.log(`${dependency}: available`) } catch (error) { console.error(`${dependency}: ${error.code ?? error.message}`); process.exitCode = 1 } }))' && \
node -e 'require("@prisma/client"); require("sharp")' && \
| let seekableArchive = false; | ||
| let backupScope: BackupMetadata['backupScope'] = undefined; | ||
|
|
||
| const tempMetaPath = path.join(getTempDir(), "meta_" + Date.now() + ".json"); |
Summary
mongodumparchive containing all databases, users, and custom rolesValidation
node --max-old-space-size=4096 node_modules/typescript/bin/tsc --noEmit