Skip to content

Commit

Permalink
Add error state when pipeline version is deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
ppadti committed Jul 1, 2024
1 parent 520c92a commit a242515
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 11 deletions.
20 changes: 20 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/pipelines/topology.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class RunDetails extends PipelinesTopology {
return cy.findByTestId('pipeline-run-tab-spec');
}

findPipelineSpecTabItem() {
return new PipelineSpecTabItem(() => cy.findByTestId('pipeline-spec-tab'));
}

findGraphTabItem() {
return new GraphTabItem(() => cy.findByTestId('pipeline-graph-tab'));
}

findDetailItem(key: string) {
return new DetailsItem(() => cy.findByTestId(`detail-item-${key}`));
}
Expand All @@ -100,6 +108,18 @@ class RunDetails extends PipelinesTopology {
}
}

class PipelineSpecTabItem extends Contextual<HTMLElement> {
findErrorState() {
return this.find().findByTestId('error-state-title');
}
}

class GraphTabItem extends Contextual<HTMLElement> {
findErrorState() {
return this.find().findByTestId('error-state-title');
}
}

class DetailsItem extends Contextual<HTMLElement> {
findValue() {
return this.find().findByTestId('detail-item-value');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import {
buildMockJobKF,
} from '~/__mocks__';
import {
activeRunsTable,
archivedRunsTable,
archiveExperimentModal,
bulkArchiveExperimentModal,
bulkRestoreExperimentModal,
pipelineRunDetails,
pipelineRunJobTable,
pipelineRunsGlobal,
restoreExperimentModal,
Expand All @@ -27,7 +29,7 @@ import {
ProjectModel,
RouteModel,
} from '~/__tests__/cypress/cypress/utils/models';
import { RecurringRunStatus, StorageStateKF } from '~/concepts/pipelines/kfTypes';
import { RecurringRunStatus, RuntimeStateKF, StorageStateKF } from '~/concepts/pipelines/kfTypes';

const projectName = 'test-project-name';
const initialMockPipeline = buildMockPipelineV2({ display_name: 'Test pipeline' });
Expand All @@ -51,6 +53,14 @@ const mockExperiments = [
}),
];

const mockActiveRuns = buildMockRunKF({
display_name: 'Test active run 4',
run_id: 'run-4',
experiment_id: 'test-experiment-1',
created_at: '2024-02-10T00:00:00Z',
state: RuntimeStateKF.SUCCEEDED,
});

describe('Experiments', () => {
describe('Active experiments', () => {
beforeEach(() => {
Expand Down Expand Up @@ -251,6 +261,43 @@ describe('Experiments', () => {
cy.findByLabelText('Experiment').contains(mockExperiment.display_name);
});

it('should display error state when the pipeline version deleted', () => {
cy.interceptOdh(
'GET /api/service/pipelines/:namespace/:serviceName/apis/v2beta1/runs/:runId',
{
path: {
namespace: projectName,
serviceName: 'dspa',
runId: mockActiveRuns.run_id,
},
},
mockActiveRuns,
);
activeRunsTable.getRowByName('Test active run 4').findColumnName('Test active run 4').click();
pipelineRunDetails
.findGraphTabItem()
.findErrorState()
.should('have.text', 'Error loading pipeline run graph');

pipelineRunDetails.findDetailsTab().click();
pipelineRunDetails.findDetailItem('Name').findValue().contains(mockActiveRuns.display_name);
pipelineRunDetails
.findDetailItem('Pipeline version')
.findValue()
.contains('No pipeline version');
pipelineRunDetails.findDetailItem('Project').findValue().contains(projectName);
pipelineRunDetails.findDetailItem('Run ID').findValue().contains(mockActiveRuns.run_id);
pipelineRunDetails
.findDetailItem('Workflow name')
.findValue()
.contains(mockActiveRuns.display_name);
pipelineRunDetails.findPipelineSpecTab().click();
pipelineRunDetails
.findPipelineSpecTabItem()
.findErrorState()
.should('have.text', 'Error loading pipeline run graph');
});

it('navigates back to experiments from "Create run" page breadcrumb', () => {
pipelineRunsGlobal.findCreateRunButton().click();
cy.findByLabelText('Breadcrumb').findByText(`Experiments - ${projectName}`).click();
Expand Down Expand Up @@ -370,7 +417,7 @@ const initIntercepts = () => {
{
path: { namespace: projectName, serviceName: 'dspa' },
},
{ runs: [] },
{ runs: [mockActiveRuns] },
);

cy.interceptOdh(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const DashboardCodeEditor: React.FC<Partial<DashboardCodeEditorProps>> = ({
height = 'calc(100% - 38px)',
...props
}) => (
<div data-testid={props.testId} style={{ height }}>
<div data-testid={props.testId} style={{ height, padding: '14px' }}>
<CodeEditor height="100%" className="odh-dashboard__code-editor" {...props} />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@ import {
} from '@patternfly/react-core';
import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
import DashboardCodeEditor from '~/concepts/dashboard/codeEditor/DashboardCodeEditor';
import PipelineVersionError from './PipelineVersionError';

type PipelineDetailsYAMLProps = {
filename?: string;
content?: Record<string, unknown> | null;
versionError?: Error;
};

const PipelineDetailsYAML: React.FC<PipelineDetailsYAMLProps> = ({ filename, content }) => {
const PipelineDetailsYAML: React.FC<PipelineDetailsYAMLProps> = ({
versionError,
filename,
content,
}) => {
if (versionError) {
return <PipelineVersionError />;
}

if (!content) {
return (
<EmptyState>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
EmptyState,
EmptyStateBody,
EmptyStateHeader,
EmptyStateIcon,
EmptyStateVariant,
PageSection,
} from '@patternfly/react-core';
import { ExclamationTriangleIcon } from '@patternfly/react-icons';
import React from 'react';

const PipelineVersionError: React.FC = () => (
<PageSection className="pf-v5-u-h-100">
<EmptyState variant={EmptyStateVariant.lg} isFullHeight>
<EmptyStateHeader
data-testid="error-state-title"
titleText="Error loading pipeline run graph"
icon={
<EmptyStateIcon
color="var(--pf-v5-global--warning-color--100)"
icon={ExclamationTriangleIcon}
/>
}
headingLevel="h2"
/>
<EmptyStateBody>
Unable to load this run graph because the pipeline version that it belongs to has been
deleted.
</EmptyStateBody>
</EmptyState>
</PageSection>
);

export default PipelineVersionError;
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ const PipelineDetails: PipelineCoreDetailsPageComponent = ({ breadcrumbPath }) =
hidden={PipelineDetailsTab.YAML !== activeTabKey}
className="pf-v5-u-h-100"
>
<TabContentBody hasPadding className="pf-v5-u-h-100">
<TabContentBody className="pf-v5-u-h-100">
<PipelineDetailsYAML
filename={`Pipeline ${
getCorePipelineSpec(pipelineVersion?.pipeline_spec)?.pipelineInfo.name ??
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ const PipelineRunDetails: PipelineCoreDetailsPageComponent = ({ breadcrumbPath,
[selectedId, nodes],
);

const loaded = runLoaded && (versionLoaded || !!run?.pipeline_spec);
const error = versionError || runError;
const loaded = runLoaded && (versionLoaded || !!run?.pipeline_spec || !!versionError);
const error = runError;

if (error) {
return (
Expand Down Expand Up @@ -160,10 +160,12 @@ const PipelineRunDetails: PipelineCoreDetailsPageComponent = ({ breadcrumbPath,
>
<PipelineRunDetailsTabs
run={run}
versionError={versionError}
pipelineSpec={version?.pipeline_spec}
graphContent={
<PipelineTopology
nodes={nodes}
versionError={versionError}
selectedIds={selectedId ? [selectedId] : []}
onSelectionChange={(ids) => {
const firstId = ids[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ interface PipelineRunDetailsTabsProps {
run: PipelineRunKFv2 | PipelineRunJobKFv2 | null;
pipelineSpec: PipelineSpecVariable | undefined;
graphContent: React.ReactNode;
versionError?: Error;
}

export const PipelineRunDetailsTabs: React.FC<PipelineRunDetailsTabsProps> = ({
run,
pipelineSpec,
graphContent,
versionError,
}) => {
const [activeKey, setActiveKey] = React.useState<string | number>(DetailsTabKey.Graph);
const isJob = run && isPipelineRunJob(run);
Expand Down Expand Up @@ -57,7 +59,7 @@ export const PipelineRunDetailsTabs: React.FC<PipelineRunDetailsTabsProps> = ({
</TabContentBody>
</Tab>

{!isJob && pipelineSpec && (
{!isJob && (
<Tab
eventKey={DetailsTabKey.Spec}
tabContentId={DetailsTabKey.Spec}
Expand All @@ -73,6 +75,7 @@ export const PipelineRunDetailsTabs: React.FC<PipelineRunDetailsTabsProps> = ({
id={DetailsTabKey.Graph}
eventKey={DetailsTabKey.Graph}
className="pf-v5-u-h-100"
data-testid="pipeline-graph-tab"
>
<TabContentBody className="pf-v5-u-h-100">{graphContent}</TabContentBody>
</TabContent>
Expand All @@ -83,9 +86,14 @@ export const PipelineRunDetailsTabs: React.FC<PipelineRunDetailsTabsProps> = ({
eventKey={DetailsTabKey.Spec}
hidden={activeKey !== DetailsTabKey.Spec}
style={{ flex: 1 }}
data-testid="pipeline-spec-tab"
>
<TabContentBody className="pf-v5-u-h-100" hasPadding>
<PipelineDetailsYAML filename={run?.display_name} content={pipelineSpec} />
<TabContentBody className="pf-v5-u-h-100">
<PipelineDetailsYAML
filename={run?.display_name}
content={pipelineSpec}
versionError={versionError}
/>
</TabContentBody>
</TabContent>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ const PipelineRunTabDetails: React.FC<PipelineRunTabDetailsProps> = ({ run, work
),
},
]
: versionError
? [{ key: 'Pipeline version', value: 'No pipeline version' }]
: []),
...(pipeline
? [
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/concepts/topology/PipelineTopology.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ import {
VisualizationProvider,
} from '@patternfly/react-topology';
import { Bullseye, Spinner } from '@patternfly/react-core';
import PipelineVersionError from '~/concepts/pipelines/content/pipelinesDetails/PipelineVersionError';
import PipelineTopologyEmpty from './PipelineTopologyEmpty';
import useTopologyController from './useTopologyController';
import PipelineVisualizationSurface from './PipelineVisualizationSurface';
import PipelineTopologyEmpty from './PipelineTopologyEmpty';

type PipelineTopologyProps = {
selectedIds?: string[];
onSelectionChange?: (selectionIds: string[]) => void;
nodes: PipelineNodeModel[];
versionError?: Error;
};

const PipelineTopology: React.FC<PipelineTopologyProps> = ({
nodes,
selectedIds,
onSelectionChange,
versionError,
}) => {
const controller = useTopologyController('g1');

Expand All @@ -37,6 +40,10 @@ const PipelineTopology: React.FC<PipelineTopologyProps> = ({
return undefined;
}, [controller, onSelectionChange]);

if (versionError) {
return <PipelineVersionError />;
}

if (!nodes.length) {
return <PipelineTopologyEmpty />;
}
Expand Down

0 comments on commit a242515

Please sign in to comment.