From 6f75c601c378601f5a69f3e46c0d79b191b0af1b Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Sat, 3 Oct 2026 19:22:36 +0200 Subject: [PATCH] feat(application): show the full file path inline and warn on a repeated base directory --- .../forms/repository-paths.blade.php | 47 +++++++++++++ .../project/application/general.blade.php | 70 ++----------------- ...ub-private-repository-deploy-key.blade.php | 25 +------ .../new/github-private-repository.blade.php | 25 +------ .../new/gitlab-private-repository.blade.php | 25 +------ .../new/public-git-repository.blade.php | 25 +------ .../Browser/ApplicationConfigurationTest.php | 32 +++++++++ .../NewApplicationRepositoryPathsTest.php | 31 ++++++++ 8 files changed, 129 insertions(+), 151 deletions(-) create mode 100644 resources/views/components/forms/repository-paths.blade.php diff --git a/resources/views/components/forms/repository-paths.blade.php b/resources/views/components/forms/repository-paths.blade.php new file mode 100644 index 0000000000..1b5c6f94f9 --- /dev/null +++ b/resources/views/components/forms/repository-paths.blade.php @@ -0,0 +1,47 @@ +@props([ + 'base', + 'file' => null, + 'fileLabel' => null, + 'defaultFile' => null, + 'disabled' => 'false', +]) + +
class('grid gap-4') }} x-data="{ + base: $wire.entangle('{{ $base }}'), + file: {{ $file ? "\$wire.entangle('{$file}')" : 'null' }}, + normalize(path) { + path = (path ?? '').trim().replace(/\/+$/, ''); + return path === '' || path.startsWith('/') ? path : '/' + path; + }, + get directory() { + return this.normalize(this.base); + }, + get location() { + return this.normalize(this.file) || '{{ $defaultFile }}'; + }, + get repeatsBase() { + return this.directory !== '' && this.location.startsWith(this.directory + '/'); + }, + get suggestion() { + return this.location.slice(this.directory.length); + }, +}"> + + @if ($file) + +

+ Resolved file: + +

+ + {{ $fileLabel }} is relative to the base directory, so it should not start with + again. + + + @endif + {{ $slot }} +
diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index e0ec7b5add..650a348d8a 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -143,36 +143,9 @@
@if ($buildPack === 'dockercompose')
-
- - -
+
@else -
- - @if ($buildPack === 'dockerfile' && !$application->dockerfile) - - @endif - + @if ($buildPack === 'dockerfile') @endif @endif - -
+ @if ($this->application->is_github_based() && !$this->application->is_public_repository())
@if ($build_pack === 'dockercompose') -
- - -

- Resolved file: - -

-
+ @else diff --git a/resources/views/livewire/project/new/github-private-repository.blade.php b/resources/views/livewire/project/new/github-private-repository.blade.php index 22be530c95..80aeb0ee33 100644 --- a/resources/views/livewire/project/new/github-private-repository.blade.php +++ b/resources/views/livewire/project/new/github-private-repository.blade.php @@ -135,28 +135,9 @@
@if ($build_pack === 'dockercompose') -
- - -

- Resolved file: - -

-
+ @else diff --git a/resources/views/livewire/project/new/gitlab-private-repository.blade.php b/resources/views/livewire/project/new/gitlab-private-repository.blade.php index 4060fff309..608b543d9c 100644 --- a/resources/views/livewire/project/new/gitlab-private-repository.blade.php +++ b/resources/views/livewire/project/new/gitlab-private-repository.blade.php @@ -133,28 +133,9 @@
@if ($build_pack === 'dockercompose') -
- - -

- Resolved file: - -

-
+ @else diff --git a/resources/views/livewire/project/new/public-git-repository.blade.php b/resources/views/livewire/project/new/public-git-repository.blade.php index 7e120b8539..6e5995ba5d 100644 --- a/resources/views/livewire/project/new/public-git-repository.blade.php +++ b/resources/views/livewire/project/new/public-git-repository.blade.php @@ -84,28 +84,9 @@
@if ($build_pack === 'dockercompose') -
- - -

