From 3f975450a6ac82bac31315218ffc3852fa797adf Mon Sep 17 00:00:00 2001 From: John Sell Date: Thu, 23 Apr 2026 15:36:48 -0400 Subject: [PATCH 1/3] fix(frontend): pass redirect_uri to GitHub App install flow for multi-cluster support When multiple clusters share a single GitHub App, GitHub doesn't know which cluster's callback URL to use. Pass redirect_uri derived from the current origin (or GITHUB_CALLBACK_URL env var) so GitHub redirects back to the correct cluster. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../frontend/src/app/integrations/IntegrationsClient.tsx | 5 +++-- components/frontend/src/app/integrations/page.tsx | 3 ++- .../frontend/src/components/github-connection-card.tsx | 9 ++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/components/frontend/src/app/integrations/IntegrationsClient.tsx b/components/frontend/src/app/integrations/IntegrationsClient.tsx index 15ff44e2f..87ca63a4f 100644 --- a/components/frontend/src/app/integrations/IntegrationsClient.tsx +++ b/components/frontend/src/app/integrations/IntegrationsClient.tsx @@ -10,9 +10,9 @@ import { PageHeader } from '@/components/page-header' import { useIntegrationsStatus } from '@/services/queries/use-integrations' import { Loader2 } from 'lucide-react' -type Props = { appSlug?: string } +type Props = { appSlug?: string; githubCallbackUrl?: string } -export default function IntegrationsClient({ appSlug }: Props) { +export default function IntegrationsClient({ appSlug, githubCallbackUrl }: Props) { const { data: integrations, isLoading, refetch } = useIntegrationsStatus() return ( @@ -38,6 +38,7 @@ export default function IntegrationsClient({ appSlug }: Props) {
+ const githubCallbackUrl = process.env.GITHUB_CALLBACK_URL + return } diff --git a/components/frontend/src/components/github-connection-card.tsx b/components/frontend/src/components/github-connection-card.tsx index 64a27e0a2..0b4b29a09 100644 --- a/components/frontend/src/components/github-connection-card.tsx +++ b/components/frontend/src/components/github-connection-card.tsx @@ -11,6 +11,7 @@ import { toast } from 'sonner' type Props = { appSlug?: string + githubCallbackUrl?: string showManageButton?: boolean status?: { installed: boolean @@ -27,7 +28,7 @@ type Props = { onRefresh?: () => void } -export function GitHubConnectionCard({ appSlug, showManageButton = true, status, onRefresh }: Props) { +export function GitHubConnectionCard({ appSlug, githubCallbackUrl, showManageButton = true, status, onRefresh }: Props) { const disconnectMutation = useDisconnectGitHub() const savePATMutation = useSaveGitHubPAT() const deletePATMutation = useDeleteGitHubPAT() @@ -41,10 +42,8 @@ export function GitHubConnectionCard({ appSlug, showManageButton = true, status, const handleConnect = () => { if (!appSlug) return - // Let GitHub use the Callback URL configured in the App settings - // rather than overriding with redirect_uri (which GitHub ignores - // unless it matches a configured callback URL) - const url = `https://github.com/apps/${appSlug}/installations/new` + const callbackUrl = githubCallbackUrl || `${window.location.origin}/integrations/github/setup` + const url = `https://github.com/apps/${appSlug}/installations/new?redirect_uri=${encodeURIComponent(callbackUrl)}` window.location.href = url } From f90deb604ba065877e748af226b4b2b8248e6af7 Mon Sep 17 00:00:00 2001 From: John Sell Date: Thu, 23 Apr 2026 15:37:17 -0400 Subject: [PATCH 2/3] chore: remove unused imports in runner test Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ambient-runner/tests/test_shared_session_credentials.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/runners/ambient-runner/tests/test_shared_session_credentials.py b/components/runners/ambient-runner/tests/test_shared_session_credentials.py index 070b5934d..133e80450 100755 --- a/components/runners/ambient-runner/tests/test_shared_session_credentials.py +++ b/components/runners/ambient-runner/tests/test_shared_session_credentials.py @@ -12,8 +12,6 @@ import pytest from ambient_runner.platform.auth import ( - _GH_WRAPPER_DIR, - _GH_WRAPPER_PATH, _GITHUB_TOKEN_FILE, _GITLAB_TOKEN_FILE, _fetch_credential, From 39171fa29b113d4ecca89be9515aa17173f37593 Mon Sep 17 00:00:00 2001 From: John Sell Date: Thu, 23 Apr 2026 15:41:34 -0400 Subject: [PATCH 3/3] fix: restore test imports and document GitHub env vars - Revert removal of _GH_WRAPPER_DIR/_PATH imports, add noqa suppression - Document GITHUB_APP_SLUG and GITHUB_CALLBACK_URL in frontend README Co-Authored-By: Claude Opus 4.6 (1M context) --- components/frontend/README.md | 4 ++++ .../ambient-runner/tests/test_shared_session_credentials.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/components/frontend/README.md b/components/frontend/README.md index a672c04eb..114108ad1 100644 --- a/components/frontend/README.md +++ b/components/frontend/README.md @@ -94,6 +94,10 @@ In production, put an OAuth/ingress proxy in front of the app to set these heade - Used by server-side API routes to reach the backend. - `FEEDBACK_URL` (optional) - URL for the feedback link in the masthead. If not set, the link will not appear. +- `GITHUB_APP_SLUG` (required for GitHub integration) + - The slug of the GitHub App (e.g. `ambient-code`). Without this, the Connect button on the Integrations page is disabled. +- `GITHUB_CALLBACK_URL` (optional) + - Explicit callback URL for GitHub App OAuth. Used when multiple clusters share one GitHub App. Falls back to `/integrations/github/setup`. Must be registered as a callback URL in the GitHub App settings. - Optional dev helpers: `OC_USER`, `OC_EMAIL`, `OC_TOKEN`, `ENABLE_OC_WHOAMI=1` You can also put these in a `.env.local` file in this folder: diff --git a/components/runners/ambient-runner/tests/test_shared_session_credentials.py b/components/runners/ambient-runner/tests/test_shared_session_credentials.py index 133e80450..15e7665cd 100755 --- a/components/runners/ambient-runner/tests/test_shared_session_credentials.py +++ b/components/runners/ambient-runner/tests/test_shared_session_credentials.py @@ -12,6 +12,8 @@ import pytest from ambient_runner.platform.auth import ( + _GH_WRAPPER_DIR, # noqa: F401 — used via _auth_mod in gh wrapper tests + _GH_WRAPPER_PATH, # noqa: F401 — used via _auth_mod in gh wrapper tests _GITHUB_TOKEN_FILE, _GITLAB_TOKEN_FILE, _fetch_credential,