fix(previews): delete compose preview storage records on cleanup (#12006)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
johandenhollander
2026-10-15 23:13:44 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent bc3ff14567
commit c79f48b6b8
2 changed files with 50 additions and 1 deletions
+4 -1
View File
@@ -54,10 +54,13 @@ class ApplicationPreview extends BaseModel
if (data_get($preview, 'application.build_pack') === 'dockercompose') {
$composeFile = $application->parse(pull_request_id: $preview->pull_request_id);
foreach ($preview->generatedComposeVolumeNames($application, collect(data_get($composeFile, 'volumes', []))) as $volumeName) {
$volumeNames = $preview->generatedComposeVolumeNames($application, collect(data_get($composeFile, 'volumes', [])));
foreach ($volumeNames as $volumeName) {
// Docker does not remove a volume that a container still uses, also with -f.
instant_remote_process(['docker volume rm -f '.escapeshellarg($volumeName)], $server, false);
}
// The compose parser stores preview volumes on the application, not on the preview
$application->persistentStorages()->whereIn('name', $volumeNames)->delete();
$preview->removeComposePreviewNetwork($application, $server);
} else {
// Regular application volume cleanup
@@ -11,6 +11,7 @@ use App\Models\StandaloneDocker;
use App\Models\Team;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Queue;
uses(RefreshDatabase::class);
@@ -118,3 +119,48 @@ it('continues removing preview volumes when an earlier volume is already absent'
Process::assertRan(fn ($process) => str_contains($process->command, "docker volume rm -f 'app-data-pr-42'"));
expect(ApplicationPreview::find($this->preview->id))->toBeNull();
});
it('deletes the persistent storage records of a docker compose preview', function () {
Queue::fake();
$this->application->update([
'build_pack' => 'dockercompose',
'compose_parsing_version' => '5',
'docker_compose_raw' => <<<'YAML'
services:
app:
image: nginx:alpine
volumes:
- files:/app/files
- db:/var/lib/mysql
volumes:
files:
db:
YAML,
]);
$this->application->refresh();
$uuid = $this->application->uuid;
// Deploying the application, this preview and another preview creates the storage records
$this->application->parse();
$this->application->parse(pull_request_id: 42);
$this->application->parse(pull_request_id: 43);
expect($this->application->persistentStorages()->pluck('name')->sort()->values()->all())->toBe([
"{$uuid}_db",
"{$uuid}_db-pr-42",
"{$uuid}_db-pr-43",
"{$uuid}_files",
"{$uuid}_files-pr-42",
"{$uuid}_files-pr-43",
]);
Process::fake(['*' => Process::result(output: '')]);
$this->preview->forceDelete();
Process::assertRan(fn ($process) => str_contains($process->command, "docker volume rm -f '{$uuid}_db-pr-42'"));
expect($this->application->persistentStorages()->pluck('name')->sort()->values()->all())->toBe([
"{$uuid}_db",
"{$uuid}_db-pr-43",
"{$uuid}_files",
"{$uuid}_files-pr-43",
]);
});