import { zodResolver } from '@hookform/resolvers/zod' import { Check, ChevronDown, GitBranch, RotateCcw, Shield } from 'lucide-react' import { useRef, useState } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import * as z from 'zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import { useBranchesQuery } from 'data/branches/branches-query' import { useGitHubBranchesQuery } from 'data/integrations/github-branches-query' import { useGitHubConnectionUpdateMutation } from 'data/integrations/github-connection-update-mutation' import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { useSelectedProject } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, CommandEmpty_Shadcn_, CommandGroup_Shadcn_, CommandInput_Shadcn_, CommandItem_Shadcn_, CommandList_Shadcn_, Command_Shadcn_, FormControl_Shadcn_, FormDescription_Shadcn_, FormField_Shadcn_, FormItem_Shadcn_, FormLabel_Shadcn_, Form_Shadcn_, Input_Shadcn_, Label_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, Switch, WarningIcon, cn, } from 'ui' interface GitHubIntegrationConnectionFormProps { disabled?: boolean connection: IntegrationProjectConnection } const GitHubIntegrationConnectionForm = ({ disabled, connection, }: GitHubIntegrationConnectionFormProps) => { const org = useSelectedOrganization() const project = useSelectedProject() const [open, setOpen] = useState(false) const comboBoxRef = useRef(null) const isBranchingEnabled = project?.is_branch_enabled === true || project?.parent_project_ref !== undefined const canUpdateGitHubConnection = useCheckPermissions( PermissionAction.UPDATE, 'integrations.github_connections' ) const { data: githubBranches, isLoading: isLoadingBranches } = useGitHubBranchesQuery( { connectionId: Number(connection.id), }, { enabled: isBranchingEnabled } ) const { mutate: updateConnection, isLoading: isUpdatingConnection } = useGitHubConnectionUpdateMutation({ onSuccess: () => toast.success('Successfully updated connection settings'), }) const { mutate: updateBranch, isLoading: isUpdatingProdBranch } = useBranchUpdateMutation({ onSuccess: (data) => { toast.success(`Successfully updated production branch to ${data.git_branch}`) setOpen(false) }, }) const { data: previewBranches } = useBranchesQuery( { projectRef: project?.parentRef }, { enabled: project !== undefined } ) const productionPreviewBranch = previewBranches?.find((branch) => branch.is_default) function onUpdateProductionBranch(branchName: string) { if (!project?.parentRef) return if (!productionPreviewBranch) return updateBranch({ id: productionPreviewBranch.id, projectRef: project.parentRef, branchName: branchName, gitBranch: branchName, }) } const FormSchema = z.object({ supabaseDirectory: z .string() .default(connection.metadata?.supabaseConfig?.supabaseDirectory ?? ''), supabaseChangesOnly: z .boolean() .default(connection.metadata?.supabaseConfig?.supabaseChangesOnly ?? false), branchLimit: z.string().default(String(connection.metadata?.supabaseConfig?.branchLimit ?? 50)), }) const form = useForm>({ resolver: zodResolver(FormSchema), defaultValues: { supabaseDirectory: connection?.metadata?.supabaseConfig?.supabaseDirectory, supabaseChangesOnly: connection?.metadata?.supabaseConfig?.supabaseChangesOnly, branchLimit: String(connection?.metadata?.supabaseConfig?.branchLimit), }, }) function onSubmit(data: z.infer) { if (org?.id === undefined) return console.error('Org ID is required') updateConnection({ connectionId: connection.id, organizationId: org?.id, workdir: data.supabaseDirectory, supabaseChangesOnly: data.supabaseChangesOnly, branchLimit: Number(data.branchLimit), }) } return (
{isBranchingEnabled ? (
Production branch

All other branches will be treated as Preview branches

Changing Git branch for Production Branch coming soon If you wish to change the Git branch that is used for the Production Branch you will need to disable Branching and opt back in. {/*
! This should only work if branching is turned on !
*/} No branches found {githubBranches?.map((branch) => { const active = branch.name === productionPreviewBranch?.git_branch return ( { setOpen(false) onUpdateProductionBranch(branch.name) }} >
{active ? ( ) : ( )} {branch.name}
{branch.name === productionPreviewBranch?.git_branch && }
) })}
) : (
Branching is not enabled This integration has no effect without Branching feature being active.
Make sure to enable it using "Enable branching" button at the top of the page first.
)}
( Branch limit Total number of branches that can be automatically created for this connection.
{ if (event.key === 'Escape') form.reset() }} type="number" /> form.reset()} />
)} /> ( Supabase directory Path in your repository where supabase directory for this connection lives.
{ if (event.key === 'Escape') form.reset() }} /> form.reset()} />
)} /> ( { field.onChange(e) form.handleSubmit(onSubmit)() }} />
Supabase changes only Trigger branch creation only when there were changes to supabase{' '} directory.
)} />
) } export default GitHubIntegrationConnectionForm