Rename scorecards plugin to tech-insights plugin

Signed-off-by: irma12 <irma@roadie.io>
This commit is contained in:
irma12
2021-11-26 13:51:43 +01:00
parent b5bd60fddc
commit 1f455f8abb
23 changed files with 93 additions and 79 deletions
@@ -0,0 +1,35 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createApiRef } from '@backstage/core-plugin-api';
import { CheckResult } from '@backstage/plugin-tech-insights-common';
import { Check } from './types';
import { CheckResultRenderer } from '../components/CheckResultRenderer';
import { EntityName } from '@backstage/catalog-model';
export const techInsightsApiRef = createApiRef<TechInsightsApi>({
id: 'plugin.techinsights.service',
description: 'Used by the tech insights plugin to make requests',
});
export interface TechInsightsApi {
getScorecardsDefinition: (
type: string,
value: CheckResult[],
) => CheckResultRenderer | undefined;
getAllChecks(): Promise<Check[]>;
runChecks(entityParams: EntityName, checks?: Check[]): Promise<CheckResult[]>;
}
@@ -0,0 +1,82 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TechInsightsApi } from './TechInsightsApi';
import { CheckResult } from '@backstage/plugin-tech-insights-common';
import { Check } from './types';
import { DiscoveryApi } from '@backstage/core-plugin-api';
import { ResponseError } from '@backstage/errors';
import { EntityName } from '@backstage/catalog-model';
import {
CheckResultRenderer,
defaultCheckResultRenderers,
} from '../components/CheckResultRenderer';
export type Options = {
discoveryApi: DiscoveryApi;
};
export class TechInsightsClient implements TechInsightsApi {
private readonly discoveryApi: DiscoveryApi;
constructor(options: Options) {
this.discoveryApi = options.discoveryApi;
}
getScorecardsDefinition(
type: string,
value: CheckResult[],
): CheckResultRenderer | undefined {
const resultRenderers = defaultCheckResultRenderers(value);
return resultRenderers.find(d => d.type === type);
}
async getAllChecks(): Promise<Check[]> {
const url = await this.discoveryApi.getBaseUrl('tech-insights');
const response = await fetch(`${url}/checks`);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
async runChecks(
entityParams: EntityName,
checks: Check[],
): Promise<CheckResult[]> {
const url = await this.discoveryApi.getBaseUrl('tech-insights');
const { namespace, kind, name } = entityParams;
const allChecks = checks ? checks : await this.getAllChecks();
const checkIds = allChecks.map((check: Check) => check.id);
const response = await fetch(
`${url}/checks/run/${encodeURIComponent(namespace)}/${encodeURIComponent(
kind,
)}/${encodeURIComponent(name)}`,
{
method: 'POST',
body: JSON.stringify({ checks: checkIds }),
headers: {
'Content-Type': 'application/json',
},
},
);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
}
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './TechInsightsApi';
export * from './TechInsightsClient';
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type Check = {
id: string;
type: string;
name: string;
description: string;
factIds: string[];
};
@@ -0,0 +1,64 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles, List, ListItem, ListItemText } from '@material-ui/core';
import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
import { CheckResult } from '@backstage/plugin-tech-insights-common';
import { JsonValue } from '@backstage/types';
const useStyles = makeStyles(() => ({
listItemText: {
paddingRight: '1rem',
flex: '0 1 auto',
},
icon: {
marginLeft: 'auto',
},
}));
type Prop = {
checkResult: CheckResult[];
};
const renderResult = (classes: any, result: JsonValue) => {
return result ? (
<CheckCircleOutline className={classes.icon} color="primary" />
) : (
<ErrorOutlineIcon className={classes.icon} color="error" />
);
};
export const BooleanCheck = ({ checkResult }: Prop) => {
const classes = useStyles();
return (
<List>
{checkResult!.map((check, index) => (
<ListItem>
<ListItemText
key={index}
primary={check.check.name}
secondary={check.check.description}
className={classes.listItemText}
/>
{renderResult(classes, check.result)}
</ListItem>
))}
</List>
);
};
@@ -0,0 +1,17 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { BooleanCheck } from './BooleanCheck';
@@ -0,0 +1,40 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CheckResult } from '@backstage/plugin-tech-insights-common';
import React from 'react';
import { BooleanCheck } from './BooleanCheck';
export type CheckResultRenderer = {
type: string;
title: string;
description: string;
component: React.ReactElement;
};
export function defaultCheckResultRenderers(
value: CheckResult[],
): CheckResultRenderer[] {
return [
{
type: 'json-rules-engine',
title: 'Boolean scorecard',
description:
'This card represents an overview of default boolean Backstage checks:',
component: <BooleanCheck checkResult={value} />,
},
];
}
@@ -0,0 +1,68 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { makeStyles, Grid, Typography } from '@material-ui/core';
import { useApi } from '@backstage/core-plugin-api';
import { Content, Page, InfoCard } from '@backstage/core-components';
import { CheckResult } from '@backstage/plugin-tech-insights-common';
import { techInsightsApiRef } from '../../api/TechInsightsApi';
import { BackstageTheme } from '@backstage/theme';
const useStyles = makeStyles((theme: BackstageTheme) => ({
contentScorecards: {
paddingLeft: 0,
paddingRight: 0,
},
subheader: {
fontWeight: 'bold',
paddingLeft: theme.spacing(0.5),
},
}));
type Checks = {
checks: CheckResult[];
};
export const ChecksOverview = ({ checks }: Checks) => {
const classes = useStyles();
const api = useApi(techInsightsApiRef);
const checkRenderType = api.getScorecardsDefinition(
checks[0].check.type,
checks,
);
if (checkRenderType) {
return (
<Page themeId="home">
<Content className={classes.contentScorecards}>
<Grid item xs={12}>
<InfoCard title={checkRenderType.title}>
<Typography className={classes.subheader} variant="body1">
{checkRenderType.description}
</Typography>
<Grid item xs={11}>
{checkRenderType.component}
</Grid>
</InfoCard>
</Grid>
</Content>
</Page>
);
}
return <></>;
};
@@ -0,0 +1,41 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { useParams } from 'react-router-dom';
import { useAsync } from 'react-use';
import { Progress } from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
import { ChecksOverview } from './ChecksOverview';
import Alert from '@material-ui/lab/Alert';
import { techInsightsApiRef } from '../../api/TechInsightsApi';
export const ScorecardsOverview = () => {
const api = useApi(techInsightsApiRef);
const { namespace, kind, name } = useParams();
const { value, loading, error } = useAsync(
async () => await api.runChecks({ namespace, kind, name }),
);
if (loading) {
return <Progress />;
} else if (error) {
return <Alert severity="error">{error.message}</Alert>;
}
return <ChecksOverview checks={value || []} />;
};
@@ -0,0 +1,17 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ScorecardsOverview } from './ScorecardsOverview';
+19
View File
@@ -0,0 +1,19 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export {
techInsightsPlugin,
EntityTechInsightsScorecardContent,
} from './plugin';
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { techInsightsPlugin } from './plugin';
describe('tech insights', () => {
it('should export plugin', () => {
expect(techInsightsPlugin).toBeDefined();
});
});
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
createPlugin,
createRoutableExtension,
createApiFactory,
discoveryApiRef,
} from '@backstage/core-plugin-api';
import { rootRouteRef } from './routes';
import { techInsightsApiRef } from './api/TechInsightsApi';
import { TechInsightsClient } from './api/TechInsightsClient';
/**
* @public
*/
export const techInsightsPlugin = createPlugin({
id: 'tech-insights',
apis: [
createApiFactory({
api: techInsightsApiRef,
deps: { discoveryApi: discoveryApiRef },
factory: ({ discoveryApi }) => new TechInsightsClient({ discoveryApi }),
}),
],
routes: {
root: rootRouteRef,
},
});
/**
* @public
*/
export const EntityTechInsightsScorecardContent = techInsightsPlugin.provide(
createRoutableExtension({
name: 'EntityTechInsightsScorecardContent',
component: () =>
import('./components/ScorecardsOverview').then(m => m.ScorecardsOverview),
mountPoint: rootRouteRef,
}),
);
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createRouteRef } from '@backstage/core-plugin-api';
export const rootRouteRef = createRouteRef({
id: 'tech-insights',
});
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import '@testing-library/jest-dom';
import 'cross-fetch/polyfill';