fix(code): cloud repo picker fetches when only team GitHub integration exists#1989
fix(code): cloud repo picker fetches when only team GitHub integration exists#1989VojtechBartos wants to merge 2 commits intomainfrom
Conversation
Repo picker for cloud tasks now flows through useCloudRepositoryIntegration, which prefers the user's personal GitHub integration and falls back to the team integration when the user has not linked one. The saga forwards whichever integration ID is populated, dropping the cloudRunSource gate so team-fallback tasks no longer drop the integration ID before POST. Generated-By: PostHog Code Task-Id: 19c36b01-cbf3-4cd2-b99b-efa50da2256a
…ation Renders an inline amber callout below the cloud repo picker when the user has no personal GitHub linked, with a one-click connect action so PRs can be authored as the user. Extracts the connect flow into a shared useConnectUserGithub hook reused by the inbox banner. Generated-By: PostHog Code Task-Id: 19c36b01-cbf3-4cd2-b99b-efa50da2256a
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/code/src/renderer/hooks/useConnectUserGithub.ts:64
**`window.open` fallback removed**
The original `openUrlInBrowser` helper silently fell back to `window.open` when `trpcClient.os.openExternal.mutate` threw. The new code lets the throw propagate to the outer `catch`, so the user sees an error toast instead of the URL opening. In non-Electron environments (tests, browser builds) or if the IPC channel is unavailable, the install flow now silently fails rather than opening the tab. Consider restoring the fallback:
```suggestion
try {
await trpcClient.os.openExternal.mutate({ url: installUrl });
} catch {
window.open(installUrl, "_blank", "noopener,noreferrer");
}
```
### Issue 2 of 2
apps/code/src/renderer/sagas/task/task-creation.test.ts:466-502
**Missing `prAuthorshipMode` assertion**
The two adjacent tests (user-integration path) both verify `createTaskRunMock` received `prAuthorshipMode: "user"`. For the team-integration path `hasUserGitHubIntegration` is `false`, so the saga should use `prAuthorshipMode: "bot"`. The new test doesn't assert this, leaving the authorship-mode branch for the team fallback untested.
```suggestion
expect(result.success).toBe(true);
expect(createTaskMock).toHaveBeenCalledWith(
expect.objectContaining({
repository: "posthog/posthog",
github_integration: 42,
github_user_integration: undefined,
}),
);
expect(createTaskRunMock).toHaveBeenCalledWith(
"task-123",
expect.objectContaining({
prAuthorshipMode: "bot",
runSource: "manual",
}),
);
```
Reviews (1): Last reviewed commit: "chore(code): notify users when cloud pic..." | Re-trigger Greptile |
| ); | ||
| return; | ||
| } | ||
| await trpcClient.os.openExternal.mutate({ url: installUrl }); |
There was a problem hiding this comment.
The original openUrlInBrowser helper silently fell back to window.open when trpcClient.os.openExternal.mutate threw. The new code lets the throw propagate to the outer catch, so the user sees an error toast instead of the URL opening. In non-Electron environments (tests, browser builds) or if the IPC channel is unavailable, the install flow now silently fails rather than opening the tab. Consider restoring the fallback:
| await trpcClient.os.openExternal.mutate({ url: installUrl }); | |
| try { | |
| await trpcClient.os.openExternal.mutate({ url: installUrl }); | |
| } catch { | |
| window.open(installUrl, "_blank", "noopener,noreferrer"); | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/hooks/useConnectUserGithub.ts
Line: 64
Comment:
**`window.open` fallback removed**
The original `openUrlInBrowser` helper silently fell back to `window.open` when `trpcClient.os.openExternal.mutate` threw. The new code lets the throw propagate to the outer `catch`, so the user sees an error toast instead of the URL opening. In non-Electron environments (tests, browser builds) or if the IPC channel is unavailable, the install flow now silently fails rather than opening the tab. Consider restoring the fallback:
```suggestion
try {
await trpcClient.os.openExternal.mutate({ url: installUrl });
} catch {
window.open(installUrl, "_blank", "noopener,noreferrer");
}
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
mmm maybe we don;t need this
| it("forwards the team GitHub integration when no user integration is selected", async () => { | ||
| const createdTask = createTask({ github_user_integration: null }); | ||
| const startedTask = createTask({ latest_run: createRun() }); | ||
| const createTaskMock = vi.fn().mockResolvedValue(createdTask); | ||
| const createTaskRunMock = vi.fn().mockResolvedValue(createRun()); | ||
| const startTaskRunMock = vi.fn().mockResolvedValue(startedTask); | ||
|
|
||
| const saga = new TaskCreationSaga({ | ||
| posthogClient: { | ||
| createTask: createTaskMock, | ||
| deleteTask: vi.fn(), | ||
| getTask: vi.fn(), | ||
| createTaskRun: createTaskRunMock, | ||
| startTaskRun: startTaskRunMock, | ||
| sendRunCommand: vi.fn(), | ||
| updateTask: vi.fn(), | ||
| } as never, | ||
| }); | ||
|
|
||
| const result = await saga.run({ | ||
| content: "Ship the fix", | ||
| repository: "posthog/posthog", | ||
| workspaceMode: "cloud", | ||
| branch: "main", | ||
| githubIntegrationId: 42, | ||
| }); | ||
|
|
||
| expect(result.success).toBe(true); | ||
| expect(createTaskMock).toHaveBeenCalledWith( | ||
| expect.objectContaining({ | ||
| repository: "posthog/posthog", | ||
| github_integration: 42, | ||
| github_user_integration: undefined, | ||
| }), | ||
| ); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing
prAuthorshipMode assertion
The two adjacent tests (user-integration path) both verify createTaskRunMock received prAuthorshipMode: "user". For the team-integration path hasUserGitHubIntegration is false, so the saga should use prAuthorshipMode: "bot". The new test doesn't assert this, leaving the authorship-mode branch for the team fallback untested.
| it("forwards the team GitHub integration when no user integration is selected", async () => { | |
| const createdTask = createTask({ github_user_integration: null }); | |
| const startedTask = createTask({ latest_run: createRun() }); | |
| const createTaskMock = vi.fn().mockResolvedValue(createdTask); | |
| const createTaskRunMock = vi.fn().mockResolvedValue(createRun()); | |
| const startTaskRunMock = vi.fn().mockResolvedValue(startedTask); | |
| const saga = new TaskCreationSaga({ | |
| posthogClient: { | |
| createTask: createTaskMock, | |
| deleteTask: vi.fn(), | |
| getTask: vi.fn(), | |
| createTaskRun: createTaskRunMock, | |
| startTaskRun: startTaskRunMock, | |
| sendRunCommand: vi.fn(), | |
| updateTask: vi.fn(), | |
| } as never, | |
| }); | |
| const result = await saga.run({ | |
| content: "Ship the fix", | |
| repository: "posthog/posthog", | |
| workspaceMode: "cloud", | |
| branch: "main", | |
| githubIntegrationId: 42, | |
| }); | |
| expect(result.success).toBe(true); | |
| expect(createTaskMock).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| repository: "posthog/posthog", | |
| github_integration: 42, | |
| github_user_integration: undefined, | |
| }), | |
| ); | |
| }); | |
| }); | |
| expect(result.success).toBe(true); | |
| expect(createTaskMock).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| repository: "posthog/posthog", | |
| github_integration: 42, | |
| github_user_integration: undefined, | |
| }), | |
| ); | |
| expect(createTaskRunMock).toHaveBeenCalledWith( | |
| "task-123", | |
| expect.objectContaining({ | |
| prAuthorshipMode: "bot", | |
| runSource: "manual", | |
| }), | |
| ); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/sagas/task/task-creation.test.ts
Line: 466-502
Comment:
**Missing `prAuthorshipMode` assertion**
The two adjacent tests (user-integration path) both verify `createTaskRunMock` received `prAuthorshipMode: "user"`. For the team-integration path `hasUserGitHubIntegration` is `false`, so the saga should use `prAuthorshipMode: "bot"`. The new test doesn't assert this, leaving the authorship-mode branch for the team fallback untested.
```suggestion
expect(result.success).toBe(true);
expect(createTaskMock).toHaveBeenCalledWith(
expect.objectContaining({
repository: "posthog/posthog",
github_integration: 42,
github_user_integration: undefined,
}),
);
expect(createTaskRunMock).toHaveBeenCalledWith(
"task-123",
expect.objectContaining({
prAuthorshipMode: "bot",
runSource: "manual",
}),
);
```
How can I resolve this? If you propose a fix, please make it concise.|
As we discussed over slack, user gh integration is the future way to go, so closing in favour of this one #2027 |
Problem
After #1951, the cloud repo picker only reads from the user's personal GitHub integration. Users without one see an empty picker with no network activity — the inner
useQueriesskips entirely whengithubIntegrations.length === 0.PR authorship-wise, falling back to the team integration is also valid (per the original Slack design: "team integration is still a fallback or primary option in case the user integration is not present or invalid"), but there's nothing in the UI surfacing that fact, so users end up with bot-authored PRs without realizing why.
Solution
useCloudRepositoryIntegration/useCloudGithubRepositories/useCloudGithubBranchesinuseIntegrations.ts. They prefer the user-level integration and fall back to the team integration when no personal one is linked. Both branches are always mounted with mutually-exclusiveenabledgates so React's hook order stays stable.cloudRunSource === "signal_report"gate in the task-creation saga. With the unified picker, mutual exclusion is enforced upstream — the saga just forwards whichever ID is populated.CloudRepoFallbackNotice) when the team-fallback is active, with a one-click "Connect GitHub" action.useConnectUserGithubto deduplicate the connect flow shared with the inboxGitHubConnectionBanner.placeholderData: (prev) => prevtouseUserGithubRepositoriesto match the search-stability fix from fix(repo-selector): preserve results while searching #1968 on the team-side path.Screenshots
Test plan
github_integration/github_user_integration.Created with PostHog Code