fix(file-mounts): preserve sibling mount configuration

This commit is contained in:
Andras Bacsai
2026-08-19 15:13:31 +02:00
parent 17d4b87ecc
commit 2d88830d50
3 changed files with 64 additions and 5 deletions
+4 -4
View File
@@ -742,7 +742,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
$source = $parsed['source'];
$target = $parsed['target'];
// Mode is available in $parsed['mode'] if needed
$foundConfig = $originalResource->fileStorages()->whereMountPath($target)->first();
$foundConfig = findLocalFileVolumeConfig($originalResource, $source, $target, $pull_request_id);
if (sourceIsLocal($source)) {
$type = str('bind');
if ($foundConfig) {
@@ -792,7 +792,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
}
}
$foundConfig = $originalResource->fileStorages()->whereMountPath($target)->first();
$foundConfig = findLocalFileVolumeConfig($originalResource, $source, $target, $pull_request_id);
if ($foundConfig) {
$content = data_get($foundConfig, 'content');
$isDirectory = data_get($foundConfig, 'is_directory');
@@ -2135,7 +2135,7 @@ function serviceParser(Service $resource): Collection
$source = $parsed['source'];
$target = $parsed['target'];
// Mode is available in $parsed['mode'] if needed
$foundConfig = $originalResource->fileStorages()->whereMountPath($target)->first();
$foundConfig = findLocalFileVolumeConfig($originalResource, $source, $target);
if (sourceIsLocal($source)) {
$type = str('bind');
if ($foundConfig) {
@@ -2185,7 +2185,7 @@ function serviceParser(Service $resource): Collection
}
}
$foundConfig = $originalResource->fileStorages()->whereMountPath($target)->first();
$foundConfig = findLocalFileVolumeConfig($originalResource, $source, $target);
if ($foundConfig) {
$content = data_get($foundConfig, 'content');
$isDirectory = data_get($foundConfig, 'is_directory');
+34 -1
View File
@@ -1666,6 +1666,39 @@ function replaceLocalSource(Stringable $source, Stringable $replacedWith)
return $source;
}
function findLocalFileVolumeConfig(
Application|ServiceApplication|ServiceDatabase $resource,
Stringable $source,
Stringable $target,
int $pullRequestId = 0,
): ?LocalFileVolume {
if ($resource instanceof Application) {
$mainDirectory = str(base_configuration_dir()."/applications/{$resource->uuid}");
} else {
$service = $resource->service;
if (! $service) {
return null;
}
$baseDirectory = (int) $service->compose_parsing_version >= 4 ? 'services' : 'applications';
$mainDirectory = str(base_configuration_dir()."/{$baseDirectory}/{$service->uuid}");
}
$resolvedSource = replaceLocalSource($source, $mainDirectory)->value();
return $resource->fileStorages()
->where('mount_path', $target->value())
->get()
->first(function (LocalFileVolume $volume) use ($pullRequestId, $resolvedSource): bool {
$expectedSource = $resolvedSource;
if ($pullRequestId !== 0 && $volume->is_preview_suffix_enabled) {
$expectedSource = addPreviewDeploymentSuffix($expectedSource, $pullRequestId);
}
return $volume->fs_path === $expectedSource;
});
}
function convertToArray($collection)
{
if ($collection instanceof Collection) {
@@ -2687,7 +2720,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$target = data_get_str($volume, 'target');
$content = data_get($volume, 'content');
$isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null);
$foundConfig = $savedService->fileStorages()->whereMountPath($target)->first();
$foundConfig = findLocalFileVolumeConfig($savedService, $source, $target);
if ($foundConfig) {
$contentNotNull = data_get($foundConfig, 'content');
if ($contentNotNull) {
@@ -78,6 +78,32 @@ it('stores sibling file mounts with different host paths and the same container
]);
});
it('finds existing file mount configuration by source and target', function () {
$application = new Application(['uuid' => 'source-aware-config-test']);
$application->id = fake()->unique()->numberBetween(10000, 99999);
foreach (['first', 'second'] as $name) {
$volume = new LocalFileVolume([
'fs_path' => base_configuration_dir()."/applications/source-aware-config-test/{$name}.html",
'mount_path' => '/usr/share/nginx/html/index.html',
'content' => "{$name} content",
'is_directory' => false,
]);
$volume->resource_type = Application::class;
$volume->resource_id = $application->id;
$volume->save();
}
$found = findLocalFileVolumeConfig(
$application,
str('./second.html'),
str('/usr/share/nginx/html/index.html'),
);
expect($found?->fs_path)->toEndWith('/second.html')
->and($found?->content)->toBe('second content');
});
function makeReadOnlyVolumeFixture(string $compose, string $fsPath, string $mountPath, ?string $appUuid = 'test-app-uuid'): LocalFileVolume
{
$app = new Application([