diff --git a/app/Extensions/Tasks/Schemas/CreateBackupSchema.php b/app/Extensions/Tasks/Schemas/CreateBackupSchema.php index 411c5ade3e..d5e7288672 100644 --- a/app/Extensions/Tasks/Schemas/CreateBackupSchema.php +++ b/app/Extensions/Tasks/Schemas/CreateBackupSchema.php @@ -17,7 +17,7 @@ public function getId(): string public function runTask(Task $task): void { - $this->initiateService->setIgnoredFiles(explode(PHP_EOL, $task->payload))->handle($task->server, null, true); + $this->initiateService->setIgnoredFiles(explode(PHP_EOL, $task->payload))->handle($task->server, null, true, true); } public function canCreate(Schedule $schedule): bool diff --git a/app/Listeners/Server/BackupCompletedListener.php b/app/Listeners/Server/BackupCompletedListener.php index 9ed63dedd3..79668ec8dd 100644 --- a/app/Listeners/Server/BackupCompletedListener.php +++ b/app/Listeners/Server/BackupCompletedListener.php @@ -12,6 +12,10 @@ class BackupCompletedListener { public function handle(BackupCompleted $event): void { + if ($event->backup->is_automated && $event->backup->is_successful) { + return; + } + $event->backup->loadMissing('server'); $event->backup->server->loadMissing('user'); diff --git a/app/Models/Backup.php b/app/Models/Backup.php index 1f5f545184..c8f5cd41b8 100644 --- a/app/Models/Backup.php +++ b/app/Models/Backup.php @@ -31,6 +31,7 @@ * @property bool $is_successful * @property string|null $upload_id * @property bool $is_locked + * @property bool $is_automated * @property-read Server $server * @property-read BackupStatus $status * @@ -50,6 +51,7 @@ * @method static BackupQueryBuilder|Backup whereIgnoredFiles($value) * @method static BackupQueryBuilder|Backup whereIsLocked($value) * @method static BackupQueryBuilder|Backup whereIsSuccessful($value) + * @method static BackupQueryBuilder|Backup whereIsAutomated($value) * @method static BackupQueryBuilder|Backup whereName($value) * @method static BackupQueryBuilder|Backup whereServerId($value) * @method static BackupQueryBuilder|Backup whereUpdatedAt($value) @@ -69,6 +71,7 @@ class Backup extends Model implements Validatable protected $attributes = [ 'is_successful' => false, 'is_locked' => false, + 'is_automated' => false, 'checksum' => null, 'bytes' => 0, 'upload_id' => null, @@ -82,6 +85,7 @@ class Backup extends Model implements Validatable 'uuid' => ['required', 'uuid'], 'is_successful' => ['boolean'], 'is_locked' => ['boolean'], + 'is_automated' => ['boolean'], 'name' => ['required', 'string'], 'ignored_files' => ['array'], 'backup_host_id' => ['required', 'integer', 'exists:backup_hosts,id'], @@ -96,6 +100,7 @@ protected function casts(): array 'id' => 'int', 'is_successful' => 'bool', 'is_locked' => 'bool', + 'is_automated' => 'bool', 'ignored_files' => 'array', 'bytes' => 'int', 'completed_at' => 'immutable_datetime', diff --git a/app/Services/Backups/InitiateBackupService.php b/app/Services/Backups/InitiateBackupService.php index ba57c241e1..9d7b0da909 100644 --- a/app/Services/Backups/InitiateBackupService.php +++ b/app/Services/Backups/InitiateBackupService.php @@ -71,7 +71,7 @@ public function setIgnoredFiles(?array $ignored): self * @throws TooManyBackupsException * @throws TooManyRequestsHttpException */ - public function handle(Server $server, ?string $name = null, bool $override = false): Backup + public function handle(Server $server, ?string $name = null, bool $override = false, bool $isAutomated = false): Backup { $limit = config('backups.throttles.limit'); $period = config('backups.throttles.period'); @@ -121,14 +121,16 @@ public function handle(Server $server, ?string $name = null, bool $override = fa throw new Exception('Backup host has unknown backup adapter.'); } - return $this->connection->transaction(function () use ($backupHost, $schema, $server, $name) { - $backup = Backup::create([ + return $this->connection->transaction(function () use ($backupHost, $schema, $server, $name, $isAutomated) { + /** @var Backup $backup */ + $backup = Backup::query()->create([ 'server_id' => $server->id, 'uuid' => Uuid::uuid4()->toString(), 'name' => trim($name) ?: sprintf('Backup at %s', now()->toDateTimeString()), 'ignored_files' => array_values($this->ignoredFiles ?? []), 'backup_host_id' => $backupHost->id, 'is_locked' => $this->isLocked, + 'is_automated' => $isAutomated, ]); $schema->createBackup($backup); diff --git a/database/migrations/2026_07_08_122500_add_is_automated_to_backups_table.php b/database/migrations/2026_07_08_122500_add_is_automated_to_backups_table.php new file mode 100644 index 0000000000..e4d1422589 --- /dev/null +++ b/database/migrations/2026_07_08_122500_add_is_automated_to_backups_table.php @@ -0,0 +1,28 @@ +boolean('is_automated')->default(false)->after('is_successful'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('backups', function (Blueprint $table) { + $table->dropColumn('is_automated'); + }); + } +};