Add @backstage/plugin-sonarqube-react
Signed-off-by: Magnus Persson <magnus.persson@fortnox.se>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@backstage/plugin-sonarqube-react",
|
||||
"version": "0.0.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",
|
||||
"alphaTypes": "dist/index.alpha.d.ts"
|
||||
},
|
||||
"backstage": {
|
||||
"role": "web-library"
|
||||
},
|
||||
"homepage": "https://backstage.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/backstage/backstage",
|
||||
"directory": "plugins/sonarqube-react"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build --experimental-type-build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack",
|
||||
"clean": "backstage-cli package clean",
|
||||
"start": "backstage-cli package start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "workspace:^",
|
||||
"@backstage/core-plugin-api": "workspace:^"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1 || ^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"alpha"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2022 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';
|
||||
|
||||
export type MetricKey =
|
||||
// alert status
|
||||
| 'alert_status'
|
||||
|
||||
// bugs and rating (-> reliability)
|
||||
| 'bugs'
|
||||
| 'reliability_rating'
|
||||
|
||||
// vulnerabilities and rating (-> security)
|
||||
| 'vulnerabilities'
|
||||
| 'security_rating'
|
||||
|
||||
// code smells and rating (-> maintainability)
|
||||
| 'code_smells'
|
||||
| 'sqale_rating'
|
||||
|
||||
// security hotspots
|
||||
| 'security_hotspots_reviewed'
|
||||
| 'security_review_rating'
|
||||
|
||||
// coverage
|
||||
| 'coverage'
|
||||
|
||||
// duplicated lines
|
||||
| 'duplicated_lines_density';
|
||||
|
||||
export type SonarUrlProcessorFunc = (identifier: string) => string;
|
||||
|
||||
/**
|
||||
* Define a type to make sure that all metrics are used
|
||||
*/
|
||||
export type Metrics = {
|
||||
[key in MetricKey]: string | undefined;
|
||||
};
|
||||
|
||||
export interface FindingSummary {
|
||||
lastAnalysis: string;
|
||||
metrics: Metrics;
|
||||
projectUrl: string;
|
||||
getIssuesUrl: SonarUrlProcessorFunc;
|
||||
getComponentMeasuresUrl: SonarUrlProcessorFunc;
|
||||
getSecurityHotspotsUrl: () => string;
|
||||
}
|
||||
|
||||
export const sonarQubeApiRef = createApiRef<SonarQubeApi>({
|
||||
id: 'plugin.sonarqube.service',
|
||||
});
|
||||
|
||||
/** @alpha */
|
||||
export type SonarQubeApi = {
|
||||
getFindingSummary(options: {
|
||||
componentKey?: string;
|
||||
projectInstance?: string;
|
||||
}): Promise<FindingSummary | undefined>;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2022 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 { sonarQubeApiRef } from './SonarQubeApi';
|
||||
export type {
|
||||
Metrics,
|
||||
MetricKey,
|
||||
SonarQubeApi,
|
||||
FindingSummary,
|
||||
SonarUrlProcessorFunc,
|
||||
} from './SonarQubeApi';
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
isSonarQubeAvailable,
|
||||
SONARQUBE_PROJECT_KEY_ANNOTATION,
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR,
|
||||
} from './isSonarQubeAvailable';
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
isSonarQubeAvailable,
|
||||
SONARQUBE_PROJECT_KEY_ANNOTATION,
|
||||
} from './isSonarQubeAvailable';
|
||||
|
||||
const createDummyEntity = (sonarqubeAnnotationValue: string): Entity => {
|
||||
return {
|
||||
apiVersion: '',
|
||||
kind: '',
|
||||
metadata: {
|
||||
name: 'dummy',
|
||||
annotations: {
|
||||
[SONARQUBE_PROJECT_KEY_ANNOTATION]: sonarqubeAnnotationValue,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
describe('isSonarQubeAvailable', () => {
|
||||
it('returns true if sonarqube annotation defined', () => {
|
||||
const entity = createDummyEntity('dummy');
|
||||
expect(isSonarQubeAvailable(entity)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if sonarqube annotation empty', () => {
|
||||
const entity = createDummyEntity('');
|
||||
expect(isSonarQubeAvailable(entity)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if sonarqube annotation not defined', () => {
|
||||
const entity = {
|
||||
apiVersion: '',
|
||||
kind: '',
|
||||
metadata: {
|
||||
name: 'dummy',
|
||||
annotations: {},
|
||||
},
|
||||
};
|
||||
expect(isSonarQubeAvailable(entity)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export const SONARQUBE_PROJECT_KEY_ANNOTATION = 'sonarqube.org/project-key';
|
||||
export const SONARQUBE_PROJECT_INSTANCE_SEPARATOR = '/';
|
||||
|
||||
/** @public */
|
||||
export const isSonarQubeAvailable = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[SONARQUBE_PROJECT_KEY_ANNOTATION]);
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2022 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 { useProjectInfo } from './useProjectInfo';
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR,
|
||||
SONARQUBE_PROJECT_KEY_ANNOTATION,
|
||||
} from '../components';
|
||||
import { useProjectInfo } from './useProjectInfo';
|
||||
|
||||
const createDummyEntity = (sonarqubeAnnotationValue: string): Entity => {
|
||||
return {
|
||||
apiVersion: '',
|
||||
kind: '',
|
||||
metadata: {
|
||||
name: 'dummy',
|
||||
annotations: {
|
||||
[SONARQUBE_PROJECT_KEY_ANNOTATION]: sonarqubeAnnotationValue,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
describe('useProjectInfo', () => {
|
||||
const DUMMY_INSTANCE = 'dummyInstance';
|
||||
const DUMMY_KEY = 'dummyKey';
|
||||
|
||||
it('parse annotation with key and instance', () => {
|
||||
const entity = createDummyEntity(
|
||||
DUMMY_INSTANCE + SONARQUBE_PROJECT_INSTANCE_SEPARATOR + DUMMY_KEY,
|
||||
);
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: DUMMY_INSTANCE,
|
||||
projectKey: DUMMY_KEY,
|
||||
});
|
||||
});
|
||||
|
||||
it('parse annotation with instance, tenant/project-key', () => {
|
||||
const DUMMY_KEY_WITH_TENANT = 'dummy-tenant/dummyKey';
|
||||
const entity = createDummyEntity(
|
||||
DUMMY_INSTANCE +
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR +
|
||||
DUMMY_KEY_WITH_TENANT,
|
||||
);
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: DUMMY_INSTANCE,
|
||||
projectKey: DUMMY_KEY_WITH_TENANT,
|
||||
});
|
||||
});
|
||||
|
||||
it('parse annotation with instance, tenant:project-key', () => {
|
||||
const DUMMY_KEY_WITH_TENANT = 'dummy-tenant:dummyKey';
|
||||
const entity = createDummyEntity(
|
||||
DUMMY_INSTANCE +
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR +
|
||||
DUMMY_KEY_WITH_TENANT,
|
||||
);
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: DUMMY_INSTANCE,
|
||||
projectKey: DUMMY_KEY_WITH_TENANT,
|
||||
});
|
||||
});
|
||||
|
||||
// compatibility with previous mono-instance sonarqube config
|
||||
it('parse annotation with only key', () => {
|
||||
const entity = createDummyEntity(DUMMY_KEY);
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: undefined,
|
||||
projectKey: DUMMY_KEY,
|
||||
});
|
||||
});
|
||||
|
||||
it('handle empty annotation', () => {
|
||||
const entity = createDummyEntity('');
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: undefined,
|
||||
projectKey: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('handle non-existent annotation', () => {
|
||||
const entity = {
|
||||
apiVersion: '',
|
||||
kind: '',
|
||||
metadata: {
|
||||
name: 'dummy',
|
||||
annotations: {},
|
||||
},
|
||||
};
|
||||
expect(useProjectInfo(entity)).toEqual({
|
||||
projectInstance: undefined,
|
||||
projectKey: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR,
|
||||
SONARQUBE_PROJECT_KEY_ANNOTATION,
|
||||
} from '../components';
|
||||
|
||||
/**
|
||||
*
|
||||
* Try to parse sonarqube information from an entity.
|
||||
*
|
||||
* If part or all info are not found, they will default to undefined
|
||||
*
|
||||
* @alpha
|
||||
* @param entity entity to find the sonarqube information from.
|
||||
* @return a ProjectInfo properly populated.
|
||||
*/
|
||||
export const useProjectInfo = (
|
||||
entity: Entity,
|
||||
): {
|
||||
projectInstance: string | undefined;
|
||||
projectKey: string | undefined;
|
||||
} => {
|
||||
let projectInstance = undefined;
|
||||
let projectKey = undefined;
|
||||
const annotation =
|
||||
entity?.metadata.annotations?.[SONARQUBE_PROJECT_KEY_ANNOTATION];
|
||||
if (annotation) {
|
||||
const instanceSeparatorIndex = annotation.indexOf(
|
||||
SONARQUBE_PROJECT_INSTANCE_SEPARATOR,
|
||||
);
|
||||
if (instanceSeparatorIndex > -1) {
|
||||
// Examples:
|
||||
// instanceA/projectA -> projectInstance = "instanceA" & projectKey = "projectA"
|
||||
// instanceA/tenantA:projectA -> projectInstance = "instanceA" & projectKey = "tenantA:projectA"
|
||||
// instanceA/tenantA/projectA -> projectInstance = "instanceA" & projectKey = "tenantA/projectA"
|
||||
projectInstance = annotation.substring(0, instanceSeparatorIndex);
|
||||
projectKey = annotation.substring(instanceSeparatorIndex + 1);
|
||||
} else {
|
||||
projectKey = annotation;
|
||||
}
|
||||
}
|
||||
return { projectInstance, projectKey };
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2022 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 './api';
|
||||
export * from './components';
|
||||
export * from './hooks';
|
||||
Reference in New Issue
Block a user