Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions app/Actions/Backup/ManageBackupFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,31 @@
use App\Http\Resources\BackupFileResource;
use App\Jobs\Backup\DeleteFileJob;
use App\Models\BackupFile;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Throwable;
use App\Models\Server;
use Illuminate\Support\Facades\Log;

class ManageBackupFile
{
/**
* @throws Throwable
*/
public function download(BackupFile $file): StreamedResponse
public function delete(BackupFile $file): void
{
$file->backup->server->ssh()->download(
Storage::disk('tmp')->path(basename($file->path())),
$file->path()
);
$server = Server::find($file->backup->server_id);

return Storage::disk('tmp')->download(basename($file->path()));
}
if ($server === null) {
Log::warning('Deleting orphaned backup file without a server', [
'backup_file_id' => $file->id,
'backup_id' => $file->backup_id,
]);
$file->delete();

return;
}

public function delete(BackupFile $file): void
{
$file->status = BackupFileStatus::DELETING;
$file->message = null;
$file->save();

SocketEvent::dispatch(new SocketEventDTO(
projectId: $file->backup->server->project_id,
projectId: $server->project_id,
type: 'backup-file.updated',
data: new BackupFileResource($file),
));
Expand Down
2 changes: 2 additions & 0 deletions app/Console/Commands/RunBackupCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public function handle(): void
Backup::query()
->where('enabled', true)
->whereNull('status')
->whereHas('server')
->with('server')
->chunkById(100, function ($backups) use (&$total): void {
/** @var Backup $backup */
foreach ($backups as $backup) {
Expand Down
23 changes: 23 additions & 0 deletions tests/Feature/BackupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\Feature;

use App\Actions\Backup\ManageBackupFile;
use App\Actions\Backup\RestoreBackup;
use App\Actions\Backup\RunBackup;
use App\Enums\BackupFileStatus;
Expand All @@ -10,6 +11,7 @@
use App\Enums\DatabaseStatus;
use App\Enums\ServerStatus;
use App\Facades\SSH;
use App\Jobs\Backup\DeleteFileJob;
use App\Jobs\Backup\RestoreDatabaseJob;
use App\Models\Backup;
use App\Models\BackupFile;
Expand Down Expand Up @@ -603,6 +605,27 @@ public function test_cannot_enable_a_backup_being_deleted(): void
]);
}

public function test_delete_orphaned_backup_file_hard_deletes_without_dispatching_job(): void
{
Bus::fake();

$backup = Backup::factory()->create([
'type' => BackupType::DATABASE,
'server_id' => 999999,
'storage_id' => $this->storageProvider->id,
'status' => null,
]);
$file = BackupFile::factory()->create([
'backup_id' => $backup->id,
'status' => BackupFileStatus::CREATED,
]);

app(ManageBackupFile::class)->delete($file);

$this->assertDatabaseMissing('backup_files', ['id' => $file->id]);
Bus::assertNotDispatched(DeleteFileJob::class);
}

public function test_see_global_backups_list_scoped_to_current_project(): void
{
$this->actingAs($this->user);
Expand Down
16 changes: 16 additions & 0 deletions tests/Unit/Commands/RunBackupCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use App\Models\StorageProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

Expand Down Expand Up @@ -121,4 +122,19 @@ public function test_runs_enabled_backup_even_after_a_failed_run(): void
$this->artisan('backups:run')
->expectsOutput('1 backups started');
}

public function test_does_not_run_backups_whose_server_is_missing(): void
{
SSH::fake();
Bus::fake();
Carbon::setTestNow('2026-06-19 10:00:00');

$backup = $this->createBackup(['interval' => '0 * * * *', 'server_id' => 999999]);

$this->artisan('backups:run')
->expectsOutput('0 backups started');

$this->assertDatabaseHas('backups', ['id' => $backup->id, 'server_id' => 999999]);
Bus::assertNothingDispatched();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
}
Loading