Skip to content

Commit

Permalink
Add a restart run button (#980)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljguarino authored May 25, 2024
1 parent 58074b5 commit fb53605
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 20 deletions.
45 changes: 41 additions & 4 deletions assets/src/components/stacks/run/Sidecar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import React, { ReactNode } from 'react'
import { Button, Sidecar, SidecarItem } from '@pluralsh/design-system'
import { ReactNode } from 'react'
import {
Button,
ReloadIcon,
Sidecar,
SidecarItem,
} from '@pluralsh/design-system'

import { useTheme } from 'styled-components'
import moment from 'moment'

import { GqlError } from 'components/utils/Alert'

import { useNavigate, useParams } from 'react-router-dom'

import { getStackRunsAbsPath } from 'routes/stacksRoutesConsts'

import {
StackRun,
StackStatus,
useApproveStackRunMutation,
useRestartStackRunMutation,
} from '../../../generated/graphql'
import { ResponsiveLayoutSidecarContainer } from '../../utils/layout/ResponsiveLayoutSidecarContainer'
import UserInfo from '../../utils/UserInfo'
Expand All @@ -19,19 +30,36 @@ interface StackRunSidecarProps {
refetch?: Nullable<() => void>
}

const TERMINAL_STATES = [
StackStatus.Successful,
StackStatus.Cancelled,
StackStatus.Failed,
]

export default function StackRunSidecar({
stackRun,
refetch,
}: StackRunSidecarProps): ReactNode {
const { stackId } = useParams()
const theme = useTheme()
const navigate = useNavigate()

const [mutation, { loading, error }] = useApproveStackRunMutation({
variables: { id: stackRun.id },
onCompleted: () => refetch?.(),
})

const [restart, { loading: restartLoading, error: restartError }] =
useRestartStackRunMutation({
variables: { id: stackRun.id },
onCompleted: ({ restartStackRun }) =>
navigate(getStackRunsAbsPath(stackId, restartStackRun?.id)),
})

const terminal = TERMINAL_STATES.includes(stackRun.status)

if (error) return <GqlError error={error} />
console.log(stackRun)
if (restartError) return <GqlError error={restartError} />

return (
<ResponsiveLayoutSidecarContainer
Expand All @@ -47,8 +75,17 @@ export default function StackRunSidecar({
Approve Run
</Button>
)}
{terminal && (
<Button
secondary
onClick={restart}
loading={restartLoading}
startIcon={<ReloadIcon />}
>
Restart Run
</Button>
)}
<Sidecar>
<SidecarItem heading="ID">{stackRun.id}</SidecarItem>
<SidecarItem heading="Needs approval">
{stackRun.approval ? 'Required' : 'Not required'}
</SidecarItem>
Expand Down
2 changes: 1 addition & 1 deletion assets/src/components/stacks/run/Sidenav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function StackRunSidenavHeader({
}}
>
<AppIcon
icon={<StackTypeIcon stackType={stackRun.type} />}
icon={<StackTypeIcon stackType={stackRun.type} size={36} />}
size="small"
/>
<StackedText
Expand Down
22 changes: 15 additions & 7 deletions assets/src/components/stacks/run/plan/Plan.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import { ReactNode } from 'react'
import { useOutletContext } from 'react-router-dom'
import { CodeEditor } from '@pluralsh/design-system'

import CommandLog from 'components/builds/build/progress/CommandLog'
import { Card } from '@pluralsh/design-system'

import { StackRun } from '../../../../generated/graphql'

export default function StackRunPlan(): ReactNode {
const { stackRun } = useOutletContext<{ stackRun: StackRun }>()
const value = JSON.parse(stackRun.state?.plan ?? '{}')
const value = stackRun.state?.plan ?? ''

return (
<CodeEditor
value={JSON.stringify(value, null, 2)}
language="json"
options={{ readOnly: true }}
/>
<Card
flexGrow={1}
fontFamily="Monument Mono"
overflowY="auto"
maxHeight="100%"
>
<CommandLog
text={value}
follow={false}
/>
</Card>
)
}
20 changes: 19 additions & 1 deletion assets/src/components/stacks/run/progress/Progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,33 @@ import { ReactNode, useMemo } from 'react'
import { useOutletContext } from 'react-router-dom'
import sortBy from 'lodash/sortBy'

import { StackRun } from '../../../../generated/graphql'
import { StackRun, StepStatus } from '../../../../generated/graphql'

import Step from './Step'

function currentStep(steps) {
for (let i = steps.length - 1; i > 0; i--) {
const { status } = steps[i]

if (
status === StepStatus.Running ||
status === StepStatus.Successful ||
status === StepStatus.Failed
) {
return steps[i].id
}
}

return steps[0].id
}

export default function StackRunProgress(): ReactNode {
const { stackRun } = useOutletContext<{ stackRun: StackRun }>()
const sorted = useMemo(
() => sortBy(stackRun.steps, (s) => s?.index),
[stackRun.steps]
)
const openId = currentStep(sorted)

return (
<ScrollablePage
Expand All @@ -31,6 +48,7 @@ export default function StackRunProgress(): ReactNode {
<Step
key={s!.id}
step={s!}
open={s!.id === openId}
/>
))}
</Card>
Expand Down
13 changes: 7 additions & 6 deletions assets/src/components/stacks/run/progress/Step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ import CommandLog from '../../../builds/build/progress/CommandLog'

interface StepProps {
step: RunStep
open?: boolean
}

export default function Step({ step }: StepProps): ReactNode {
export default function Step({ step, open }: StepProps): ReactNode {
const ref = useRef<any>()

const [folded, setFolded] = useState(
step.status === StepStatus.Successful || step.status === StepStatus.Pending
)
const [folded, setFolded] = useState<boolean | undefined>(undefined)
const [logs, setLogs] = useState(step?.logs as Array<RunLogs>)

const command = useMemo(
Expand Down Expand Up @@ -62,6 +61,8 @@ export default function Step({ step }: StepProps): ReactNode {
setLogs(step?.logs as Array<RunLogs>)
}, [step?.logs])

const show = folded === undefined ? open : !folded

return (
<Div ref={ref}>
<Flex
Expand All @@ -83,7 +84,7 @@ export default function Step({ step }: StepProps): ReactNode {
align="center"
grow={1}
>
{folded ? (
{!show ? (
<CaretRightIcon
size={12}
paddingRight="small"
Expand All @@ -98,7 +99,7 @@ export default function Step({ step }: StepProps): ReactNode {
</Flex>
<Status status={step.status} />
</Flex>
{!folded && (
{show && (
<CommandLog
text={toLogsString(logs)}
follow={step.status === StepStatus.Running}
Expand Down
41 changes: 41 additions & 0 deletions assets/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8773,6 +8773,13 @@ export type ApproveStackRunMutationVariables = Exact<{

export type ApproveStackRunMutation = { __typename?: 'RootMutationType', approveStackRun?: { __typename?: 'StackRun', id: string, insertedAt?: string | null, message?: string | null, status: StackStatus, approval?: boolean | null, approvedAt?: string | null, git: { __typename?: 'GitRef', ref: string }, approver?: { __typename?: 'User', name: string, email: string } | null } | null };

export type RestartStackRunMutationVariables = Exact<{
id: Scalars['ID']['input'];
}>;


export type RestartStackRunMutation = { __typename?: 'RootMutationType', restartStackRun?: { __typename?: 'StackRun', id: string, insertedAt?: string | null, message?: string | null, status: StackStatus, approval?: boolean | null, approvedAt?: string | null, git: { __typename?: 'GitRef', ref: string }, approver?: { __typename?: 'User', name: string, email: string } | null } | null };

export type LogsDeltaSubscriptionVariables = Exact<{
id: Scalars['ID']['input'];
}>;
Expand Down Expand Up @@ -17826,6 +17833,39 @@ export function useApproveStackRunMutation(baseOptions?: Apollo.MutationHookOpti
export type ApproveStackRunMutationHookResult = ReturnType<typeof useApproveStackRunMutation>;
export type ApproveStackRunMutationResult = Apollo.MutationResult<ApproveStackRunMutation>;
export type ApproveStackRunMutationOptions = Apollo.BaseMutationOptions<ApproveStackRunMutation, ApproveStackRunMutationVariables>;
export const RestartStackRunDocument = gql`
mutation RestartStackRun($id: ID!) {
restartStackRun(id: $id) {
...StackRun
}
}
${StackRunFragmentDoc}`;
export type RestartStackRunMutationFn = Apollo.MutationFunction<RestartStackRunMutation, RestartStackRunMutationVariables>;

/**
* __useRestartStackRunMutation__
*
* To run a mutation, you first call `useRestartStackRunMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useRestartStackRunMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [restartStackRunMutation, { data, loading, error }] = useRestartStackRunMutation({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useRestartStackRunMutation(baseOptions?: Apollo.MutationHookOptions<RestartStackRunMutation, RestartStackRunMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<RestartStackRunMutation, RestartStackRunMutationVariables>(RestartStackRunDocument, options);
}
export type RestartStackRunMutationHookResult = ReturnType<typeof useRestartStackRunMutation>;
export type RestartStackRunMutationResult = Apollo.MutationResult<RestartStackRunMutation>;
export type RestartStackRunMutationOptions = Apollo.BaseMutationOptions<RestartStackRunMutation, RestartStackRunMutationVariables>;
export const LogsDeltaDocument = gql`
subscription LogsDelta($id: ID!) {
runLogsDelta(stepId: $id) {
Expand Down Expand Up @@ -18440,6 +18480,7 @@ export const namedOperations = {
DeleteStack: 'DeleteStack',
KickStack: 'KickStack',
ApproveStackRun: 'ApproveStackRun',
RestartStackRun: 'RestartStackRun',
CreateAccessToken: 'CreateAccessToken',
DeleteAccessToken: 'DeleteAccessToken',
Logout: 'Logout'
Expand Down
6 changes: 6 additions & 0 deletions assets/src/graph/stacks.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ mutation ApproveStackRun($id: ID!) {
}
}

mutation RestartStackRun($id: ID!) {
restartStackRun(id: $id) {
...StackRun
}
}

subscription LogsDelta($id: ID!) {
runLogsDelta(stepId: $id) {
delta
Expand Down
2 changes: 1 addition & 1 deletion lib/console/deployments/pubsub/protocols/notifiable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ defimpl Console.Deployments.PubSub.Notifiable, for: Console.PubSub.PipelineGateU
def message(_), do: :ok
end

defimpl Console.Deployments.PubSub.Notifiable, for: [Console.PubSub.StackRunCreated, Console.PubSub.StackRunUpdated, Console.PubSub.StackRunDeleted] do
defimpl Console.Deployments.PubSub.Notifiable, for: Console.PubSub.StackRunCreated do
alias Console.Deployments.Notifications.Utils

def message(%{item: run}) do
Expand Down

0 comments on commit fb53605

Please sign in to comment.