- Resolved file: - -

-
+ @else diff --git a/tests/v4/Browser/ApplicationConfigurationTest.php b/tests/v4/Browser/ApplicationConfigurationTest.php index f7778b501b..7d65f22ae8 100644 --- a/tests/v4/Browser/ApplicationConfigurationTest.php +++ b/tests/v4/Browser/ApplicationConfigurationTest.php @@ -156,6 +156,38 @@ it('saves custom docker run options from the UI', function () { ->screenshot(filename: 'application-docker-run-options'); }); +it('warns when the Dockerfile location repeats the base directory and applies the suggested fix', function () { + $this->application->update([ + 'build_pack' => 'dockerfile', + 'base_directory' => '/apps/api', + 'dockerfile_location' => '/apps/api/Dockerfile', + ]); + + loginAndSkipBoarding(); + + $page = visit(applicationConfigurationUrl( + $this->stack['project'], + $this->stack['environment'], + $this->application + )); + + $page->assertSee('Base directory is repeated') + ->assertSee('/apps/api/apps/api/Dockerfile') + ->screenshot(filename: 'application-dockerfile-location-repeats-base-directory') + ->click('Use /Dockerfile') + ->assertDontSee('Base directory is repeated') + ->assertSee('/apps/api/Dockerfile'); + + submitLivewireForm($page); + + $page->assertNoJavaScriptErrors() + ->screenshot(filename: 'application-dockerfile-location-fixed'); + + $this->application->refresh(); + expect($this->application->base_directory)->toBe('/apps/api') + ->and($this->application->dockerfile_location)->toBe('/Dockerfile'); +}); + it('restores the default file location when the field is cleared', function (string $buildPack, string $column, string $default) { $this->application->update(['build_pack' => $buildPack, $column => '/docker/custom']); diff --git a/tests/v4/Browser/NewApplicationRepositoryPathsTest.php b/tests/v4/Browser/NewApplicationRepositoryPathsTest.php index f7970fd02a..7571eb06a6 100644 --- a/tests/v4/Browser/NewApplicationRepositoryPathsTest.php +++ b/tests/v4/Browser/NewApplicationRepositoryPathsTest.php @@ -1,5 +1,6 @@ assertNoJavaScriptErrors() ->screenshot(filename: 'new-application-compose-file-cleared'); }); + +it('warns when the compose file repeats the base directory and creates the application with the suggested fix', function () { + $stack = seedBrowserResourceStack(); + loginAndSkipBoarding(); + + $page = visit("/project/{$stack['project']->uuid}/environment/{$stack['environment']->uuid}/new?type=public&destination={$stack['destination']->uuid}"); + + $page->fill('repository_url', 'https://gitlab.com/example/monorepo.git') + ->click('Check repository') + ->assertSee('Build configuration'); + + selectListboxOption($page, 'build_pack', 'Docker Compose'); + + $page->fill("input[placeholder='/']", 'apps/api/') + ->fill("input[placeholder='/docker-compose.yaml']", 'apps/api/compose.yaml') + ->assertSee('Base directory is repeated') + ->assertSee('/apps/api/apps/api/compose.yaml') + ->screenshot(filename: 'new-application-compose-file-repeats-base-directory') + ->click('button:has-text("Use /compose.yaml")') + ->assertDontSee('Base directory is repeated') + ->assertSee('/apps/api/compose.yaml') + ->assertNoJavaScriptErrors() + ->screenshot(filename: 'new-application-compose-file-fixed'); + + submitLivewireForm($page); + + $application = Application::query()->where('git_repository', 'https://gitlab.com/example/monorepo.git')->sole(); + expect($application->base_directory)->toBe('/apps/api') + ->and($application->docker_compose_location)->toBe('/compose.yaml'); +});