fix(github): sync app slug before generating installation path

This commit is contained in:
Andras Bacsai 2026-06-15 12:55:29 +02:00
parent b9bda7301a
commit 507a8afa20
3 changed files with 40 additions and 7 deletions

View file

@ -204,6 +204,8 @@ public function checkPermissions()
return; return;
} }
syncGithubAppName($this->github_app);
GithubAppPermissionJob::dispatchSync($this->github_app); GithubAppPermissionJob::dispatchSync($this->github_app);
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
$this->syncData(false); $this->syncData(false);

View file

@ -192,8 +192,6 @@ function syncGithubAppName(GithubApp $source, bool $throw = false): ?string
function getInstallationPath(GithubApp $source): string function getInstallationPath(GithubApp $source): string
{ {
syncGithubAppName($source);
$name = str(Str::kebab($source->name)); $name = str(Str::kebab($source->name));
$baseUrl = rtrim($source->html_url, '/'); $baseUrl = rtrim($source->html_url, '/');
$host = parse_url($source->html_url, PHP_URL_HOST); $host = parse_url($source->html_url, PHP_URL_HOST);

View file

@ -171,10 +171,8 @@ function validPrivateKey(): string
]); ]);
}); });
test('installation path synchronizes github app slug before generating the url', function () { test('installation path is pure and never calls github or mutates the app', function () {
Http::fake([ Http::fake();
'https://api.github.com/app' => Http::response(['slug' => 'actual-github-slug']),
]);
$privateKey = PrivateKey::create([ $privateKey = PrivateKey::create([
'name' => 'github-app-local-name', 'name' => 'github-app-local-name',
@ -198,7 +196,42 @@ function validPrivateKey(): string
$installationUrl = getInstallationPath($githubApp); $installationUrl = getInstallationPath($githubApp);
expect($installationUrl)->toStartWith('https://octocorp.ghe.com/apps/acme-enterprise/actual-github-slug/installations/new?') Http::assertNothingSent();
expect($installationUrl)->toStartWith('https://octocorp.ghe.com/apps/acme-enterprise/local-display-name/installations/new?')
->and($githubApp->refresh()->name)->toBe('Local Display Name')
->and($privateKey->refresh()->name)->toBe('github-app-local-name');
});
test('syncGithubAppName persists the github slug and renames the private key', function () {
Http::fake([
'*/app' => Http::response(['slug' => 'actual-github-slug']),
'*/zen' => Http::response('Keep it logically awesome.'),
]);
$privateKey = PrivateKey::create([
'name' => 'github-app-local-name',
'private_key' => validPrivateKey(),
'team_id' => $this->team->id,
'is_git_related' => true,
]);
$githubApp = GithubApp::create([
'name' => 'Local Display Name',
'organization' => 'acme-enterprise',
'api_url' => 'https://api.github.com',
'html_url' => 'https://octocorp.ghe.com',
'custom_user' => 'git',
'custom_port' => 22,
'app_id' => 12345,
'private_key_id' => $privateKey->id,
'team_id' => $this->team->id,
'is_system_wide' => false,
]);
$appSlug = syncGithubAppName($githubApp, true);
expect($appSlug)->toBe('actual-github-slug')
->and($githubApp->refresh()->name)->toBe('actual-github-slug') ->and($githubApp->refresh()->name)->toBe('actual-github-slug')
->and($privateKey->refresh()->name)->toBe('github-app-actual-github-slug'); ->and($privateKey->refresh()->name)->toBe('github-app-actual-github-slug');
}); });