Skip to content

Commit

Permalink
fix(quay): fix infinite progress bar when scan is unsupported (janus-…
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitkrai03 authored Dec 21, 2023
1 parent 1544d1f commit 2c050db
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
24 changes: 24 additions & 0 deletions plugins/quay/src/components/QuayRepository/QuayRepository.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,28 @@ describe('QuayRepository', () => {
expect(queryByText(/Quay repository/i)).toBeInTheDocument();
expect(queryByTestId('quay-repo-security-scan-progress')).not.toBeNull();
});

it('should show table if loaded and data is present but shows unsupported if security scan is not supported', () => {
(useTags as jest.Mock).mockReturnValue({
loading: false,
data: [
{
name: 'latest',
manifest_digest: undefined,
securityStatus: 'unsupported',
size: null,
last_modified: 'Wed, 15 Mar 2023 18:22:18 -0000',
},
],
});
const { queryByTestId, queryByText } = render(
<BrowserRouter>
<QuayRepository />
</BrowserRouter>,
);
expect(queryByTestId('quay-repo-table')).not.toBeNull();
expect(queryByTestId('quay-repo-table-empty')).toBeNull();
expect(queryByText(/Quay repository/i)).toBeInTheDocument();
expect(queryByTestId('quay-repo-security-scan-unsupported')).not.toBeNull();
});
});
14 changes: 13 additions & 1 deletion plugins/quay/src/components/QuayRepository/tableHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import { Link, Progress, TableColumn } from '@backstage/core-components';

import { Tooltip } from '@material-ui/core';
import makeStyles from '@material-ui/core/styles/makeStyles';

import type { Layer } from '../../types';
Expand Down Expand Up @@ -41,13 +42,24 @@ export const columns: TableColumn[] = [
title: 'Security Scan',
field: 'securityScan',
render: (rowData: any): React.ReactNode => {
if (!rowData.securityDetails) {
if (!rowData.securityStatus && !rowData.securityDetails) {
return (
<span data-testid="quay-repo-security-scan-progress">
<Progress />
</span>
);
}

if (rowData.securityStatus === 'unsupported') {
return (
<Tooltip title="The manifest for this tag has an operating system or package manager unsupported by Quay Security Scanner">
<span data-testid="quay-repo-security-scan-unsupported">
Unsupported
</span>
</Tooltip>
);
}

const tagManifest = rowData.manifest_digest_raw;
const retStr = vulnerabilitySummary(rowData.securityDetails as Layer);
return <Link to={`tag/${tagManifest}`}>{retStr}</Link>;
Expand Down
22 changes: 16 additions & 6 deletions plugins/quay/src/hooks/quay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export const useTags = (organization: string, repository: string) => {
const [tagManifestLayers, setTagManifestLayers] = React.useState<
Record<string, Layer>
>({});
const [tagManifestStatuses, setTagManifestStatuses] = React.useState<
Record<string, string>
>({});
const localClasses = useLocalStyles();

const fetchSecurityDetails = async (tag: Tag) => {
Expand All @@ -46,13 +49,19 @@ export const useTags = (organization: string, repository: string) => {
tagsResponse.tags.map(async tag => {
const securityDetails = await fetchSecurityDetails(tag);
const securityData = securityDetails.data;
if (!securityData) {
return;
}
setTagManifestLayers(prevState => ({
const securityStatus = securityDetails.status;

setTagManifestStatuses(prevState => ({
...prevState,
[tag.manifest_digest]: securityData.Layer,
[tag.manifest_digest]: securityStatus,
}));

if (securityData) {
setTagManifestLayers(prevState => ({
...prevState,
[tag.manifest_digest]: securityData.Layer,
}));
}
}),
);
setTags(prevTags => [...prevTags, ...tagsResponse.tags]);
Expand All @@ -76,6 +85,7 @@ export const useTags = (organization: string, repository: string) => {
),
expiration: tag.expiration,
securityDetails: tagManifestLayers[tag.manifest_digest],
securityStatus: tagManifestStatuses[tag.manifest_digest],
manifest_digest_raw: tag.manifest_digest,
// is_manifest_list: tag.is_manifest_list,
// reversion: tag.reversion,
Expand All @@ -84,7 +94,7 @@ export const useTags = (organization: string, repository: string) => {
// manifest_list: tag.manifest_list,
};
});
}, [tags, tagManifestLayers, localClasses.chip]);
}, [tags, localClasses.chip, tagManifestLayers, tagManifestStatuses]);

return { loading, data };
};
Expand Down
38 changes: 38 additions & 0 deletions plugins/quay/src/hooks/useTags.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useApi } from '@backstage/core-plugin-api';

import { waitFor } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';

Expand All @@ -21,4 +23,40 @@ describe('useTags', () => {
expect(result.current.data).toHaveLength(1);
});
});

it('should return security status for tags', async () => {
(useApi as jest.Mock).mockReturnValue({
getSecurityDetails: jest
.fn()
.mockReturnValue({ data: null, status: 'unsupported' }),
getTags: jest.fn().mockReturnValue({
tags: [{ name: 'tag1', manifest_digest: 'manifestDigest' }],
}),
});
const { result } = renderHook(() => useTags('foo', 'bar'));
await waitFor(() => {
expect(result.current.loading).toBeFalsy();
expect(result.current.data).toHaveLength(1);
expect(result.current.data[0].securityStatus).toBe('unsupported');
expect(result.current.data[0].securityDetails).toBeUndefined();
});
});

it('should return tag layers as security details for tags', async () => {
(useApi as jest.Mock).mockReturnValue({
getSecurityDetails: jest
.fn()
.mockReturnValue({ data: { Layer: {} }, status: 'scanned' }),
getTags: jest.fn().mockReturnValue({
tags: [{ name: 'tag1', manifest_digest: 'manifestDigest' }],
}),
});
const { result } = renderHook(() => useTags('foo', 'bar'));
await waitFor(() => {
expect(result.current.loading).toBeFalsy();
expect(result.current.data).toHaveLength(1);
expect(result.current.data[0].securityStatus).toBe('scanned');
expect(result.current.data[0].securityDetails).toEqual({});
});
});
});

0 comments on commit 2c050db

Please sign in to comment.