diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index cd773f6a9..88ac01819 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -3660,13 +3660,19 @@ function convertGitUrl(string $gitRepository, string $deploymentType, GithubApp| } } - preg_match('/(?<=:)\d+(?=\/)/', $gitRepository, $matches); + if (str($gitRepository)->contains('://')) { + $parsedRepository = parse_url($gitRepository); - if (count($matches) === 1) { - $providerInfo['port'] = $matches[0]; - $gitHost = str($gitRepository)->before(':'); - $gitRepo = str($gitRepository)->after('/'); - $repository = "$gitHost:$gitRepo"; + if ($parsedRepository !== false && array_key_exists('port', $parsedRepository)) { + $providerInfo['port'] = (string) $parsedRepository['port']; + } + } else { + preg_match('/^(?[^:]+):(?\d+)\/(?.+)$/', $gitRepository, $matches); + + if (! empty($matches['port'])) { + $providerInfo['port'] = $matches['port']; + $repository = "{$matches['host']}:{$matches['path']}"; + } } return [ diff --git a/tests/Feature/ConvertingGitUrlsTest.php b/tests/Feature/ConvertingGitUrlsTest.php index 5bcdea1a1..5ff1c8365 100644 --- a/tests/Feature/ConvertingGitUrlsTest.php +++ b/tests/Feature/ConvertingGitUrlsTest.php @@ -60,3 +60,11 @@ 'port' => '766', ]); }); + +test('convertGitUrlsForSourceAndSshUrlSchemeWithCustomPort', function () { + $result = convertGitUrl('ssh://git@192.168.56.11:22222/User/Repo.git', 'source', null); + expect($result)->toBe([ + 'repository' => 'ssh://git@192.168.56.11:22222/User/Repo.git', + 'port' => '22222', + ]); +}); diff --git a/tests/Unit/ApplicationGitSecurityTest.php b/tests/Unit/ApplicationGitSecurityTest.php index 3603b18db..f983d4bf0 100644 --- a/tests/Unit/ApplicationGitSecurityTest.php +++ b/tests/Unit/ApplicationGitSecurityTest.php @@ -99,3 +99,23 @@ // The malicious payload should be escaped (escapeshellarg wraps and escapes quotes) expect($command)->toContain("'https://github.com/user/repo.git'\\''"); }); + +it('preserves ssh scheme URLs with custom ports in deploy_key commands', function () { + $deploymentUuid = 'test-deployment-uuid'; + + $application = new Application; + $application->git_branch = 'master'; + $application->git_repository = 'ssh://git@192.168.56.11:22222/User/Repo.git'; + $application->private_key_id = 1; + + $privateKey = new PrivateKey; + $privateKey->private_key = 'fake-private-key'; + $application->setRelation('private_key', $privateKey); + + $result = $application->generateGitLsRemoteCommands($deploymentUuid, false); + + expect($result['commands']) + ->toContain("'ssh://git@192.168.56.11:22222/User/Repo.git'") + ->toContain('-p 22222') + ->not->toContain('ssh:/git@192.168.56.11:22222/User/Repo.git'); +});