diff --git a/app/Livewire/Project/New/PublicGitRepository.php b/app/Livewire/Project/New/PublicGitRepository.php index 62ac7ec0d..dbfa15a55 100644 --- a/app/Livewire/Project/New/PublicGitRepository.php +++ b/app/Livewire/Project/New/PublicGitRepository.php @@ -208,13 +208,8 @@ private function getGitSource() if ($this->repository_url_parsed->getSegment(3) === 'tree') { $path = str($this->repository_url_parsed->getPath())->trim('/'); - $this->git_branch = str($path)->after('tree/')->before('/')->value(); - $this->base_directory = str($path)->after($this->git_branch)->after('/')->value(); - if (filled($this->base_directory)) { - $this->base_directory = '/'.$this->base_directory; - } else { - $this->base_directory = '/'; - } + $this->git_branch = str($path)->after('tree/')->value(); + $this->base_directory = '/'; } else { $this->git_branch = 'main'; } @@ -235,9 +230,32 @@ private function getBranch() return; } if ($this->git_source->getMorphClass() === GithubApp::class) { - ['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = githubApi(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}"); - $this->rate_limit_reset = Carbon::parse((int) $this->rate_limit_reset)->format('Y-M-d H:i:s'); - $this->branchFound = true; + $originalBranch = $this->git_branch; + $branchToTry = $originalBranch; + + while (true) { + try { + $encodedBranch = urlencode($branchToTry); + ['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = githubApi(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$encodedBranch}"); + $this->rate_limit_reset = Carbon::parse((int) $this->rate_limit_reset)->format('Y-M-d H:i:s'); + $this->git_branch = $branchToTry; + + $remaining = str($originalBranch)->after($branchToTry)->trim('/')->value(); + $this->base_directory = filled($remaining) ? '/'.$remaining : '/'; + + $this->branchFound = true; + + return; + } catch (\Throwable $e) { + if (str_contains($branchToTry, '/')) { + $branchToTry = str($branchToTry)->beforeLast('/')->value(); + + continue; + } + + throw $e; + } + } } } diff --git a/resources/views/livewire/project/shared/environment-variable/all.blade.php b/resources/views/livewire/project/shared/environment-variable/all.blade.php index 28c67c5b4..2ae3ad166 100644 --- a/resources/views/livewire/project/shared/environment-variable/all.blade.php +++ b/resources/views/livewire/project/shared/environment-variable/all.blade.php @@ -84,21 +84,21 @@ Inline comments with space before # (e.g., KEY=value #comment) are stripped. - @if ($showPreview) - @endif Save All Environment Variables @else - @if ($showPreview) - @endif @endcan diff --git a/resources/views/livewire/project/shared/environment-variable/show.blade.php b/resources/views/livewire/project/shared/environment-variable/show.blade.php index 6e93d296b..b873a6f05 100644 --- a/resources/views/livewire/project/shared/environment-variable/show.blade.php +++ b/resources/views/livewire/project/shared/environment-variable/show.blade.php @@ -155,7 +155,7 @@ @else -
+
toContain('wire:key="env-show-value-textarea-{{ $env->id }}"') ->toContain('wire:key="env-show-value-input-{{ $env->id }}"'); }); + +it('uses sans font for the developer bulk environment variable editor', function () { + $view = file_get_contents(resource_path('views/livewire/project/shared/environment-variable/all.blade.php')); + + expect($view) + ->toContain('class="whitespace-pre-wrap font-sans"') + ->not->toContain('wire:model="variables" monospace') + ->not->toContain('wire:model="variablesPreview" monospace'); +}); diff --git a/tests/Feature/PublicGitRepositoryBranchParsingTest.php b/tests/Feature/PublicGitRepositoryBranchParsingTest.php new file mode 100644 index 000000000..38f757b2e --- /dev/null +++ b/tests/Feature/PublicGitRepositoryBranchParsingTest.php @@ -0,0 +1,71 @@ +getSegment(3) === 'tree') { + $path = str($parsed->getPath())->trim('/'); + $branch = str($path)->after('tree/')->value(); + $baseDirectory = '/'; + } + + return [ + 'branch' => $branch, + 'base_directory' => $baseDirectory, + 'repository' => $parsed->getSegment(1).'/'.$parsed->getSegment(2), + ]; +} + +test('parses simple branch from GitHub URL', function () { + $result = parseBranchFromUrl('https://github.com/andrasbacsai/coolify-examples/tree/main'); + + expect($result['branch'])->toBe('main'); + expect($result['base_directory'])->toBe('/'); + expect($result['repository'])->toBe('andrasbacsai/coolify-examples'); +}); + +test('parses branch with slash from GitHub URL', function () { + $result = parseBranchFromUrl('https://github.com/andrasbacsai/coolify-examples-1/tree/fix/8854-env-var-fallback-volume'); + + expect($result['branch'])->toBe('fix/8854-env-var-fallback-volume'); + expect($result['base_directory'])->toBe('/'); + expect($result['repository'])->toBe('andrasbacsai/coolify-examples-1'); +}); + +test('parses branch with multiple slashes from GitHub URL', function () { + $result = parseBranchFromUrl('https://github.com/user/repo/tree/feature/team/new-widget'); + + expect($result['branch'])->toBe('feature/team/new-widget'); + expect($result['base_directory'])->toBe('/'); +}); + +test('defaults to main branch when no tree segment in URL', function () { + $result = parseBranchFromUrl('https://github.com/andrasbacsai/coolify-examples'); + + expect($result['branch'])->toBe('main'); + expect($result['base_directory'])->toBe('/'); +}); + +test('parses version-style branch with slash from GitHub URL', function () { + $result = parseBranchFromUrl('https://github.com/coollabsio/coolify-examples/tree/release/v2.0'); + + expect($result['branch'])->toBe('release/v2.0'); + expect($result['base_directory'])->toBe('/'); +}); + +test('parses branch from non-GitHub URL with tree segment', function () { + $result = parseBranchFromUrl('https://gitlab.com/user/repo/tree/hotfix/critical-bug'); + + expect($result['branch'])->toBe('hotfix/critical-bug'); + expect($result['base_directory'])->toBe('/'); +});