All checks were successful
CI / Build Docker image (pull_request) Successful in 19s
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
import type { BackupContext } from "./backupContext";
|
|
|
|
export function parseResticSummary(output: string): string | null {
|
|
try {
|
|
const lines = output.split("\n").filter((line) => line.trim());
|
|
for (const line of lines) {
|
|
try {
|
|
const parsed = JSON.parse(line);
|
|
if (parsed.message_type === "summary") {
|
|
return `Snapshot ${parsed.snapshot_id || "none"}: files new: ${
|
|
parsed.files_new || 0
|
|
}, files changed: ${parsed.files_changed || 0}, data added: ${
|
|
parsed.data_added || 0
|
|
} bytes in ${parsed.total_duration || 0} sec`;
|
|
}
|
|
} catch {
|
|
continue;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.warn(`Failed to parse restic output: ${error}`);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function runResticBackup(
|
|
sourceDir: string,
|
|
context: BackupContext
|
|
): { success: boolean; output: string; summary: string | null } {
|
|
const { logger, resticRepository } = context;
|
|
|
|
logger.info(
|
|
`Starting backup of '${sourceDir}' to repository ${resticRepository}`
|
|
);
|
|
|
|
const result = Bun.spawnSync(
|
|
[
|
|
"restic",
|
|
"-r",
|
|
resticRepository,
|
|
"backup",
|
|
"--no-cache",
|
|
"--json",
|
|
"--verbose",
|
|
".",
|
|
],
|
|
{
|
|
cwd: sourceDir,
|
|
stdio: ["pipe", "pipe", "pipe"],
|
|
}
|
|
);
|
|
|
|
const output = result.stdout?.toString() + result.stderr?.toString() || "";
|
|
const success = result.success;
|
|
const summary = parseResticSummary(output);
|
|
|
|
return { success, output, summary };
|
|
}
|
|
|
|
export async function executeBackup(
|
|
backupType: string,
|
|
backupFn: () => Promise<{
|
|
success: boolean;
|
|
output: string;
|
|
summary: string | null;
|
|
}>,
|
|
context: BackupContext
|
|
): Promise<void> {
|
|
const { logger, notificationClient } = context;
|
|
|
|
try {
|
|
logger.info(`Starting ${backupType} backup process`);
|
|
|
|
const { success, output, summary } = await backupFn();
|
|
|
|
console.log(output);
|
|
|
|
if (success) {
|
|
const message = `${backupType} backup successful. ${
|
|
summary || "No summary available"
|
|
}`;
|
|
logger.info(message);
|
|
await notificationClient.sendNotification(message);
|
|
} else {
|
|
const message = `${backupType} backup failed: ${
|
|
summary || "Unknown error"
|
|
}`;
|
|
logger.error(message);
|
|
await notificationClient.sendNotification(message);
|
|
throw new Error(`${backupType} backup failed: ${message}`);
|
|
}
|
|
|
|
logger.info(`${backupType} backup completed successfully`);
|
|
} catch (error) {
|
|
const errorMessage = `${backupType} backup failed: ${error}`;
|
|
logger.error(errorMessage);
|
|
await notificationClient.sendNotification(errorMessage);
|
|
throw error;
|
|
}
|
|
}
|