mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
feat: add a dashboard button to retrigger a branch workflow (#46626)
## Problem When workflow runs for branches fail due to stuck tasks, they can sit idle indefinitely. Users are unaware that they need to make a new commit to retrigger the workflow — leading to confusion, wasted time, and silent failures going unnoticed. ## Solution Provide a button that allows users to retrigger a workflow when it is not being removed. ## How to test - Create a branch - Wait for its row to appear on the branch management page - Click the _View logs_ button - You should see a _Retrigger_ button - Clicking it should make a new row appear in those logs <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Retrigger previously executed workflows directly from branch preview actions. * Confirmation dialog added for retrigger actions. * **Improvements** * Toast-style error notifications when retriggering fails. * Workflow run list layout updated for a more flexible horizontal display. * After retriggering, workflow and action lists refresh so updates appear promptly. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
1673012bc7
commit
375cbcf4a2
3 files changed
+85
-24
No files matched your search
@@ -8,6 +8,7 @@ import {
|
||||
Infinity,
|
||||
MoreVertical,
|
||||
Pencil,
|
||||
Redo,
|
||||
RefreshCw,
|
||||
Shield,
|
||||
Trash2,
|
||||
@@ -30,6 +31,7 @@ import { EditBranchModal } from './EditBranchModal'
|
||||
import { PreviewBranchesEmptyState } from './EmptyStates'
|
||||
import { DropdownMenuItemTooltip } from '@/components/ui/DropdownMenuItemTooltip'
|
||||
import { TextConfirmModal } from '@/components/ui/TextConfirmModalWrapper'
|
||||
import { useBranchPushMutation } from '@/data/branches/branch-push-mutation'
|
||||
import { useBranchQuery } from '@/data/branches/branch-query'
|
||||
import { useBranchResetMutation } from '@/data/branches/branch-reset-mutation'
|
||||
import { useBranchRestoreMutation } from '@/data/branches/branch-restore-mutation'
|
||||
@@ -262,6 +264,7 @@ const PreviewBranchActions = ({
|
||||
setShowPersistentBranchDeleteConfirmationModal,
|
||||
] = useState(false)
|
||||
const [showEditBranchModal, setShowEditBranchModal] = useState(false)
|
||||
const [showConfirmRetriggersModal, setShowConfirmRetriggersModal] = useState(false)
|
||||
|
||||
const { mutate: resetBranch, isPending: isResetting } = useBranchResetMutation({
|
||||
onSuccess() {
|
||||
@@ -286,6 +289,20 @@ const PreviewBranchActions = ({
|
||||
},
|
||||
})
|
||||
|
||||
const { mutate: branchPushMutate, isPending: isRetriggering } = useBranchPushMutation({
|
||||
onSuccess() {
|
||||
toast.success('Success! Please allow a few minutes for the branch to update.')
|
||||
setShowConfirmRetriggersModal(false)
|
||||
},
|
||||
onError: (data) => {
|
||||
toast.error(`Failed to trigger workflow: ${data.message}`)
|
||||
},
|
||||
})
|
||||
|
||||
const onRetriggerBranch = () => {
|
||||
branchPushMutate({ branchRef, projectRef })
|
||||
}
|
||||
|
||||
const onRestoreBranch = () => {
|
||||
restoreBranch({ branchRef, projectRef })
|
||||
}
|
||||
@@ -345,28 +362,54 @@ const PreviewBranchActions = ({
|
||||
</DropdownMenuItemTooltip>
|
||||
|
||||
{!branch.deletion_scheduled_at && (
|
||||
<DropdownMenuItemTooltip
|
||||
className="gap-x-2"
|
||||
disabled={isResetting || !isBranchActiveHealthy}
|
||||
onSelect={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmResetModal(true)
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmResetModal(true)
|
||||
}}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'left',
|
||||
text: !isBranchActiveHealthy
|
||||
? 'Branch is still initializing. Please wait for it to become healthy before resetting.'
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<RefreshCw size={14} /> Reset branch
|
||||
</DropdownMenuItemTooltip>
|
||||
<>
|
||||
<DropdownMenuItemTooltip
|
||||
className="gap-x-2"
|
||||
disabled={!canUpdateBranches || !isBranchActiveHealthy || isUpdatingBranch}
|
||||
onSelect={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmRetriggersModal(true)
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmRetriggersModal(true)
|
||||
}}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'left',
|
||||
text: !canUpdateBranches
|
||||
? `You need additional permissions to ${branch.git_branch ? 'resync' : 'rebase'} branches`
|
||||
: !isBranchActiveHealthy
|
||||
? `Branch is still initializing. Please wait for it to become healthy before ${branch.git_branch ? 'resyncing' : 'rebasing'}.`
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Redo size={14} /> {branch.git_branch ? 'Resync branch' : 'Rebase branch'}
|
||||
</DropdownMenuItemTooltip>
|
||||
<DropdownMenuItemTooltip
|
||||
className="gap-x-2"
|
||||
disabled={isResetting || !isBranchActiveHealthy}
|
||||
onSelect={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmResetModal(true)
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setShowConfirmResetModal(true)
|
||||
}}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'left',
|
||||
text: !isBranchActiveHealthy
|
||||
? 'Branch is still initializing. Please wait for it to become healthy before resetting.'
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<RefreshCw size={14} /> Reset branch
|
||||
</DropdownMenuItemTooltip>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!branch.deletion_scheduled_at && (
|
||||
@@ -497,10 +540,26 @@ const PreviewBranchActions = ({
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
variant="default"
|
||||
visible={showConfirmRetriggersModal}
|
||||
confirmLabel={branch.git_branch ? 'Resync' : 'Rebase'}
|
||||
title={branch.git_branch ? 'Confirm branch resync' : 'Confirm branch rebase'}
|
||||
loading={isRetriggering}
|
||||
onCancel={() => setShowConfirmRetriggersModal(false)}
|
||||
onConfirm={onRetriggerBranch}
|
||||
>
|
||||
<p className="text-sm text-foreground-light">
|
||||
{branch.git_branch
|
||||
? 'This will re-run all steps of the workflow based on the latest git branch state.'
|
||||
: 'This will re-run all steps of the workflow based on the latest dashboard state.'}
|
||||
</p>
|
||||
</ConfirmationModal>
|
||||
|
||||
<ConfirmationModal
|
||||
variant="warning"
|
||||
visible={showPersistentBranchDeleteConfirmationModal}
|
||||
confirmLabel={'Switch to preview'}
|
||||
confirmLabel="Switch to preview"
|
||||
title="Branch must be switched to preview before deletion"
|
||||
loading={isUpdatingBranch}
|
||||
onCancel={() => setShowPersistentBranchDeleteConfirmationModal(false)}
|
||||
|
||||
@@ -111,7 +111,7 @@ export const WorkflowLogs = ({ branch }: WorkflowLogsProps) => {
|
||||
(workflowRuns.length > 0 ? (
|
||||
<ul className="divide-y">
|
||||
{workflowRuns.map((workflowRun) => (
|
||||
<li key={workflowRun.id} className="px-4 py-3">
|
||||
<li key={workflowRun.id} className="flex justify-between px-4 py-3 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
disabled={workflowRun.id === projectRef}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { actionKeys } from '../actions/keys'
|
||||
import { branchKeys } from './keys'
|
||||
import { handleError, post } from '@/data/fetchers'
|
||||
import type { ResponseError, UseCustomMutationOptions } from '@/types'
|
||||
@@ -36,6 +37,7 @@ export const useBranchPushMutation = ({
|
||||
async onSuccess(data, variables, context) {
|
||||
const { projectRef } = variables
|
||||
await queryClient.invalidateQueries({ queryKey: branchKeys.list(projectRef) })
|
||||
await queryClient.invalidateQueries({ queryKey: actionKeys.list(projectRef) })
|
||||
await onSuccess?.(data, variables, context)
|
||||
},
|
||||
async onError(data, variables, context) {
|
||||
|
||||
Reference in new issue
Block a user