From ab9f8e158d09212b7e76e4089fdb6cb57717fba3 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Thu, 26 Jun 2025 15:57:09 +1000 Subject: [PATCH] failed merge --- .../EdgeFunctionsDiffPanel.tsx | 63 +++------ apps/studio/pages/project/[ref]/merge.tsx | 126 +++++++++++------- 2 files changed, 97 insertions(+), 92 deletions(-) diff --git a/apps/studio/components/interfaces/BranchManagement/EdgeFunctionsDiffPanel.tsx b/apps/studio/components/interfaces/BranchManagement/EdgeFunctionsDiffPanel.tsx index 3e3dc1a03ca..66d4cf93e76 100644 --- a/apps/studio/components/interfaces/BranchManagement/EdgeFunctionsDiffPanel.tsx +++ b/apps/studio/components/interfaces/BranchManagement/EdgeFunctionsDiffPanel.tsx @@ -5,19 +5,13 @@ import { Card, CardContent, CardHeader, CardTitle, cn } from 'ui' import { Code, Wind } from 'lucide-react' import DiffViewer from 'components/ui/DiffViewer' import { Loading, EmptyState } from 'components/ui/AsyncState' -import useEdgeFunctionsDiff, { - type FileInfo, - type FileStatus, -} from 'hooks/misc/useEdgeFunctionsDiff' +import type { EdgeFunctionsDiffResult, FileInfo, FileStatus } from 'hooks/misc/useEdgeFunctionsDiff' import Link from 'next/link' import { useEffect, useMemo, useState } from 'react' import { basename } from 'path' interface EdgeFunctionsDiffPanelProps { - currentBranchFunctions?: EdgeFunctionsData - mainBranchFunctions?: EdgeFunctionsData - isCurrentFunctionsLoading: boolean - isMainFunctionsLoading: boolean + diffResults: EdgeFunctionsDiffResult currentBranchRef?: string mainBranchRef?: string } @@ -143,36 +137,15 @@ const FunctionDiff = ({ } const EdgeFunctionsDiffPanel = ({ - currentBranchFunctions, - mainBranchFunctions, - isCurrentFunctionsLoading, - isMainFunctionsLoading, + diffResults, currentBranchRef, mainBranchRef, }: EdgeFunctionsDiffPanelProps) => { - const { - addedSlugs, - removedSlugs, - modifiedSlugs, - addedBodiesMap, - removedBodiesMap, - currentBodiesMap, - mainBodiesMap, - functionFileInfo, - isLoading, - hasChanges, - } = useEdgeFunctionsDiff({ - currentBranchFunctions, - mainBranchFunctions, - currentBranchRef, - mainBranchRef, - }) - - if (isCurrentFunctionsLoading || isMainFunctionsLoading || isLoading) { + if (diffResults.isLoading) { return } - if (!hasChanges) { + if (!diffResults.hasChanges) { return ( - {addedSlugs.length > 0 && ( + {diffResults.addedSlugs.length > 0 && (
- {addedSlugs.map((slug) => ( + {diffResults.addedSlugs.map((slug) => ( ))}
)} - {removedSlugs.length > 0 && ( + {diffResults.removedSlugs.length > 0 && (
- {removedSlugs.map((slug) => ( + {diffResults.removedSlugs.map((slug) => ( ))}
)} - {modifiedSlugs.length > 0 && ( + {diffResults.modifiedSlugs.length > 0 && (
- {modifiedSlugs.map((slug) => ( + {diffResults.modifiedSlugs.map((slug) => ( ))}
diff --git a/apps/studio/pages/project/[ref]/merge.tsx b/apps/studio/pages/project/[ref]/merge.tsx index 4dbf7e36ab5..dc8b8358a3d 100644 --- a/apps/studio/pages/project/[ref]/merge.tsx +++ b/apps/studio/pages/project/[ref]/merge.tsx @@ -14,6 +14,7 @@ import { useBranchDiffQuery } from 'data/branches/branch-diff-query' import { useBranchPushMutation } from 'data/branches/branch-push-mutation' import { useMigrationsQuery } from 'data/database/migrations-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' +import useEdgeFunctionsDiff from 'hooks/misc/useEdgeFunctionsDiff' import DatabaseDiffPanel from 'components/interfaces/BranchManagement/DatabaseDiffPanel' import EdgeFunctionsDiffPanel from 'components/interfaces/BranchManagement/EdgeFunctionsDiffPanel' import { Badge, Button, NavMenu, NavMenuItem, cn, Alert } from 'ui' @@ -41,6 +42,9 @@ const MergePage: NextPageWithLayout = () => { // State to track related workflow runs with their project refs const [relatedWorkflowRunIds, setRelatedWorkflowRunIds] = useState>({}) + // State to track failed workflows + const [failedWorkflowIds, setFailedWorkflowIds] = useState>(new Set()) + const isBranch = project?.parent_project_ref !== undefined const parentProjectRef = project?.parent_project_ref @@ -84,8 +88,6 @@ const MergePage: NextPageWithLayout = () => { } ) - console.log('migrations:', currentBranchMigrations, mainBranchMigrations) - // Check if current branch is out of date with main branch const isBranchOutOfDate = useMemo(() => { if (!currentBranchMigrations || !mainBranchMigrations) return false @@ -143,16 +145,23 @@ const MergePage: NextPageWithLayout = () => { ) // Get edge functions for both branches - const { data: currentBranchFunctions, isLoading: isCurrentFunctionsLoading } = - useEdgeFunctionsQuery( - { projectRef: ref }, - { - enabled: gitlessBranching && !!ref, - staleTime: 30000, // 30 seconds - } - ) + const { + data: currentBranchFunctions, + isLoading: isCurrentFunctionsLoading, + refetch: refetchCurrentBranchFunctions, + } = useEdgeFunctionsQuery( + { projectRef: ref }, + { + enabled: gitlessBranching && !!ref, + staleTime: 30000, // 30 seconds + } + ) - const { data: mainBranchFunctions, isLoading: isMainFunctionsLoading } = useEdgeFunctionsQuery( + const { + data: mainBranchFunctions, + isLoading: isMainFunctionsLoading, + refetch: refetchMainBranchFunctions, + } = useEdgeFunctionsQuery( { projectRef: parentProjectRef }, { enabled: gitlessBranching && !!parentProjectRef, @@ -160,6 +169,14 @@ const MergePage: NextPageWithLayout = () => { } ) + // Get edge functions diff + const edgeFunctionsDiff = useEdgeFunctionsDiff({ + currentBranchFunctions, + mainBranchFunctions, + currentBranchRef: ref, + mainBranchRef: parentProjectRef, + }) + // Handle workflow completion - refetch diff once when workflow completes or fails const handleWorkflowStatusChange = useCallback( (status: string, workflowRunId: string) => { @@ -168,12 +185,20 @@ const MergePage: NextPageWithLayout = () => { status === 'MIGRATIONS_FAILED' || status === 'FUNCTIONS_FAILED' + const isFailed = status === 'MIGRATIONS_FAILED' || status === 'FUNCTIONS_FAILED' + + if (isFailed) { + setFailedWorkflowIds((prev) => new Set(prev).add(workflowRunId)) + } + if (isComplete) { - // Refetch diff once when workflow completes + // Refetch diff and edge functions once when workflow completes refetchDiff() + refetchCurrentBranchFunctions() + refetchMainBranchFunctions() } }, - [refetchDiff] + [refetchDiff, refetchCurrentBranchFunctions, refetchMainBranchFunctions] ) // Check if there are any changes (database or edge functions) @@ -181,30 +206,8 @@ const MergePage: NextPageWithLayout = () => { // Check database changes const hasDatabaseChanges = diffContent && diffContent.trim() !== '' - // Check edge function changes - const hasEdgeFunctionChanges = (() => { - if (!currentBranchFunctions || !mainBranchFunctions) return false - - const currentFuncs = currentBranchFunctions || [] - const mainFuncs = mainBranchFunctions || [] - - // Check for added functions - const added = currentFuncs.filter( - (currentFunc) => !mainFuncs.find((mainFunc) => mainFunc.slug === currentFunc.slug) - ) - - // Check for removed functions - const removed = mainFuncs.filter( - (mainFunc) => !currentFuncs.find((currentFunc) => currentFunc.slug === mainFunc.slug) - ) - - // Check for modified functions (functions present in both branches) - const modified = currentFuncs.filter((currentFunc) => - mainFuncs.some((f) => f.slug === currentFunc.slug) - ) - - return added.length > 0 || removed.length > 0 || modified.length > 0 - })() + // Check edge function changes using the diff hook + const hasEdgeFunctionChanges = edgeFunctionsDiff.hasChanges return hasDatabaseChanges || hasEdgeFunctionChanges } @@ -289,10 +292,7 @@ const MergePage: NextPageWithLayout = () => { ) // `hasAnyChanges` should be true only when there are *no* pending changes - const hasAnyChanges = useMemo( - () => !hasChanges(), - [diffContent, currentBranchFunctions, mainBranchFunctions] - ) + const hasAnyChanges = useMemo(() => !hasChanges(), [diffContent, edgeFunctionsDiff.hasChanges]) // Determine current active tab via query param (defaults to 'database') const currentTab = (router.query.tab as string) || 'database' @@ -303,6 +303,10 @@ const MergePage: NextPageWithLayout = () => { // Check if we have any active workflow runs const hasActiveWorkflowRuns = Object.keys(relatedWorkflowRunIds).length > 0 + // Check if current workflow run has failed + const hasCurrentWorkflowFailed = + currentWorkflowRunId && failedWorkflowIds.has(currentWorkflowRunId) + // Navigation items for PageLayout - updates the `tab` query param const navigationItems = useMemo(() => { const buildHref = (tab: string) => { @@ -375,7 +379,11 @@ const MergePage: NextPageWithLayout = () => { ) } - const isDataLoaded = !isDiffLoading && !isCurrentFunctionsLoading && !isMainFunctionsLoading + const isDataLoaded = + !isDiffLoading && + !isCurrentFunctionsLoading && + !isMainFunctionsLoading && + !edgeFunctionsDiff.isLoading const isMergeDisabled = hasAnyChanges && isDataLoaded // Update primary actions - remove push button if branch is out of date (it will be in the notice) @@ -465,6 +473,31 @@ const MergePage: NextPageWithLayout = () => { ) + // Workflow failure notice component + const WorkflowFailureNotice = () => ( + +
+
+

Workflow failed

+

+ The deployment workflow encountered an error. Consider creating a fresh branch from the + latest production branch to resolve potential conflicts. +

+
+ +
+
+ ) + + console.log('workflow:', currentWorkflowRunId) + return ( { >
- {/* Show out of date notice or workflow logs */} + {/* Show out of date notice, workflow failure notice, or workflow logs */} {isBranchOutOfDate && !currentWorkflowRunId ? ( + ) : hasCurrentWorkflowFailed ? ( + ) : currentWorkflowRunId ? ( { /> ) : (