Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCPBUGS-23912 OCPBUGS-23918: Add Vulnerabilities column and signed icon in PAC repository PLR list #13364

Merged
merged 2 commits into from Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -13,7 +13,8 @@ export type ScanResults = {
};

export const getPipelineRunVulnerabilities = (pipelineRun: PipelineRunKind): ScanResults => {
return pipelineRun.status?.results?.reduce((acc, result) => {
const results = pipelineRun.status?.results || pipelineRun.status?.pipelineResults;
return results?.reduce((acc, result) => {
if (result.name?.endsWith(SCAN_OUTPUT_SUFFIX)) {
if (!acc.vulnerabilities) {
acc.vulnerabilities = { critical: 0, high: 0, medium: 0, low: 0 };
Expand Down
Expand Up @@ -105,10 +105,9 @@ const useRuns = <Kind extends K8sResourceCommon>(
runs && trResources
? uniqBy([...runs, ...trResources], (r) => r.metadata.name)
: runs || trResources;

return [
rResources,
namespace ? !!rResources?.[0] : false,
loaded || trLoaded,
namespace
? queryTr
? isList
Expand All @@ -119,7 +118,18 @@ const useRuns = <Kind extends K8sResourceCommon>(
: undefined,
trGetNextPage,
];
}, [error, trResources, trLoaded, trError, trGetNextPage, namespace, isList, queryTr, runs]);
}, [
runs,
trResources,
loaded,
trLoaded,
namespace,
queryTr,
isList,
trError,
error,
trGetNextPage,
]);
};

export const usePipelineRuns = (
Expand Down
Expand Up @@ -36,6 +36,12 @@ const RepositoryPipelineRunHeader = () => {
props: { className: tableColumnClasses[2] },
id: 'namespace',
},
{
title: i18n.t('pipelines-plugin~Vulnerabilities'),
sortFunc: 'vulnerabilities',
transforms: [sortable],
props: { className: tableColumnClasses[3] },
},
{
title: i18n.t('pipelines-plugin~Status'),
sortField: 'status.conditions[0].reason',
Expand Down
Expand Up @@ -3,8 +3,8 @@ import { SortByDirection } from '@patternfly/react-table';
import { useTranslation } from 'react-i18next';
import { Table } from '@console/internal/components/factory';
import { PipelineRunModel } from '../../models';
import { useTaskRuns } from '../pipelineruns/hooks/useTaskRuns';
import { usePipelineOperatorVersion } from '../pipelines/utils/pipeline-operator';
import { useTaskRuns } from '../taskruns/useTaskRuns';
import RepositoryPipelineRunHeader from './RepositoryPipelineRunHeader';
import RepositoryPipelineRunRow from './RepositoryPipelineRunRow';

Expand Down
Expand Up @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { referenceForModel } from '@console/internal/module/k8s';
import { PipelineRunModel } from '../../models';
import { ListPage } from '../ListPage';
import { useGetPipelineRuns } from '../pipelineruns/hooks/useTektonResults';
import { usePipelineRuns } from '../pipelineruns/hooks/usePipelineRuns';
import { runFilters } from '../pipelines/detail-page-tabs/PipelineRuns';
import { RepositoryFields, RepositoryLabels } from './consts';
import RunList from './RepositoryPipelineRunList';
Expand All @@ -16,9 +16,16 @@ export interface RepositoryPipelineRunListPageProps {
const RepositoryPipelineRunListPage: React.FC<RepositoryPipelineRunListPageProps> = (props) => {
const { t } = useTranslation();
const { obj } = props;
const [pipelineRuns, pipelineRunsLoaded, pipelineRunsLoadError] = useGetPipelineRuns(
const selector = React.useMemo(() => {
return {
matchLabels: { [RepositoryLabels[RepositoryFields.REPOSITORY]]: obj.metadata.name },
};
}, [obj.metadata.name]);
const [pipelineRuns, pipelineRunsLoaded, pipelineRunsLoadError] = usePipelineRuns(
obj.metadata.namespace,
{ name: obj.metadata.name, kind: obj.kind },
{
selector,
},
);
const resources = {
[referenceForModel(PipelineRunModel)]: {
Expand Down
Expand Up @@ -10,6 +10,7 @@ import {
ExternalLink,
} from '@console/internal/components/utils';
import { referenceForModel } from '@console/internal/module/k8s';
import * as SignedPipelinerunIcon from '../../images/signed-badge.svg';
import { PipelineRunModel } from '../../models';
import { PipelineRunKind, TaskRunKind } from '../../types';
import { getPipelineRunKebabActions } from '../../utils/pipeline-actions';
Expand All @@ -20,7 +21,9 @@ import {
import { pipelineRunDuration } from '../../utils/pipeline-utils';
import LinkedPipelineRunTaskStatus from '../pipelineruns/status/LinkedPipelineRunTaskStatus';
import PipelineRunStatus from '../pipelineruns/status/PipelineRunStatus';
import PipelineRunVulnerabilities from '../pipelineruns/status/PipelineRunVulnerabilities';
import { ResourceKebabWithUserLabel } from '../pipelineruns/triggered-by';
import { chainsSignedAnnotation } from '../pipelines/const';
import { getTaskRunsOfPipelineRun } from '../taskruns/useTaskRuns';
import {
RepositoryLabels,
Expand Down Expand Up @@ -68,6 +71,13 @@ const RepositoryPipelineRunRow: React.FC<RowFunctionArgs<PipelineRunKind>> = ({
data-test-id={obj.metadata.name}
nameSuffix={
<>
{obj?.metadata?.annotations?.[chainsSignedAnnotation] === 'true' ? (
<Tooltip content={t('pipelines-plugin~Signed')}>
<div className="opp-pipeline-run-list__signed-indicator">
<img src={SignedPipelinerunIcon} alt={t('pipelines-plugin~Signed')} />
</div>
</Tooltip>
) : null}
{obj?.metadata?.annotations?.['resource.deleted.in.k8s'] === 'true' ? (
<Tooltip content={t('pipelines-plugin~Archived in Tekton results')}>
<div className="opp-pipeline-run-list__results-indicator">
Expand Down Expand Up @@ -103,6 +113,9 @@ const RepositoryPipelineRunRow: React.FC<RowFunctionArgs<PipelineRunKind>> = ({
<TableData className={tableColumnClasses[2]} columnID="namespace">
<ResourceLink kind="Namespace" name={obj.metadata.namespace} />
</TableData>
<TableData className={tableColumnClasses[3]}>
<PipelineRunVulnerabilities pipelineRun={obj} condensed />
</TableData>
<TableData className={tableColumnClasses[3]}>
<PLRStatus obj={obj} taskRuns={PLRTaskRuns} />
</TableData>
Expand Down
Expand Up @@ -3,7 +3,6 @@ import { Link } from 'react-router-dom';
import { TableData, RowFunctionArgs } from '@console/internal/components/factory';
import {
Kebab,
LoadingInline,
ResourceIcon,
ResourceKebab,
ResourceLink,
Expand All @@ -18,7 +17,6 @@ import {
pipelineRunTitleFilterReducer,
} from '../../../utils/pipeline-filter-reducer';
import { pipelineRunDuration } from '../../../utils/pipeline-utils';
import { useGetPipelineRuns } from '../../pipelineruns/hooks/useTektonResults';
import LinkedPipelineRunTaskStatus from '../../pipelineruns/status/LinkedPipelineRunTaskStatus';
import PipelineRunStatus from '../../pipelineruns/status/PipelineRunStatus';
import { getTaskRunsOfPipelineRun } from '../../taskruns/useTaskRuns';
Expand All @@ -30,11 +28,13 @@ const RepositoryRow: React.FC<RowFunctionArgs<RepositoryKind>> = ({ obj, customD
const {
metadata: { name, namespace },
} = obj;
const { taskRuns } = customData;

const [pipelineRuns, loaded] = useGetPipelineRuns(namespace, { name, kind: obj.kind });

const latestRun = loaded && getLatestRun(pipelineRuns, 'creationTimestamp');
const { taskRuns, pipelineRuns } = customData;
const plrs = pipelineRuns.filter((plr) => {
return (
plr.metadata?.labels[RepositoryLabels[RepositoryFields.REPOSITORY]] === obj.metadata.name
);
});
const latestRun = getLatestRun(plrs, 'creationTimestamp');

const latestPLREventType =
latestRun && latestRun?.metadata?.labels[RepositoryLabels[RepositoryFields.EVENT_TYPE]];
Expand All @@ -59,49 +59,39 @@ const RepositoryRow: React.FC<RowFunctionArgs<RepositoryKind>> = ({ obj, customD
{latestPLREventType || '-'}
</TableData>
<TableData className={repositoriesTableColumnClasses[3]}>
{loaded ? (
latestRun ? (
<ResourceLink
kind={referenceForModel(PipelineRunModel)}
name={latestRun?.metadata.name}
namespace={namespace}
/>
) : (
'-'
)
{latestRun ? (
<ResourceLink
kind={referenceForModel(PipelineRunModel)}
name={latestRun?.metadata.name}
namespace={namespace}
/>
) : (
<LoadingInline />
'-'
)}
</TableData>
<TableData className={repositoriesTableColumnClasses[4]}>
{}
{loaded ? (
latestRun ? (
<LinkedPipelineRunTaskStatus pipelineRun={latestRun} taskRuns={PLRTaskRuns} />
) : (
'-'
)
{latestRun ? (
<LinkedPipelineRunTaskStatus pipelineRun={latestRun} taskRuns={PLRTaskRuns} />
) : (
<LoadingInline />
'-'
)}
</TableData>
<TableData className={repositoriesTableColumnClasses[5]}>
{loaded ? (
{
<PipelineRunStatus
status={pipelineRunFilterReducer(latestRun)}
title={pipelineRunTitleFilterReducer(latestRun)}
pipelineRun={latestRun}
taskRuns={PLRTaskRuns}
/>
) : (
<LoadingInline />
)}
}
</TableData>
<TableData className={repositoriesTableColumnClasses[6]}>
{loaded ? <Timestamp timestamp={latestRun?.status.startTime} /> : <LoadingInline />}
{<Timestamp timestamp={latestRun?.status.startTime} />}
</TableData>
<TableData className={repositoriesTableColumnClasses[7]}>
{loaded ? pipelineRunDuration(latestRun) : <LoadingInline />}
{pipelineRunDuration(latestRun)}
</TableData>
<TableData className={repositoriesTableColumnClasses[8]}>
<ResourceKebab actions={Kebab.factory.common} kind={referenceFor(obj)} resource={obj} />
Expand Down
@@ -1,7 +1,8 @@
import * as React from 'react';
import { Table } from '@console/internal/components/factory';
import { RepositoryModel } from '../../../models';
import { useGetTaskRuns } from '../../pipelineruns/hooks/useTektonResults';
import { usePipelineRuns } from '../../pipelineruns/hooks/usePipelineRuns';
import { useTaskRuns } from '../../pipelineruns/hooks/useTaskRuns';
import { RepositoryKind } from '../types';
import RepositoryHeader from './RepositoryHeader';
import RepositoryRow from './RepositoryRow';
Expand All @@ -12,15 +13,18 @@ export interface RepositoryListProps {
}

const RepositoryList: React.FC<RepositoryListProps> = (props) => {
const [taskRuns, taskRunsLoaded] = useGetTaskRuns(props.namespace);

const [taskRuns, taskRunsLoaded] = useTaskRuns(props.namespace);
const [pipelineRuns, pipelineRunsLoaded] = usePipelineRuns(props.namespace);
return (
<Table
{...props}
aria-label={RepositoryModel.labelPluralKey}
Header={RepositoryHeader}
Row={RepositoryRow}
customData={{ taskRuns: taskRunsLoaded ? taskRuns : [] }}
customData={{
taskRuns: taskRunsLoaded ? taskRuns : [],
pipelineRuns: pipelineRunsLoaded ? pipelineRuns : [],
}}
virtualize
/>
);
Expand Down
Expand Up @@ -546,7 +546,9 @@ export const getSbomTaskRun = (taskruns: TaskRunKind[]): TaskRunKind =>
);

export const getSbomLink = (sbomTaskRun: TaskRunKind): string | undefined =>
sbomTaskRun?.status?.results?.find((r) => r.name === 'LINK_TO_SBOM')?.value;
(sbomTaskRun?.status?.results || sbomTaskRun?.status?.taskResults)?.find(
(r) => r.name === 'LINK_TO_SBOM',
)?.value;
export const taskRunStatus = (taskRun: TaskRunKind | PLRTaskRunData): ComputedStatus => {
if (!taskRun?.status?.conditions?.length) {
return ComputedStatus.Pending;
Expand Down