Skip to content

Commit

Permalink
fix: Restore doesn't work when backup file is renamed (appsmithorg#37666
Browse files Browse the repository at this point in the history
)

When backups are renamed from their original generated name, restore
operation can't process that backup anymore. This PR should fix that.


## Automation

/test sanity

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/12004342912>
> Commit: ef62c35
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12004342912&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Sanity`
> Spec:
> <hr>Mon, 25 Nov 2024 06:54:45 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a new function to determine the contents path within backup
archives, enhancing backup restoration capabilities.
  
- **Bug Fixes**
- Improved error handling for invalid backup file indices and password
attempts during restoration.

- **Refactor**
- Streamlined output and error handling in the backup process, including
cleanup and email notifications for backup errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
sharat87 authored Nov 25, 2024
1 parent aa47249 commit 71e90d5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
3 changes: 0 additions & 3 deletions packages/rts/src/ctl/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ export async function run() {

try {
// PRE-BACKUP
console.log("Available free space at /appsmith-stacks");
const availSpaceInBytes: number =
await getAvailableBackupSpaceInBytes("/appsmith-stacks");

console.log("\n");

checkAvailableBackupSpace(availSpaceInBytes);

if (
Expand Down
53 changes: 48 additions & 5 deletions packages/rts/src/ctl/restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ async function restoreGitStorageArchive(
async function checkRestoreVersionCompatability(restoreContentsPath: string) {
const currentVersion = await utils.getCurrentAppsmithVersion();
const manifest_data = await fsPromises.readFile(
restoreContentsPath + "/manifest.json",
{ encoding: "utf8" },
path.join(restoreContentsPath, "manifest.json"),
"utf8",
);
const manifest_json = JSON.parse(manifest_data);
const restoreVersion = manifest_json["appsmithVersion"];
Expand All @@ -270,9 +270,9 @@ async function checkRestoreVersionCompatability(restoreContentsPath: string) {
"The Appsmith instance to be restored is not compatible with the current version.",
);
console.log(
'Please update your appsmith image to "index.docker.io/appsmith/appsmith-ce:' +
"Please update your appsmith image to 'index.docker.io/appsmith/appsmith-ce:" +
restoreVersion +
'" in the "docker-compose.yml" file\nand run the cmd: "docker-compose restart" ' +
"' in the 'docker-compose.yml' file\nand run the cmd: 'docker-compose restart' " +
"after the restore process is completed, to ensure the restored instance runs successfully.",
);
const confirm = readlineSync.question(
Expand Down Expand Up @@ -352,9 +352,11 @@ export async function run() {

const backupName = backupFileName.replace(/\.tar\.gz$/, "");
const restoreRootPath = await fsPromises.mkdtemp(os.tmpdir());
const restoreContentsPath = path.join(restoreRootPath, backupName);

await extractArchive(backupFilePath, restoreRootPath);

const restoreContentsPath = await figureOutContentsPath(restoreRootPath);

await checkRestoreVersionCompatability(restoreContentsPath);

console.log(
Expand Down Expand Up @@ -390,3 +392,44 @@ export async function run() {
function isArchiveEncrypted(backupFilePath: string) {
return backupFilePath.endsWith(".enc");
}

async function figureOutContentsPath(root: string): Promise<string> {
const subfolders = await fsPromises.readdir(root, { withFileTypes: true });

try {
// Check if the root itself contains the contents.
await fsPromises.access(path.join(root, "manifest.json"));

return root;
} catch (error) {
// Ignore
}

for (const subfolder of subfolders) {
if (subfolder.isDirectory()) {
try {
// Try to find the `manifest.json` file.
await fsPromises.access(
path.join(root, subfolder.name, "manifest.json"),
);

return path.join(root, subfolder.name);
} catch (error) {
// Ignore
}

try {
// If that fails, look for the MongoDB data archive, since backups from v1.7.x and older won't have `manifest.json`.
await fsPromises.access(
path.join(root, subfolder.name, "mongodb-data.gz"),
);

return path.join(root, subfolder.name);
} catch (error) {
// Ignore
}
}
}

throw new Error("Could not find the contents of the backup archive.");
}

0 comments on commit 71e90d5

Please sign in to comment.