diff --git a/apps/studio/components/interfaces/BranchManagement/ConnectToGitHub.tsx b/apps/studio/components/interfaces/BranchManagement/ConnectToGitHub.tsx
new file mode 100644
index 00000000000..d4256ee9e34
--- /dev/null
+++ b/apps/studio/components/interfaces/BranchManagement/ConnectToGitHub.tsx
@@ -0,0 +1,56 @@
+import { useParams } from 'common'
+import { Github } from 'lucide-react'
+import { useRouter } from 'next/router'
+import { Button } from 'ui'
+
+import { useGitHubAuthorizationQuery } from '@/data/integrations/github-authorization-query'
+import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
+import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
+import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
+import { openInstallGitHubIntegrationWindow } from '@/lib/github'
+import { useAppStateSnapshot } from '@/state/app-state'
+
+export const ConnectToGitHub = () => {
+ const router = useRouter()
+ const { ref } = useParams()
+ const { data: project } = useSelectedProjectQuery()
+ const { data: selectedOrg } = useSelectedOrganizationQuery()
+ const { showCreateBranchModal, setShowCreateBranchModal } = useAppStateSnapshot()
+
+ const isBranch = project?.parent_project_ref !== undefined
+ const projectRef =
+ project !== undefined ? (isBranch ? project.parent_project_ref : ref) : undefined
+
+ const { data: gitHubAuthorization } = useGitHubAuthorizationQuery()
+
+ const { data: connections } = useGitHubConnectionsQuery(
+ { organizationId: selectedOrg?.id },
+ { enabled: showCreateBranchModal }
+ )
+ const githubConnection = connections?.find((connection) => connection.project.ref === projectRef)
+
+ const showAuthorizeCta = githubConnection && !gitHubAuthorization
+
+ const onClick = () => {
+ if (showAuthorizeCta) {
+ openInstallGitHubIntegrationWindow('authorize')
+ } else {
+ if (showCreateBranchModal) setShowCreateBranchModal(false)
+ router.push(`/project/${projectRef}/settings/integrations`)
+ }
+ }
+
+ return (
+
+
+
Sync with a GitHub branch
+
+ Keep this preview branch in sync with a chosen GitHub branch
+
+
+
} onClick={onClick}>
+ {showAuthorizeCta ? 'Authorize' : 'Configure'}
+
+
+ )
+}
diff --git a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx
index 1f50e17d6d6..d282a1e5eeb 100644
--- a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx
+++ b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx
@@ -3,7 +3,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
import { useDebounce } from '@uidotdev/usehooks'
import { useFlag, useParams } from 'common'
-import { Check, DatabaseZap, DollarSign, Github, GitMerge, Loader2 } from 'lucide-react'
+import { Check, DatabaseZap, DollarSign, GitMerge, Loader2 } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
@@ -25,7 +25,6 @@ import {
FormControl,
FormField,
Input,
- Label,
Switch,
Tooltip,
TooltipContent,
@@ -40,6 +39,7 @@ import {
estimateDiskCost,
estimateRestoreTime,
} from './BranchManagement.utils'
+import { ConnectToGitHub } from './ConnectToGitHub'
import { TaxDisclaimer } from '@/components/interfaces/Billing/TaxDisclaimer'
import { getInfrastructurePath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils'
import { BranchingPITRNotice } from '@/components/layouts/AppLayout/EnableBranchingButton/BranchingPITRNotice'
@@ -50,6 +50,7 @@ import { UpgradeToPro } from '@/components/ui/UpgradeToPro'
import { useBranchCreateMutation } from '@/data/branches/branch-create-mutation'
import { useBranchesQuery } from '@/data/branches/branches-query'
import { DiskAttributesData, useDiskAttributesQuery } from '@/data/config/disk-attributes-query'
+import { useGitHubAuthorizationQuery } from '@/data/integrations/github-authorization-query'
import { useCheckGithubBranchValidity } from '@/data/integrations/github-branch-check-query'
import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
import { projectKeys } from '@/data/projects/keys'
@@ -118,6 +119,14 @@ export const CreateBranchModal = () => {
})
const debouncedGitBranchName = useDebounce(gitBranchName, 500)
+ const {
+ data: githubAuthorization,
+ error: authorizationError,
+ isPending: isLoadingAuthorization,
+ isSuccess: isSuccessAuthorization,
+ isError: isErrorAuthorization,
+ } = useGitHubAuthorizationQuery()
+
const {
data: connections,
error: connectionsError,
@@ -129,6 +138,11 @@ export const CreateBranchModal = () => {
{ enabled: showCreateBranchModal }
)
+ const isLoading = isLoadingAuthorization || isLoadingConnections
+ const isSuccess = isSuccessAuthorization && isSuccessConnections
+ const isError = isErrorAuthorization || isErrorConnections
+ const error = authorizationError || connectionsError
+
const { data: branches } = useBranchesQuery({ projectRef })
const { data: addons, isSuccess: isSuccessAddons } = useProjectAddonsQuery(
{ projectRef },
@@ -260,11 +274,6 @@ export const CreateBranchModal = () => {
})
}
- const handleGitHubClick = () => {
- setShowCreateBranchModal(false)
- router.push(`/project/${projectRef}/settings/integrations`)
- }
-
useEffect(() => {
if (showCreateBranchModal) form.reset()
}, [form, showCreateBranchModal])
@@ -323,22 +332,24 @@ export const CreateBranchModal = () => {
)}
/>
- {isLoadingConnections && (
+ {isLoading && (
)}
- {isErrorConnections && (
+ {isError && (
)}
- {isSuccessConnections &&
- (githubConnection ? (
+ {isSuccess &&
+ (!githubAuthorization || !githubConnection ? (
+
+ ) : (
{
}
labelOptional="Optional"
- description="Automatically deploy changes on every commit"
+ description={
+ githubAuthorization
+ ? 'Automatically deploy changes on every commit'
+ : undefined
+ }
>
@@ -394,18 +409,6 @@ export const CreateBranchModal = () => {
)}
/>
- ) : (
-
-
-
-
- Keep this preview branch in sync with a chosen GitHub branch
-
-
-
} onClick={handleGitHubClick}>
- Configure
-
-
))}
{allowDataBranching && (
@@ -416,7 +419,7 @@ export const CreateBranchModal = () => {
-
+ Include data
{!hasPitrEnabled && Requires PITR}
>
}
@@ -426,6 +429,7 @@ export const CreateBranchModal = () => {
>
{
const { ref } = useParams()
- const router = useRouter()
const { data: projectDetails } = useSelectedProjectQuery()
const { data: selectedOrg } = useSelectedOrganizationQuery()
@@ -55,6 +54,14 @@ export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalPro
const projectRef =
projectDetails !== undefined ? (isBranch ? projectDetails.parent_project_ref : ref) : undefined
+ const {
+ data: githubAuthorization,
+ error: authorizationError,
+ isPending: isLoadingAuthorization,
+ isSuccess: isSuccessAuthorization,
+ isError: isErrorAuthorization,
+ } = useGitHubAuthorizationQuery()
+
const {
data: connections,
error: connectionsError,
@@ -65,6 +72,11 @@ export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalPro
organizationId: selectedOrg?.id,
})
+ const isLoading = isLoadingAuthorization || isLoadingConnections
+ const isSuccess = isSuccessAuthorization && isSuccessConnections
+ const isError = isErrorAuthorization || isErrorConnections
+ const error = authorizationError || connectionsError
+
const { data: branches } = useBranchesQuery({ projectRef })
const { mutate: checkGithubBranchValidity, isPending: isChecking } = useCheckGithubBranchValidity(
{ onError: () => {} }
@@ -113,14 +125,6 @@ export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalPro
const isFormValid = form.formState.isValid && (!gitBranchName || isGitBranchValid)
const canSubmit = isFormValid && !isUpdating && !isChecking
- const openLinkerPanel = () => {
- onClose()
-
- if (projectRef) {
- router.push(`/project/${projectRef}/settings/integrations`)
- }
- }
-
const onSubmit = (data: z.infer) => {
if (!projectRef) return console.error('Project ref is required')
if (!branch?.project_ref) return console.error('Branch ref is required')
@@ -179,8 +183,9 @@ export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalPro
if (form.getValues('gitBranchName') !== requested) return
setIsGitBranchValid(false)
form.setError('gitBranchName', {
- ...error,
- message: `Unable to find branch "${branchName}" in ${repoOwner}/${repoName}`,
+ message:
+ error?.message ??
+ `Unable to find branch "${branchName}" in ${repoOwner}/${repoName}`,
})
},
}
@@ -234,22 +239,24 @@ export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalPro
)}
/>
- {isLoadingConnections && (
+ {isLoading && (
)}
- {isErrorConnections && (
+ {isError && (
)}
- {isSuccessConnections &&
- (githubConnection ? (
+ {isSuccess &&
+ (!githubAuthorization || !githubConnection ? (
+
+ ) : (
)}
/>
- ) : (
-
-
-
-
-
-
- Optionally connect to a GitHub repository to manage migrations automatically
- for this branch.
-
-
-
} onClick={openLinkerPanel}>
- Connect to GitHub
-
-
))}