fix(git): use cloud install path for ghe apps

This commit is contained in:
vuguul 2026-06-06 17:23:22 -06:00
parent 7053f560c5
commit 5e37024f10
2 changed files with 38 additions and 2 deletions

View file

@ -120,7 +120,11 @@ function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $m
function getInstallationPath(GithubApp $source): string
{
$name = str(Str::kebab($source->name));
$installation_path = $source->html_url === 'https://github.com' ? 'apps' : 'github-apps';
$baseUrl = rtrim($source->html_url, '/');
$host = parse_url($source->html_url, PHP_URL_HOST);
$host = blank($host) ? null : Str::lower($host);
$usesDataResidencyPath = filled($host) && Str::endsWith($host, '.ghe.com');
$installation_path = $host === 'github.com' || $usesDataResidencyPath ? 'apps' : 'github-apps';
$state = Str::random(64);
Cache::put('github-app-setup-state:'.hash('sha256', $state), [
@ -129,7 +133,15 @@ function getInstallationPath(GithubApp $source): string
'team_id' => $source->team_id,
], now()->addMinutes(60));
return "$source->html_url/$installation_path/$name/installations/new?".http_build_query(['state' => $state]);
if ($usesDataResidencyPath) {
$organization = str($source->organization)->trim('/');
if ($organization->isNotEmpty()) {
return "$baseUrl/$installation_path/$organization/$name/installations/new?".http_build_query(['state' => $state]);
}
}
return "$baseUrl/$installation_path/$name/installations/new?".http_build_query(['state' => $state]);
}
function getPermissionsPath(GithubApp $source)

View file

@ -147,6 +147,30 @@ function validPrivateKey(): string
]);
});
test('ghe.com installation path uses github cloud owner scoped route', function () {
$githubApp = new GithubApp;
$githubApp->forceFill([
'id' => 123,
'name' => 'provided-github-app',
'organization' => 'acme-enterprise',
'html_url' => 'https://octocorp.ghe.com',
'team_id' => 456,
]);
$installationUrl = getInstallationPath($githubApp);
parse_str(parse_url($installationUrl, PHP_URL_QUERY), $query);
$installState = $query['state'] ?? null;
expect($installationUrl)->toStartWith('https://octocorp.ghe.com/apps/acme-enterprise/provided-github-app/installations/new?')
->and($installState)->not->toBeEmpty()
->and(Cache::get('github-app-setup-state:'.hash('sha256', $installState)))
->toMatchArray([
'action' => 'install',
'github_app_id' => 123,
'team_id' => 456,
]);
});
test('defaults webhook endpoint to app url when it is the first available endpoint', function () {
config(['app.url' => 'http://localhost:8000']);