diff --git a/.changeset/popular-rules-hang.md b/.changeset/popular-rules-hang.md
new file mode 100644
index 0000000000..593cfcd3b6
--- /dev/null
+++ b/.changeset/popular-rules-hang.md
@@ -0,0 +1,11 @@
+---
+'example-app': patch
+'example-backend': patch
+'@backstage/plugin-scorecards': patch
+'@backstage/plugin-tech-insights-backend': patch
+'@backstage/plugin-tech-insights-common': patch
+---
+
+Removed unecessary check in @backstage/plugin-tech-insights-backend
+
+Added new property 'result' in every CheckResult in @backstage/plugin-tech-insights-common
diff --git a/packages/app/package.json b/packages/app/package.json
index 9a1fb108f6..82fdeb6d18 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -36,6 +36,7 @@
"@backstage/plugin-pagerduty": "0.3.17",
"@backstage/plugin-rollbar": "^0.3.18",
"@backstage/plugin-scaffolder": "^0.11.8",
+ "@backstage/plugin-scorecards": "^0.1.0",
"@backstage/plugin-search": "^0.4.15",
"@backstage/plugin-sentry": "^0.3.26",
"@backstage/plugin-shortcuts": "^0.1.12",
diff --git a/plugins/scorecards/.eslintrc.js b/plugins/scorecards/.eslintrc.js
new file mode 100644
index 0000000000..13573efa9c
--- /dev/null
+++ b/plugins/scorecards/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: [require.resolve('@backstage/cli/config/eslint')],
+};
diff --git a/plugins/scorecards/README.md b/plugins/scorecards/README.md
new file mode 100644
index 0000000000..2ff9aaf1ab
--- /dev/null
+++ b/plugins/scorecards/README.md
@@ -0,0 +1,52 @@
+# Scorecards
+
+This plugin represents scorecards which are rendered as a part of the default Backstage Tech Insights feature.
+It provides UI for the scorecards as well as a check overview.
+
+## Installation
+
+### Install the plugin
+
+```bash
+# From your Backstage root directory
+cd packages/app
+yarn add @backstage/plugin-scorecards
+```
+
+### Adding the plugin to your `packages/app`
+
+```tsx
+// In packages/app/src/App.tsx
+
+import { EntityScorecardContent } from '@backstage/plugin-scorecards';
+
+} />;
+```
+
+3. Add Scorecards overview page to the EntityPage:
+
+```tsx
+// packages/app/src/components/catalog/EntityPage.tsx
+
+import { EntityScorecardContent } from '@backstage/plugin-scorecards';
+
+const serviceEntityPage = (
+
+
+ {overviewContent}
+
+
+ {cicdContent}
+
+ ...
+
+
+
+ ...
+
+);
+```
+
+## Links
+
+- [The Backstage homepage](https://backstage.io)
diff --git a/plugins/scorecards/api-report.md b/plugins/scorecards/api-report.md
new file mode 100644
index 0000000000..eb3ce4533b
--- /dev/null
+++ b/plugins/scorecards/api-report.md
@@ -0,0 +1,27 @@
+## API Report File for "@backstage/plugin-scorecards"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+///
+
+import { BackstagePlugin } from '@backstage/core-plugin-api';
+import { RouteRef } from '@backstage/core-plugin-api';
+
+// Warning: (ae-missing-release-tag) "EntityScorecardContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const EntityScorecardContent: () => JSX.Element;
+
+// Warning: (ae-missing-release-tag) "scorecardsPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export const scorecardsPlugin: BackstagePlugin<
+ {
+ root: RouteRef;
+ },
+ {}
+>;
+
+// (No @packageDocumentation comment for this package)
+```
diff --git a/plugins/scorecards/dev/index.tsx b/plugins/scorecards/dev/index.tsx
new file mode 100644
index 0000000000..559e92b969
--- /dev/null
+++ b/plugins/scorecards/dev/index.tsx
@@ -0,0 +1,27 @@
+/*
+ * 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 { createDevApp } from '@backstage/dev-utils';
+import { scorecardsPlugin, EntityScorecardContent } from '../src/plugin';
+
+createDevApp()
+ .registerPlugin(scorecardsPlugin)
+ .addPage({
+ element: ,
+ title: 'Root Page',
+ path: '/scorecards',
+ })
+ .render();
diff --git a/plugins/scorecards/package.json b/plugins/scorecards/package.json
new file mode 100644
index 0000000000..4d104410da
--- /dev/null
+++ b/plugins/scorecards/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "@backstage/plugin-scorecards",
+ "version": "0.1.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.esm.js",
+ "types": "dist/index.d.ts"
+ },
+ "scripts": {
+ "build": "backstage-cli plugin:build",
+ "start": "backstage-cli plugin:serve",
+ "lint": "backstage-cli lint",
+ "test": "backstage-cli test",
+ "diff": "backstage-cli plugin:diff",
+ "prepack": "backstage-cli prepack",
+ "postpack": "backstage-cli postpack",
+ "clean": "backstage-cli clean"
+ },
+ "dependencies": {
+ "@backstage/core-components": "^0.7.2",
+ "@backstage/core-plugin-api": "^0.1.12",
+ "@backstage/theme": "^0.2.12",
+ "@material-ui/core": "^4.12.2",
+ "@material-ui/icons": "^4.9.1",
+ "@material-ui/lab": "4.0.0-alpha.57",
+ "react": "^16.13.1",
+ "react-dom": "^16.13.1",
+ "react-use": "^17.2.4",
+ "react-router-dom": "6.0.0-beta.0",
+ "@backstage/plugin-catalog-react": "^0.6.2",
+ "@backstage/plugin-tech-insights-common": "^0.1.0"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.8.1",
+ "@backstage/core-app-api": "^0.1.19",
+ "@backstage/dev-utils": "^0.2.12",
+ "@backstage/test-utils": "^0.1.20",
+ "@testing-library/jest-dom": "^5.10.1",
+ "@testing-library/react": "^11.2.5",
+ "@testing-library/user-event": "^13.1.8",
+ "@types/jest": "*",
+ "@types/node": "*",
+ "msw": "^0.35.0",
+ "cross-fetch": "^3.0.6"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/scorecards/src/api/ScorecardsApi.ts b/plugins/scorecards/src/api/ScorecardsApi.ts
new file mode 100644
index 0000000000..83f34d4cf5
--- /dev/null
+++ b/plugins/scorecards/src/api/ScorecardsApi.ts
@@ -0,0 +1,44 @@
+/*
+ * 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';
+
+export const scorecardsApiRef = createApiRef({
+ id: 'plugin.scorecards.service',
+ description: 'Used by the scorecards plugin to make requests',
+});
+
+export interface ScorecardsApi {
+ getScorecardsDefinition: (
+ type: string,
+ value: CheckResult[],
+ ) => CheckResultRenderer | undefined;
+ getAllChecks(): Promise;
+ runChecks({
+ namespace,
+ kind,
+ name,
+ checks,
+ }: {
+ namespace: string;
+ kind: string;
+ name: string;
+ checks?: Check[];
+ }): Promise;
+}
diff --git a/plugins/scorecards/src/api/ScorecardsClient.ts b/plugins/scorecards/src/api/ScorecardsClient.ts
new file mode 100644
index 0000000000..bdfc89dc09
--- /dev/null
+++ b/plugins/scorecards/src/api/ScorecardsClient.ts
@@ -0,0 +1,91 @@
+/*
+ * 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 { ScorecardsApi } from './ScorecardsApi';
+import { CheckResult } from '@backstage/plugin-tech-insights-common';
+import { Check } from './types';
+import { DiscoveryApi } from '@backstage/core-plugin-api';
+import {
+ CheckResultRenderer,
+ defaultCheckResultRenderers,
+} from '../components/CheckResultRenderer';
+
+export type Options = {
+ discoveryApi: DiscoveryApi;
+ proxyPath?: string;
+};
+
+export class ScorecardsClient implements ScorecardsApi {
+ private readonly discoveryApi: DiscoveryApi;
+ private baseUrl: string = '';
+
+ 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);
+ }
+
+ getBaseUrl: () => Promise = async () => {
+ if (!this.baseUrl) {
+ this.baseUrl = await this.discoveryApi.getBaseUrl('tech-insights');
+ }
+ return this.baseUrl;
+ };
+
+ async getAllChecks(): Promise {
+ const url = await this.getBaseUrl();
+ const allChecks = await fetch(`${url}/checks`);
+ const payload = await allChecks.json();
+ if (!allChecks.ok) {
+ throw new Error(payload.errors[0]);
+ }
+ return payload;
+ }
+
+ async runChecks({
+ namespace,
+ kind,
+ name,
+ checks,
+ }: {
+ namespace: string;
+ kind: string;
+ name: string;
+ checks: Check[];
+ }): Promise {
+ const url = await this.getBaseUrl();
+ const allChecks = checks ? checks : await this.getAllChecks();
+ const checkIds = allChecks.map((check: Check) => check.id);
+ const response = await fetch(
+ `${url}/checks/run/${namespace}/${kind}/${name}`,
+ {
+ method: 'POST',
+ body: JSON.stringify({ checks: checkIds }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ },
+ );
+ const result = await response.json();
+ return result;
+ }
+}
diff --git a/plugins/scorecards/src/api/index.ts b/plugins/scorecards/src/api/index.ts
new file mode 100644
index 0000000000..afebc5432f
--- /dev/null
+++ b/plugins/scorecards/src/api/index.ts
@@ -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 './ScorecardsApi';
+export * from './ScorecardsClient';
diff --git a/plugins/scorecards/src/api/types.ts b/plugins/scorecards/src/api/types.ts
new file mode 100644
index 0000000000..20071ba0c9
--- /dev/null
+++ b/plugins/scorecards/src/api/types.ts
@@ -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[];
+};
diff --git a/plugins/scorecards/src/components/BooleanCheck/BooleanCheck.tsx b/plugins/scorecards/src/components/BooleanCheck/BooleanCheck.tsx
new file mode 100644
index 0000000000..3920538983
--- /dev/null
+++ b/plugins/scorecards/src/components/BooleanCheck/BooleanCheck.tsx
@@ -0,0 +1,62 @@
+/*
+ * 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';
+
+const useStyles = makeStyles(() => ({
+ listItemText: {
+ paddingRight: '1rem',
+ flex: '0 1 auto',
+ },
+ icon: {
+ marginLeft: 'auto',
+ },
+}));
+
+type Prop = {
+ checkResult: CheckResult[];
+};
+
+const renderResult = (classes: any, result: Boolean) => {
+ return result ? (
+
+ ) : (
+
+ );
+};
+
+export const BooleanCheck = ({ checkResult }: Prop) => {
+ const classes = useStyles();
+
+ return (
+
+ {checkResult!.map(check => (
+
+
+ {renderResult(classes, check.result)}
+
+ ))}
+
+ );
+};
diff --git a/plugins/scorecards/src/components/BooleanCheck/index.ts b/plugins/scorecards/src/components/BooleanCheck/index.ts
new file mode 100644
index 0000000000..729ab4d62e
--- /dev/null
+++ b/plugins/scorecards/src/components/BooleanCheck/index.ts
@@ -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';
diff --git a/plugins/scorecards/src/components/CheckResultRenderer.tsx b/plugins/scorecards/src/components/CheckResultRenderer.tsx
new file mode 100644
index 0000000000..adac458d74
--- /dev/null
+++ b/plugins/scorecards/src/components/CheckResultRenderer.tsx
@@ -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 checks:',
+ component: ,
+ },
+ ];
+}
diff --git a/plugins/scorecards/src/components/ScorecardsOverview/ChecksOverview.tsx b/plugins/scorecards/src/components/ScorecardsOverview/ChecksOverview.tsx
new file mode 100644
index 0000000000..3c66226da9
--- /dev/null
+++ b/plugins/scorecards/src/components/ScorecardsOverview/ChecksOverview.tsx
@@ -0,0 +1,66 @@
+/*
+ * 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 { scorecardsApiRef } from '../../api/ScorecardsApi';
+
+const useStyles = makeStyles(() => ({
+ contentScorecards: {
+ paddingLeft: 0,
+ paddingRight: 0,
+ },
+ subheader: {
+ fontWeight: 'bold',
+ },
+}));
+
+type Checks = {
+ checks: CheckResult[];
+};
+
+export const ChecksOverview = ({ checks }: Checks) => {
+ const classes = useStyles();
+ const api = useApi(scorecardsApiRef);
+ const checkRenderType = api.getScorecardsDefinition(
+ checks[0].check.type,
+ checks,
+ );
+
+ if (checkRenderType) {
+ return (
+
+
+
+
+
+ {checkRenderType.description}
+
+
+ {checkRenderType.component}
+
+
+
+
+
+ );
+ }
+
+ return <>>;
+};
diff --git a/plugins/scorecards/src/components/ScorecardsOverview/ScorecardsOverview.tsx b/plugins/scorecards/src/components/ScorecardsOverview/ScorecardsOverview.tsx
new file mode 100644
index 0000000000..7bfd57be72
--- /dev/null
+++ b/plugins/scorecards/src/components/ScorecardsOverview/ScorecardsOverview.tsx
@@ -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 { scorecardsApiRef } from '../../api/ScorecardsApi';
+
+export const ScorecardsOverview = () => {
+ const api = useApi(scorecardsApiRef);
+ const { namespace, kind, name } = useParams();
+
+ const { value, loading, error } = useAsync(
+ async () => await api.runChecks({ namespace, kind, name }),
+ );
+
+ if (loading) {
+ return ;
+ } else if (error) {
+ return {error.message};
+ }
+
+ return ;
+};
diff --git a/plugins/scorecards/src/components/ScorecardsOverview/index.ts b/plugins/scorecards/src/components/ScorecardsOverview/index.ts
new file mode 100644
index 0000000000..64198790d9
--- /dev/null
+++ b/plugins/scorecards/src/components/ScorecardsOverview/index.ts
@@ -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';
diff --git a/plugins/scorecards/src/index.ts b/plugins/scorecards/src/index.ts
new file mode 100644
index 0000000000..cba54febcf
--- /dev/null
+++ b/plugins/scorecards/src/index.ts
@@ -0,0 +1,16 @@
+/*
+ * 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 { scorecardsPlugin, EntityScorecardContent } from './plugin';
diff --git a/plugins/scorecards/src/plugin.test.ts b/plugins/scorecards/src/plugin.test.ts
new file mode 100644
index 0000000000..537a6399bf
--- /dev/null
+++ b/plugins/scorecards/src/plugin.test.ts
@@ -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 { scorecardsPlugin } from './plugin';
+
+describe('scorecards', () => {
+ it('should export plugin', () => {
+ expect(scorecardsPlugin).toBeDefined();
+ });
+});
diff --git a/plugins/scorecards/src/plugin.ts b/plugins/scorecards/src/plugin.ts
new file mode 100644
index 0000000000..c9f0d47571
--- /dev/null
+++ b/plugins/scorecards/src/plugin.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 { scorecardsApiRef } from './api/ScorecardsApi';
+import { ScorecardsClient } from './api';
+
+export const scorecardsPlugin = createPlugin({
+ id: 'scorecards',
+ apis: [
+ createApiFactory({
+ api: scorecardsApiRef,
+ deps: { discoveryApi: discoveryApiRef },
+ factory: ({ discoveryApi }) => new ScorecardsClient({ discoveryApi }),
+ }),
+ ],
+ routes: {
+ root: rootRouteRef,
+ },
+});
+
+export const EntityScorecardContent = scorecardsPlugin.provide(
+ createRoutableExtension({
+ name: 'EntityScorecardContent',
+ component: () =>
+ import('./components/ScorecardsOverview').then(m => m.ScorecardsOverview),
+ mountPoint: rootRouteRef,
+ }),
+);
diff --git a/plugins/scorecards/src/routes.ts b/plugins/scorecards/src/routes.ts
new file mode 100644
index 0000000000..c81a4b8eef
--- /dev/null
+++ b/plugins/scorecards/src/routes.ts
@@ -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({
+ title: 'scorecards',
+});
diff --git a/plugins/scorecards/src/setupTests.ts b/plugins/scorecards/src/setupTests.ts
new file mode 100644
index 0000000000..fc6dbd98f8
--- /dev/null
+++ b/plugins/scorecards/src/setupTests.ts
@@ -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';
diff --git a/plugins/tech-insights-backend/src/service/router.ts b/plugins/tech-insights-backend/src/service/router.ts
index a8951318ea..80902c307c 100644
--- a/plugins/tech-insights-backend/src/service/router.ts
+++ b/plugins/tech-insights-backend/src/service/router.ts
@@ -92,11 +92,6 @@ export async function createRouter<
router.post('/checks/run/:namespace/:kind/:name', async (req, res) => {
const { namespace, kind, name } = req.params;
try {
- if (!('checks' in req.body)) {
- return res.status(422).send({
- message: 'Failed to get checks from request.',
- });
- }
const { checks }: { checks: string[] } = req.body;
const entityTriplet = stringifyEntityRef({ namespace, kind, name });
const checkResult = await factChecker.runChecks(entityTriplet, checks);
diff --git a/plugins/tech-insights-common/api-report.md b/plugins/tech-insights-common/api-report.md
index ddb38cfa85..3c806daa57 100644
--- a/plugins/tech-insights-common/api-report.md
+++ b/plugins/tech-insights-common/api-report.md
@@ -25,6 +25,7 @@ export interface CheckResponse {
export type CheckResult = {
facts: FactResponse;
check: CheckResponse;
+ result: any;
};
// @public
diff --git a/plugins/tech-insights-common/src/index.ts b/plugins/tech-insights-common/src/index.ts
index 4bfc660748..5b6e814474 100644
--- a/plugins/tech-insights-common/src/index.ts
+++ b/plugins/tech-insights-common/src/index.ts
@@ -112,6 +112,7 @@ export type FactResponse = {
export type CheckResult = {
facts: FactResponse;
check: CheckResponse;
+ result: any;
};
/**