diff --git a/frontend/src/lib/components/GitHubAppIntegration.svelte b/frontend/src/lib/components/GitHubAppIntegration.svelte
index 7aa136b072..11844d7d9c 100644
--- a/frontend/src/lib/components/GitHubAppIntegration.svelte
+++ b/frontend/src/lib/components/GitHubAppIntegration.svelte
@@ -55,6 +55,19 @@
)
)
+ // Org names that appear on more than one installation, so the dropdown can
+ // tell those entries apart.
+ let duplicatedAccountIds = $derived(
+ new Set(
+ githubState.workspaceGithubInstallations
+ .filter(
+ (installation, _, array) =>
+ array.filter((other) => other.account_id === installation.account_id).length > 1
+ )
+ .map((installation) => installation.account_id)
+ )
+ )
+
let showGitHubApp = $derived(
resourceType === 'git_repository' &&
$workspaceStore &&
@@ -205,29 +218,47 @@
GitHub Account ID
-
- {#if githubState.selectedGHAppAccountId}
+ {#if githubState.selectedGHAppInstallationId !== undefined}
{@const selectedInstallation = githubState.workspaceGithubInstallations.find(
- (inst) => inst.account_id === githubState.selectedGHAppAccountId
+ (inst) => inst.installation_id === githubState.selectedGHAppInstallationId
)}
{#if selectedInstallation}
Repository
-
+
+ {#key selectedInstallation.installation_id}
+
+ {/key}
{/if}
{/if}
diff --git a/frontend/src/lib/components/RepositorySelector.svelte b/frontend/src/lib/components/RepositorySelector.svelte
index cfeaa3945d..30f8361cbb 100644
--- a/frontend/src/lib/components/RepositorySelector.svelte
+++ b/frontend/src/lib/components/RepositorySelector.svelte
@@ -11,7 +11,7 @@
interface Props {
disabled?: boolean
selectedRepository?: string | undefined
- accountId: string
+ installationId: number
initialRepositories: Repository[]
totalCount: number
perPage: number
@@ -23,7 +23,7 @@
let {
disabled = false,
selectedRepository = $bindable(),
- accountId,
+ installationId,
initialRepositories,
totalCount,
perPage,
@@ -67,8 +67,8 @@
page: nextPage
})
- // Find the matching installation and get its repositories
- const installation = installations.find((inst) => inst.account_id === accountId)
+ // Match on installation_id: several installations can share one account_id
+ const installation = installations.find((inst) => inst.installation_id === installationId)
if (installation?.repositories) {
// Append new repos to existing ones
@@ -95,8 +95,8 @@
}))}
placeholder="Select repository..."
clearable
- disabled={disabled}
- bind:filterText={filterText}
+ {disabled}
+ bind:filterText
bind:value={selectedRepository}
/>
{#if hasMoreRepos}
diff --git a/frontend/src/lib/githubApp.ts b/frontend/src/lib/githubApp.ts
index f60b1f8538..666734546e 100644
--- a/frontend/src/lib/githubApp.ts
+++ b/frontend/src/lib/githubApp.ts
@@ -10,7 +10,12 @@ export interface GitHubAppState {
loadingGithubInstallations: boolean
githubInstallations: GetGlobalConnectedRepositoriesResponse
workspaceGithubInstallations: GetGlobalConnectedRepositoriesResponse
- selectedGHAppAccountId: string | undefined
+ /**
+ * Installations are keyed by `installation_id`, never by `account_id`: an org
+ * can be installed more than once (re-installed, or added from another
+ * workspace), and matching on the org name resolves to the wrong one.
+ */
+ selectedGHAppInstallationId: number | undefined
selectedGHAppRepository: string | undefined
githubInstallationUrl: string | undefined
installationCheckInterval: number | undefined
@@ -25,11 +30,6 @@ export interface GitHubAppState {
isGhesSelfManaged: boolean
}
-export interface GitHubRepository {
- name: string
- url: string
-}
-
export interface GitHubAppError extends Error {
code: 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'AUTH_ERROR' | 'UNKNOWN_ERROR'
details?: unknown
@@ -101,7 +101,7 @@ export function createGitHubAppState(): GitHubAppState {
loadingGithubInstallations: false,
githubInstallations: [],
workspaceGithubInstallations: [],
- selectedGHAppAccountId: undefined,
+ selectedGHAppInstallationId: undefined,
selectedGHAppRepository: undefined,
githubInstallationUrl: undefined,
installationCheckInterval: undefined,
@@ -241,18 +241,6 @@ export function stopInstallationCheck(state: GitHubAppState): void {
state.isCheckingInstallation = false
}
-/**
- * Gets repositories for a specific GitHub account
- */
-export function getRepositories(state: GitHubAppState, accountId: string): GitHubRepository[] {
- if (!accountId) return []
-
- return (
- state.githubInstallations.find((installation) => installation.account_id === accountId)
- ?.repositories || []
- )
-}
-
/**
* Adds a GitHub installation to the current workspace
*/