Skip to content

Enable branching for vercel marketplace #32396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: Add support for branching for Vercel Marketplace resources
  • Loading branch information
kamilogorek committed Dec 30, 2024
commit b442d48f242d2889d749082efba555e443a46150
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
DropdownMenuTrigger,
} from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'

interface IntegrationConnectionItemProps extends IntegrationConnectionProps {
disabled?: boolean
Expand All @@ -30,6 +31,7 @@ interface IntegrationConnectionItemProps extends IntegrationConnectionProps {
const IntegrationConnectionItem = forwardRef<HTMLLIElement, IntegrationConnectionItemProps>(
({ disabled, onDeleteConnection, ...props }, ref) => {
const router = useRouter()
const org = useSelectedOrganization()

const { type, connection } = props
const { data: projects } = useProjectsQuery()
Expand Down Expand Up @@ -113,7 +115,7 @@ const IntegrationConnectionItem = forwardRef<HTMLLIElement, IntegrationConnectio
</Link>
</DropdownMenuItem>
)}
{type === 'Vercel' && (
{type === 'Vercel' && org?.managed_by !== 'vercel-marketplace' && (
<DropdownMenuItem
className="space-x-2"
onSelect={(event) => {
Expand All @@ -130,9 +132,8 @@ const IntegrationConnectionItem = forwardRef<HTMLLIElement, IntegrationConnectio
<p>Resync environment variables</p>
</DropdownMenuItem>
)}
{(type === 'Vercel' || router.pathname !== projectIntegrationUrl) && (
<DropdownMenuSeparator />
)}
{((type === 'Vercel' && org?.managed_by !== 'vercel-marketplace') ||
router.pathname !== projectIntegrationUrl) && <DropdownMenuSeparator />}
<DropdownMenuItem className="space-x-2" onSelect={() => setIsOpen(true)}>
<Trash size={14} />
<p>Delete connection</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import type {
} from 'data/integrations/integrations.types'
import { useVercelConnectionUpdateMutation } from 'data/integrations/vercel-connection-update-mutate'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
Alert_Shadcn_,
FormControl_Shadcn_,
FormDescription_Shadcn_,
FormField_Shadcn_,
Expand All @@ -21,6 +24,8 @@ import {
Input_Shadcn_,
Switch,
} from 'ui'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import Link from 'next/link'

const VercelIntegrationConnectionForm = ({
disabled,
Expand All @@ -31,7 +36,11 @@ const VercelIntegrationConnectionForm = ({
connection: IntegrationProjectConnection
integration: Integration
}) => {
const envSyncTargets = connection.env_sync_targets ?? []
// NOTE(kamil): Ignore sync targets for Vercel Marketplace as it's not synchronized using integration,
// but through a separate marketplace mechanism. It's not theoretically necessary, but we might have some stale data.
const org = useSelectedOrganization()
const envSyncTargets =
org?.managed_by === 'vercel-marketplace' ? [] : connection.env_sync_targets ?? []

const FormSchema = z.object({
environmentVariablesProduction: z.boolean().default(envSyncTargets.includes('production')),
Expand Down Expand Up @@ -88,76 +97,101 @@ const VercelIntegrationConnectionForm = ({
className={'w-full space-y-6'}
>
<div className="px-6 py-4 flex flex-col gap-y-4">
<h5 className="text-foreground text-sm">
Sync environment variables for selected target environments
</h5>
<div className="flex flex-col gap-4">
<FormField_Shadcn_
control={form.control}
name="environmentVariablesProduction"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Production</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>production</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
<FormField_Shadcn_
control={form.control}
name="environmentVariablesPreview"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Preview</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>preview</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
<FormField_Shadcn_
control={form.control}
name="environmentVariablesDevelopment"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Development</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>development</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
{org?.managed_by === 'vercel-marketplace' ? (
<Alert_Shadcn_>
<AlertTitle_Shadcn_ className="text-sm">
Vercel Marketplace managed project
</AlertTitle_Shadcn_>
<AlertDescription_Shadcn_ className="text-xs">
This project is managed via Vercel Marketplace. Environment variables are
automatically synchronized for your connected Vercel projects. This integration
purpose is synchronizing preview deployments environment variables with our{' '}
<Link
target="_blank"
rel="noreferrer"
href="https://supabase.com/docs/guides/platform/branching"
className="underline"
>
Branching
</Link>{' '}
feature.
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
) : (
<div>
<h5 className="text-foreground text-sm">
Sync environment variables for selected target environments
</h5>

<FormField_Shadcn_
control={form.control}
name="environmentVariablesProduction"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Production</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>production</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
<FormField_Shadcn_
control={form.control}
name="environmentVariablesPreview"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Preview</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>preview</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
<FormField_Shadcn_
control={form.control}
name="environmentVariablesDevelopment"
render={({ field }) => (
<FormItem_Shadcn_ className="space-y-0 flex gap-x-4">
<FormControl_Shadcn_>
<Switch
disabled={disabled}
className="mt-1"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl_Shadcn_>
<div>
<FormLabel_Shadcn_ className="!text">Development</FormLabel_Shadcn_>
<FormDescription_Shadcn_ className="text-xs text-foreground-lighter">
Sync environment variables for <code>development</code> environment.
</FormDescription_Shadcn_>
</div>
</FormItem_Shadcn_>
)}
/>
</div>
)}
</div>
<h5 className="mt-2 text-foreground text-sm">
Customize public environment variable prefix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,6 @@ You can change the scope of the access for Supabase by configuring
<ScaffoldSectionContent>
{!canReadVercelConnection ? (
<NoPermission resourceText="view this organization's Vercel connections" />
) : org?.managed_by === 'vercel-marketplace' ? (
<Alert_Shadcn_ className="flex flex-col items-center gap-y-2 border-0 rounded-none">
<PartnerIcon
organization={{ managed_by: 'vercel-marketplace' }}
showTooltip={false}
size="large"
/>

<AlertTitle_Shadcn_ className="text-sm">
Vercel Integration is not available for Vercel Marketplace managed projects.
</AlertTitle_Shadcn_>
</Alert_Shadcn_>
) : (
<>
<Markdown content={VercelContentSectionTop} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { ScaffoldColumn, ScaffoldContainer } from 'components/layouts/Scaffold'
import PasswordStrengthBar from 'components/ui/PasswordStrengthBar'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useIntegrationsQuery } from 'data/integrations/integrations-query'
import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation'
import { useIntegrationVercelConnectionsCreateMutation } from 'data/integrations/integrations-vercel-connections-create-mutation'
import { useVercelProjectsQuery } from 'data/integrations/integrations-vercel-projects-query'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
Expand Down Expand Up @@ -72,7 +71,6 @@ const CreateProject = () => {
const { slug, next, currentProjectId: foreignProjectId, externalId } = useParams()

const { mutateAsync: createConnections } = useIntegrationVercelConnectionsCreateMutation()
const { mutateAsync: syncEnvs } = useIntegrationsVercelConnectionSyncEnvsMutation()

const { data: organizationData } = useOrganizationsQuery()
const organization = organizationData?.find((x) => x.slug === slug)
Expand Down Expand Up @@ -195,8 +193,6 @@ const CreateProject = () => {
},
orgSlug: selectedOrganization?.slug,
})

await syncEnvs({ connectionId })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming this has been removed because it now happens automatically / is no longer needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was always syncing on creation time, not sure why we ever synced twice 😅

} catch (error) {
console.error('An error occurred during createConnections:', error)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import VercelIntegrationWindowLayout from 'components/layouts/IntegrationsLayout
import { ScaffoldColumn, ScaffoldContainer } from 'components/layouts/Scaffold'
import { vercelIcon } from 'components/to-be-cleaned/ListIcons'
import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only'
import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation'
import { useIntegrationVercelConnectionsCreateMutation } from 'data/integrations/integrations-vercel-connections-create-mutation'
import { useVercelProjectsQuery } from 'data/integrations/integrations-vercel-projects-query'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
Expand Down Expand Up @@ -104,17 +103,9 @@ const VercelIntegration: NextPageWithLayout = () => {

const snapshot = useIntegrationInstallationSnapshot()

const { mutateAsync: syncEnvs } = useIntegrationsVercelConnectionSyncEnvsMutation()
const { mutate: createConnections, isLoading: isCreatingConnection } =
useIntegrationVercelConnectionsCreateMutation({
async onSuccess({ id }) {
try {
await syncEnvs({ connectionId: id })
} catch (error: any) {
snapshot.setLoading(false)
toast.error('Failed to sync environment variables: ', error.message)
}

onSuccess() {
if (next) {
snapshot.setLoading(false)
window.location.href = next
Expand Down
16 changes: 1 addition & 15 deletions apps/studio/pages/integrations/vercel/install.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ const VercelIntegration: NextPageWithLayout = () => {
: false
}, [installed, selectedOrg, source, dataLoading])

const hasVercelManagedOrgSelected = useMemo(() => {
return !!selectedOrg && selectedOrg.managed_by === 'vercel-marketplace'
}, [selectedOrg])

const disableInstallationForm =
(isLoadingVercelIntegrationCreateMutation && !dataLoading) ||
// disables installation button if integration is already installed and it is Marketplace flow
Expand Down Expand Up @@ -231,21 +227,11 @@ const VercelIntegration: NextPageWithLayout = () => {
</AlertDescription_Shadcn_>
</Alert_Shadcn_>
)}
{hasVercelManagedOrgSelected && (
<p className="prose text-sm text-red-900">
Vercel Integration cannot be used with Vercel-managed organizations. Choose a
different organization or create a Vercel resource directly.
</p>
)}
<div className="flex flex-row w-full justify-end">
<Button
size="medium"
className="self-end"
disabled={
disableInstallationForm ||
isLoadingVercelIntegrationCreateMutation ||
hasVercelManagedOrgSelected
}
disabled={disableInstallationForm || isLoadingVercelIntegrationCreateMutation}
loading={isLoadingVercelIntegrationCreateMutation}
onClick={onInstall}
>
Expand Down