diff --git a/tests/Feature/ContentFilesBeforeComposeUpTest.php b/tests/Feature/ContentFilesBeforeComposeUpTest.php index 20b9db56f4..97e4d9df17 100644 --- a/tests/Feature/ContentFilesBeforeComposeUpTest.php +++ b/tests/Feature/ContentFilesBeforeComposeUpTest.php @@ -379,14 +379,14 @@ test('a deployment to an additional server writes missing content files on that ->and(ContentFilesUpRecorder::ssh()[$write])->not->toContain("@'{$this->server->ip}'"); }); -test('a Dockerfile deployment to an additional server writes missing content files before the container starts', function () { +test('a Dockerfile deployment to an additional server writes missing content files before the container starts', function (string $state) { $this->application->update(['build_pack' => 'dockerfile', 'docker_compose_location' => null]); $volume = contentFilesVolume($this->application, 'config/app.conf'); $otherServer = Server::factory()->create([ 'team_id' => $this->team->id, 'private_key_id' => $this->server->private_key_id, ])->fresh(); - fakeContentFilesServer([$volume->fs_path => 'missing']); + fakeContentFilesServer([$volume->fs_path => $state]); $job = new ContentFilesUpDeploymentJob; $queue = Mockery::mock(ApplicationDeploymentQueue::class)->makePartial(); @@ -421,11 +421,20 @@ test('a Dockerfile deployment to an additional server writes missing content fil ->and($write)->toBeLessThan($up) ->and(ContentFilesUpRecorder::ssh()[$write])->toContain("@'{$otherServer->ip}'") ->and($this->logEntries)->toContain(['Writing 1 missing configuration file.', 'stdout']); + if ($state === 'empty-directory') { + $writeCommand = ContentFilesUpRecorder::ssh()[$write]; + $escapedPath = escapeshellarg($volume->fs_path); + expect(strpos($writeCommand, "rmdir {$escapedPath}"))->toBeLessThan(strpos($writeCommand, "tee {$escapedPath}")); + } $connect = ContentFilesUpRecorder::indexOf('deployment', "docker network connect '{$this->destination->network}' coolify-proxy"); expect($connect)->not->toBeNull() ->and($connect)->toBeLessThan($up); -}); +})->with([ + 'missing file' => ['missing'], + // Docker creates a missing bind source as an empty directory (#10398). + 'empty directory left by Docker' => ['empty-directory'], +]); test('the content file check and write are safe for non-root servers', function () { $this->server->update(['user' => 'ubuntu']); diff --git a/tests/Feature/DatabaseImportInterruptedCleanupTest.php b/tests/Feature/DatabaseImportInterruptedCleanupTest.php index baabb45a09..8ee4d8d3ce 100644 --- a/tests/Feature/DatabaseImportInterruptedCleanupTest.php +++ b/tests/Feature/DatabaseImportInterruptedCleanupTest.php @@ -440,12 +440,15 @@ test('a restore that exits like a lost SSH connection or timeout reports a norma expect($restoreLine)->toContain($scriptPath); // Fake sudo and docker: `docker exec ...` runs the restore script on this machine. + // Database images have no sudo (#9949), so sudo fails inside the fake container. $dir = sys_get_temp_dir().'/coolify-restore-exit-'.Str::random(8); - mkdir($dir); + mkdir("{$dir}/container", recursive: true); file_put_contents("{$dir}/sudo", "#!/bin/sh\nexec \"\$@\"\n"); - file_put_contents("{$dir}/docker", "#!/bin/sh\n[ \"\$1\" = exec ] || exit 1\nshift 2\nexec \"\$@\"\n"); + file_put_contents("{$dir}/container/sudo", "#!/bin/sh\necho 'sh: sudo: not found' >&2\nexit 127\n"); + file_put_contents("{$dir}/docker", "#!/bin/sh\n[ \"\$1\" = exec ] || exit 1\nshift 2\nPATH=\"{$dir}/container:\$PATH\" exec \"\$@\"\n"); file_put_contents($scriptPath, "echo restoring\nexit {$restoreExitCode}\n"); chmod("{$dir}/sudo", 0755); + chmod("{$dir}/container/sudo", 0755); chmod("{$dir}/docker", 0755); chmod($scriptPath, 0755); @@ -454,9 +457,12 @@ test('a restore that exits like a lost SSH connection or timeout reports a norma $restore->run(); expect($restore->getExitCode())->toBe($expectedExitCode) - ->and($restore->getOutput())->toContain('restoring'); + ->and($restore->getOutput())->toContain('restoring') + ->and($restore->getErrorOutput())->not->toContain('sudo: not found'); } finally { @unlink($scriptPath); + @unlink("{$dir}/container/sudo"); + rmdir("{$dir}/container"); array_map('unlink', glob("{$dir}/*")); rmdir($dir); }