mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 10:18:20 +00:00
feat(volume-backups): add service backup UI and polish layouts
Add dedicated service volume-backup Livewire pages and routes, wire shared storage backups for services, and pass S3 trusted hosts into MinIO resolve options. Also refine breadcrumbs, sticky sidebars, destination/GitHub layouts, resource filters, and login recovery link.
This commit is contained in:
1 parent
0312cc8ffb
commit
5842d77b81
69 files changed
+1607
-501
No files matched your search
@@ -1,12 +1,16 @@
|
||||
<?php
|
||||
|
||||
use App\Livewire\Project\Service\VolumeBackup\Create as CreateServiceVolumeBackup;
|
||||
use App\Livewire\Project\Shared\Storages\All;
|
||||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use App\Models\Project;
|
||||
use App\Models\ScheduledVolumeBackup;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\Team;
|
||||
@@ -103,18 +107,21 @@ it('renders volumes as a data table with shared column headers', function () {
|
||||
->toContain('Destination Path')
|
||||
->toContain('volumes-col-backup')
|
||||
->toContain('supportsPreviewSuffix')
|
||||
->toContain('openBackupModal')
|
||||
->toContain('x-modal-input')
|
||||
->not->toContain('wire:click="openBackupModal')
|
||||
->toContain('data-table-row')
|
||||
->toContain('volumes-mobile-label')
|
||||
->not->toContain('table-badge table-badge-success')
|
||||
->not->toContain('livewire:project.shared.storages.show')
|
||||
->not->toContain('x-status-badge')
|
||||
->not->toContain('font-mono')
|
||||
->not->toContain('Service volume mounts are read-only here.');
|
||||
|
||||
// Show remains available for isolated embeds/tests but is no longer nested from All.
|
||||
expect($showView)
|
||||
->toContain('data-table-row')
|
||||
->toContain('volumes-table-grid');
|
||||
->toContain('volumes-table-grid')
|
||||
->not->toContain('font-mono');
|
||||
|
||||
// Service stack page: one settings-section card per compose service/resource.
|
||||
expect($storageView)
|
||||
@@ -131,6 +138,20 @@ it('renders volumes as a data table with shared column headers', function () {
|
||||
->toContain('Service volume mounts are read-only here.')
|
||||
->toContain("'storage-service-'.\$resource->uuid");
|
||||
|
||||
expect($serviceConfigurationView)->not->toContain('Storage Backups');
|
||||
expect(file_get_contents(resource_path('views/livewire/project/service/heading.blade.php')))
|
||||
->toContain("'label' => 'Backups'")
|
||||
->toContain('project.service.volume-backups.*');
|
||||
expect(file_get_contents(resource_path('views/livewire/project/service/volume-backup/show.blade.php')))
|
||||
->toContain('context="service-volume"');
|
||||
expect(file_get_contents(resource_path('views/livewire/project/shared/storages/volume-backups/general.blade.php')))
|
||||
->not->toContain('<code')
|
||||
->toMatch('/<x-callout[^>]*title="File-level consistency"[\s\S]*id="stopDuringBackup"[\s\S]*<\/x-callout>/');
|
||||
expect(file_get_contents(resource_path('views/livewire/project/shared/storages/volume-backups/executions.blade.php')))
|
||||
->toContain('<span>Time</span>')
|
||||
->toContain('x-forms.copy-button')
|
||||
->toContain('col-span-6');
|
||||
|
||||
$css = file_get_contents(resource_path('css/app.css'));
|
||||
|
||||
expect($css)
|
||||
@@ -149,6 +170,43 @@ it('renders volumes as a data table with shared column headers', function () {
|
||||
->toMatch('/\.application-settings-form label\s*\{[^}]*font-size:\s*13px/s');
|
||||
});
|
||||
|
||||
it('creates and exposes volume backups for service storage', function () {
|
||||
$service = Service::factory()->create([
|
||||
'environment_id' => $this->environment->id,
|
||||
'server_id' => $this->server->id,
|
||||
'destination_id' => $this->destination->id,
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
$serviceApplication = ServiceApplication::create([
|
||||
'service_id' => $service->id,
|
||||
'name' => 'buzz',
|
||||
]);
|
||||
$volume = LocalPersistentVolume::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'name' => 'buzz-data',
|
||||
'mount_path' => '/data',
|
||||
'resource_id' => $serviceApplication->id,
|
||||
'resource_type' => $serviceApplication->getMorphClass(),
|
||||
]);
|
||||
|
||||
Livewire::test(CreateServiceVolumeBackup::class, [
|
||||
'service' => $service,
|
||||
'selectedTargetKey' => 'volume:'.$volume->id,
|
||||
])->set('frequency', 'daily')
|
||||
->call('submit')
|
||||
->assertHasNoErrors();
|
||||
|
||||
expect($volume->scheduledBackups()->first())
|
||||
->not->toBeNull()
|
||||
->enabled->toBeTrue();
|
||||
expect(ScheduledVolumeBackup::query()->forService($service)->count())->toBe(1);
|
||||
|
||||
Livewire::test(All::class, ['resource' => $serviceApplication])
|
||||
->assertSet('showActionsColumn', true)
|
||||
->assertSee('Backup')
|
||||
->assertSeeHtml('title="Volume backup is enabled"');
|
||||
});
|
||||
|
||||
it('shows PR deployment suffix only for git-based applications', function () {
|
||||
[$gitApp] = createApplicationWithVolume(['build_pack' => 'nixpacks']);
|
||||
|
||||
|
||||
Reference in new issue
Block a user