Skip to content

Commit 54f88b8

Browse files
committed
refactor(backend): simplify GitHub installation handling logic
1 parent bfaac7f commit 54f88b8

File tree

3 files changed

+7
-138
lines changed

3 files changed

+7
-138
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/backend/src/routes/teams/deploy/github.ts

Lines changed: 6 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -296,64 +296,13 @@ export default async function deployGitHubRoutes(server: FastifyInstance) {
296296
const { teamId } = request.params as { teamId: string };
297297

298298
// Step 1: Check database for installation record
299-
let installation = await credentialService.getInstallation(teamId, 'github');
299+
const installation = await credentialService.getInstallation(teamId, 'github');
300300

301301
if (!installation) {
302-
// No database record - try to auto-detect and link
303-
try {
304-
const installations = await githubService.listInstallations();
305-
306-
if (installations.length > 0) {
307-
// Found installations - select the best one (most recent, not suspended)
308-
const selectedInstallation = installations[0];
309-
310-
// Auto-link to this team
311-
await credentialService.storeInstallation({
312-
teamId,
313-
source: 'github',
314-
installationId: selectedInstallation.id.toString()
315-
});
316-
317-
server.log.info({
318-
teamId,
319-
installation_id: selectedInstallation.id,
320-
account_login: selectedInstallation.account.login,
321-
total_installations_found: installations.length,
322-
operation: 'auto_linked_installation'
323-
}, 'Auto-linked GitHub installation to team');
324-
325-
if (installations.length > 1) {
326-
server.log.info({
327-
teamId,
328-
total_installations: installations.length,
329-
selected_installation_id: selectedInstallation.id,
330-
selected_account: selectedInstallation.account.login,
331-
operation: 'multiple_installations_found'
332-
}, 'Multiple GitHub installations found, selected most recent');
333-
}
334-
335-
// Return connected
336-
const response: ConnectionStatusResponse = { connected: true };
337-
const jsonString = JSON.stringify(response);
338-
return reply.status(200).type('application/json').send(jsonString);
339-
}
340-
341-
// No installations found
342-
server.log.info({
343-
teamId,
344-
operation: 'no_installations_found'
345-
}, 'No GitHub installations found for user');
346-
347-
const response: ConnectionStatusResponse = { connected: false };
348-
const jsonString = JSON.stringify(response);
349-
return reply.status(200).type('application/json').send(jsonString);
350-
} catch (error) {
351-
// Failed to list installations - log and return false
352-
server.log.warn({ error, teamId }, 'Failed to list GitHub installations during auto-detection');
353-
const response: ConnectionStatusResponse = { connected: false };
354-
const jsonString = JSON.stringify(response);
355-
return reply.status(200).type('application/json').send(jsonString);
356-
}
302+
// No database record - team must install the GitHub App via the /install flow
303+
const response: ConnectionStatusResponse = { connected: false };
304+
const jsonString = JSON.stringify(response);
305+
return reply.status(200).type('application/json').send(jsonString);
357306
}
358307

359308
// Step 2: Verify installation still exists on GitHub
@@ -370,35 +319,7 @@ export default async function deployGitHubRoutes(server: FastifyInstance) {
370319
operation: 'stale_installation_cleaned'
371320
}, 'Cleaned up stale GitHub installation record');
372321

373-
// After cleaning up stale record, retry auto-detection
374-
try {
375-
const installations = await githubService.listInstallations();
376-
377-
if (installations.length > 0) {
378-
const selectedInstallation = installations[0];
379-
380-
await credentialService.storeInstallation({
381-
teamId,
382-
source: 'github',
383-
installationId: selectedInstallation.id.toString()
384-
});
385-
386-
server.log.info({
387-
teamId,
388-
installation_id: selectedInstallation.id,
389-
account_login: selectedInstallation.account.login,
390-
total_installations_found: installations.length,
391-
operation: 'auto_linked_installation_after_cleanup'
392-
}, 'Auto-linked GitHub installation to team after cleaning stale record');
393-
394-
const response: ConnectionStatusResponse = { connected: true };
395-
const jsonString = JSON.stringify(response);
396-
return reply.status(200).type('application/json').send(jsonString);
397-
}
398-
} catch (retryError) {
399-
server.log.warn({ error: retryError, teamId }, 'Failed to auto-detect installation after cleanup');
400-
}
401-
322+
// Team must re-install the GitHub App via the /install flow
402323
const response: ConnectionStatusResponse = { connected: false };
403324
const jsonString = JSON.stringify(response);
404325
return reply.status(200).type('application/json').send(jsonString);

services/backend/src/services/deploymentGitHubService.ts

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -132,59 +132,6 @@ export class DeploymentGitHubService {
132132
}
133133
}
134134

135-
/**
136-
* List all GitHub App installations accessible to this app
137-
* Returns installations sorted by most recent (updated_at descending)
138-
* Filters out suspended installations
139-
*/
140-
async listInstallations(): Promise<Array<{
141-
id: number;
142-
account: {
143-
login: string;
144-
id: number;
145-
};
146-
created_at: string;
147-
updated_at: string;
148-
repository_selection: 'all' | 'selected';
149-
suspended_at: string | null;
150-
}>> {
151-
try {
152-
const config = await getGitHubAppConfig();
153-
154-
const appOctokit = new Octokit({
155-
authStrategy: createAppAuth,
156-
auth: {
157-
appId: config.appId,
158-
privateKey: config.privateKey
159-
}
160-
});
161-
162-
// Query GitHub API for all installations
163-
const { data: installations } = await appOctokit.apps.listInstallations({
164-
per_page: 100
165-
});
166-
167-
// Filter out suspended installations and sort by most recent
168-
return installations
169-
.filter(installation => !installation.suspended_at)
170-
.map(installation => ({
171-
id: installation.id,
172-
account: {
173-
login: installation.account?.login || 'unknown',
174-
id: installation.account?.id || 0
175-
},
176-
created_at: installation.created_at,
177-
updated_at: installation.updated_at,
178-
repository_selection: installation.repository_selection as 'all' | 'selected',
179-
suspended_at: installation.suspended_at
180-
}))
181-
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
182-
} catch (error: unknown) {
183-
const message = error instanceof Error ? error.message : 'Unknown error';
184-
throw new Error(`Failed to list GitHub installations: ${message}`);
185-
}
186-
}
187-
188135
/**
189136
* Get repository details
190137
*/

0 commit comments

Comments
 (0)