Skip to content

Commit

Permalink
Pipeline gate force open/close UI (#809)
Browse files Browse the repository at this point in the history
  • Loading branch information
renemennab authored Apr 4, 2024
1 parent cacbaa8 commit fd7b98f
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
10 changes: 5 additions & 5 deletions assets/src/components/cd/ContinuousDeployment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ function useDirectory({ filtered = true }: { filtered?: boolean } = {}) {
label: 'Services',
enabled: personaConfiguration?.all || config?.services,
},
{
path: GLOBAL_SERVICES_REL_PATH,
label: 'Global Services',
enabled: personaConfiguration?.all || config?.services,
},
{
path: REPOS_REL_PATH,
label: 'Repositories',
Expand All @@ -153,11 +158,6 @@ function useDirectory({ filtered = true }: { filtered?: boolean } = {}) {
label: 'Add-ons',
enabled: personaConfiguration?.all || config?.addOns,
},
{
path: GLOBAL_SERVICES_REL_PATH,
label: 'Global Services',
enabled: personaConfiguration?.all || config?.services,
},
]

if (!filtered) {
Expand Down
73 changes: 71 additions & 2 deletions assets/src/components/cd/pipelines/job/PipelineJobLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { useMemo, useState } from 'react'
import { FormField, ListBoxItem, Select } from '@pluralsh/design-system'
import { useJobGateLogsQuery } from 'generated/graphql'
import {
Banner,
Button,
FormField,
ListBoxItem,
Select,
} from '@pluralsh/design-system'
import {
GateState,
useForceGateMutation,
useJobGateLogsQuery,
useJobGateQuery,
} from 'generated/graphql'
import { useParams } from 'react-router-dom'
import { useTheme } from 'styled-components'

Expand Down Expand Up @@ -40,7 +51,13 @@ export default function PipelineJobLogs() {
const [selectedContainer, setSelectedContainer] = useState<string>(
containers?.[0]?.name || ''
)
const { data: jobGateData } = useJobGateQuery({
variables: { id },
})
const jobGateState = jobGateData?.pipelineGate?.state

const [forceGate, { loading: loadingForceGate, error: errorForceGate }] =
useForceGateMutation()
const {
data: currentData,
previousData,
Expand All @@ -66,6 +83,46 @@ export default function PipelineJobLogs() {
<ScrollablePage
heading="Logs"
scrollable={false}
headingContent={
jobGateState === GateState.Running ||
jobGateState === GateState.Pending ? (
<div
css={{
display: 'flex',
alignItems: 'center',
gap: theme.spacing.medium,
}}
>
<Button
disabled={loadingForceGate}
onClick={() =>
forceGate({
variables: {
id,
state: GateState.Open,
},
})
}
>
Mark Successful
</Button>
<Button
disabled={loadingForceGate}
secondary
onClick={() =>
forceGate({
variables: {
id,
state: GateState.Closed,
},
})
}
>
Cancel
</Button>
</div>
) : null
}
>
<div
css={{
Expand All @@ -75,6 +132,18 @@ export default function PipelineJobLogs() {
height: '100%',
}}
>
{errorForceGate && (
<Banner
heading="Error forcing gate"
severity="error"
position="fixed"
top={80}
right={50}
zIndex={100}
>
{errorForceGate.message}
</Banner>
)}
<div
css={{
display: 'flex',
Expand Down
43 changes: 43 additions & 0 deletions assets/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7124,6 +7124,14 @@ export type CreatePipelineContextMutationVariables = Exact<{

export type CreatePipelineContextMutation = { __typename?: 'RootMutationType', createPipelineContext?: { __typename?: 'PipelineContext', id: string, context: Record<string, unknown>, insertedAt?: string | null, updatedAt?: string | null, pipeline?: { __typename?: 'Pipeline', id: string } | null, pullRequests?: Array<{ __typename?: 'PullRequest', id: string, title?: string | null, url: string, labels?: Array<string | null> | null, creator?: string | null, status?: PrStatus | null, insertedAt?: string | null, updatedAt?: string | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, deletedAt?: string | null } | null, cluster?: { __typename?: 'Cluster', handle?: string | null, self?: boolean | null, protect?: boolean | null, deletedAt?: string | null, version?: string | null, currentVersion?: string | null, id: string, name: string, distro?: ClusterDistro | null, provider?: { __typename?: 'ClusterProvider', cloud: string } | null } | null } | null> | null, pipelinePullRequests?: Array<{ __typename?: 'PipelinePullRequest', id: string, service?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, deletedAt?: string | null } | null, pullRequest?: { __typename?: 'PullRequest', id: string, title?: string | null, url: string, labels?: Array<string | null> | null, creator?: string | null, status?: PrStatus | null, insertedAt?: string | null, updatedAt?: string | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, protect?: boolean | null, deletedAt?: string | null } | null, cluster?: { __typename?: 'Cluster', handle?: string | null, self?: boolean | null, protect?: boolean | null, deletedAt?: string | null, version?: string | null, currentVersion?: string | null, id: string, name: string, distro?: ClusterDistro | null, provider?: { __typename?: 'ClusterProvider', cloud: string } | null } | null } | null } | null> | null } | null };

export type ForceGateMutationVariables = Exact<{
id: Scalars['ID']['input'];
state?: InputMaybe<GateState>;
}>;


export type ForceGateMutation = { __typename?: 'RootMutationType', forceGate?: { __typename?: 'PipelineGate', id: string, name: string, state: GateState, type: GateType, insertedAt?: string | null, updatedAt?: string | null, approver?: { __typename?: 'User', id: string, pluralId?: string | null, name: string, email: string, profile?: string | null, backgroundColor?: string | null, readTimestamp?: string | null, roles?: { __typename?: 'UserRoles', admin?: boolean | null } | null, personas?: Array<{ __typename?: 'Persona', id: string, name: string, description?: string | null, bindings?: Array<{ __typename?: 'PolicyBinding', id?: string | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null, group?: { __typename?: 'Group', id: string, name: string } | null } | null> | null, configuration?: { __typename?: 'PersonaConfiguration', all?: boolean | null, deployments?: { __typename?: 'PersonaDeployment', addOns?: boolean | null, clusters?: boolean | null, pipelines?: boolean | null, providers?: boolean | null, repositories?: boolean | null, services?: boolean | null } | null, sidebar?: { __typename?: 'PersonaSidebar', audits?: boolean | null, kubernetes?: boolean | null, pullRequests?: boolean | null, settings?: boolean | null, backups?: boolean | null, stacks?: boolean | null } | null } | null } | null> | null } | null, spec?: { __typename?: 'GateSpec', job?: { __typename?: 'JobGateSpec', annotations?: Record<string, unknown> | null, labels?: Record<string, unknown> | null, namespace: string, raw?: string | null, serviceAccount?: string | null, containers?: Array<{ __typename?: 'ContainerSpec', args?: Array<string | null> | null, image: string, env?: Array<{ __typename?: 'ContainerEnv', name: string, value: string } | null> | null, envFrom?: Array<{ __typename?: 'ContainerEnvFrom', configMap: string, secret: string } | null> | null } | null> | null } | null } | null } | null };

export type ProviderCredentialFragment = { __typename?: 'ProviderCredential', id: string, insertedAt?: string | null, kind: string, name: string, namespace: string, updatedAt?: string | null };

export type ClusterProviderFragment = { __typename?: 'ClusterProvider', id: string, name: string, namespace: string, cloud: string, editable?: boolean | null, supportedVersions?: Array<string | null> | null, deletedAt?: string | null, insertedAt?: string | null, updatedAt?: string | null, git: { __typename?: 'GitRef', folder: string, ref: string }, repository?: { __typename?: 'GitRepository', id: string, url: string } | null, service?: { __typename?: 'ServiceDeployment', id: string, name: string, namespace: string } | null, credentials?: Array<{ __typename?: 'ProviderCredential', id: string, insertedAt?: string | null, kind: string, name: string, namespace: string, updatedAt?: string | null } | null> | null };
Expand Down Expand Up @@ -12666,6 +12674,40 @@ export function useCreatePipelineContextMutation(baseOptions?: Apollo.MutationHo
export type CreatePipelineContextMutationHookResult = ReturnType<typeof useCreatePipelineContextMutation>;
export type CreatePipelineContextMutationResult = Apollo.MutationResult<CreatePipelineContextMutation>;
export type CreatePipelineContextMutationOptions = Apollo.BaseMutationOptions<CreatePipelineContextMutation, CreatePipelineContextMutationVariables>;
export const ForceGateDocument = gql`
mutation ForceGate($id: ID!, $state: GateState) {
forceGate(id: $id, state: $state) {
...PipelineGate
}
}
${PipelineGateFragmentDoc}`;
export type ForceGateMutationFn = Apollo.MutationFunction<ForceGateMutation, ForceGateMutationVariables>;

/**
* __useForceGateMutation__
*
* To run a mutation, you first call `useForceGateMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useForceGateMutation` 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 [forceGateMutation, { data, loading, error }] = useForceGateMutation({
* variables: {
* id: // value for 'id'
* state: // value for 'state'
* },
* });
*/
export function useForceGateMutation(baseOptions?: Apollo.MutationHookOptions<ForceGateMutation, ForceGateMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<ForceGateMutation, ForceGateMutationVariables>(ForceGateDocument, options);
}
export type ForceGateMutationHookResult = ReturnType<typeof useForceGateMutation>;
export type ForceGateMutationResult = Apollo.MutationResult<ForceGateMutation>;
export type ForceGateMutationOptions = Apollo.BaseMutationOptions<ForceGateMutation, ForceGateMutationVariables>;
export const ClusterProvidersDocument = gql`
query ClusterProviders {
clusterProviders(first: 100) {
Expand Down Expand Up @@ -15814,6 +15856,7 @@ export const namedOperations = {
deletePipeline: 'deletePipeline',
ApproveGate: 'ApproveGate',
CreatePipelineContext: 'CreatePipelineContext',
ForceGate: 'ForceGate',
CreateClusterProvider: 'CreateClusterProvider',
UpdateClusterProvider: 'UpdateClusterProvider',
DeleteClusterProvider: 'DeleteClusterProvider',
Expand Down
6 changes: 6 additions & 0 deletions assets/src/graph/cdPipelines.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,9 @@ mutation CreatePipelineContext(
}
}
}

mutation ForceGate($id: ID!, $state: GateState) {
forceGate(id: $id, state: $state) {
...PipelineGate
}
}

0 comments on commit fd7b98f

Please sign in to comment.