@backstage-community/plugin-code-coverage-backend 0.2.32 → 0.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.cjs.js +15 -23
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +16 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @backstage-community/plugin-code-coverage-backend
|
|
2
2
|
|
|
3
|
+
## 0.2.34
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ae2ee8a: Updated dependency `@types/supertest` to `^6.0.0`.
|
|
8
|
+
Updated dependency `supertest` to `^7.0.0`.
|
|
9
|
+
|
|
10
|
+
## 0.2.33
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 1a94274: version:bump to v1.29.1
|
|
15
|
+
|
|
3
16
|
## 0.2.32
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -60,8 +60,7 @@ class CoverageUtils {
|
|
|
60
60
|
this.urlReader = urlReader;
|
|
61
61
|
}
|
|
62
62
|
async processCoveragePayload(entity, req) {
|
|
63
|
-
|
|
64
|
-
const enforceScmFiles = ((_a = entity.metadata.annotations) == null ? void 0 : _a["backstage.io/code-coverage"]) === "scm-only" || false;
|
|
63
|
+
const enforceScmFiles = entity.metadata.annotations?.["backstage.io/code-coverage"] === "scm-only" || false;
|
|
65
64
|
let sourceLocation = void 0;
|
|
66
65
|
let vcs = void 0;
|
|
67
66
|
let scmFiles = [];
|
|
@@ -78,11 +77,11 @@ class CoverageUtils {
|
|
|
78
77
|
)}`
|
|
79
78
|
);
|
|
80
79
|
}
|
|
81
|
-
vcs =
|
|
80
|
+
vcs = this.scm.byUrl?.(sourceLocation);
|
|
82
81
|
if (!vcs) {
|
|
83
82
|
throw new errors.InputError(`Unable to determine SCM from ${sourceLocation}`);
|
|
84
83
|
}
|
|
85
|
-
const scmTree = await
|
|
84
|
+
const scmTree = await this.urlReader.readTree?.(sourceLocation);
|
|
86
85
|
if (!scmTree) {
|
|
87
86
|
throw new errors.NotFoundError(`Unable to read tree from ${sourceLocation}`);
|
|
88
87
|
}
|
|
@@ -103,7 +102,7 @@ class CoverageUtils {
|
|
|
103
102
|
return {
|
|
104
103
|
metadata: {
|
|
105
104
|
vcs: {
|
|
106
|
-
type:
|
|
105
|
+
type: vcs?.type || "unknown",
|
|
107
106
|
location: sourceLocation || "unknown"
|
|
108
107
|
},
|
|
109
108
|
generationTime: Date.now()
|
|
@@ -142,9 +141,8 @@ class CodeCoverageDatabase {
|
|
|
142
141
|
this.db = db;
|
|
143
142
|
}
|
|
144
143
|
static async create(database) {
|
|
145
|
-
var _a;
|
|
146
144
|
const knex = await database.getClient();
|
|
147
|
-
if (!
|
|
145
|
+
if (!database.migrations?.skip) {
|
|
148
146
|
await knex.migrate.latest({
|
|
149
147
|
directory: migrationsDir
|
|
150
148
|
});
|
|
@@ -205,9 +203,8 @@ class Cobertura {
|
|
|
205
203
|
* @param scmFiles - list of files that are committed to SCM
|
|
206
204
|
*/
|
|
207
205
|
convert(xml, scmFiles) {
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
const pc = (_b = xml.coverage.package) == null ? void 0 : _b.filter(Boolean).flatMap((p) => p.classes);
|
|
206
|
+
const ppc = xml.coverage.packages?.flatMap((p) => p.package).filter(Boolean).flatMap((p) => p.classes);
|
|
207
|
+
const pc = xml.coverage.package?.filter(Boolean).flatMap((p) => p.classes);
|
|
211
208
|
const classes = [ppc, pc].flat().filter(Boolean).flatMap((c) => c.class).filter(Boolean);
|
|
212
209
|
const jscov = [];
|
|
213
210
|
classes.forEach((c) => {
|
|
@@ -264,9 +261,8 @@ class Cobertura {
|
|
|
264
261
|
* @param clz - class coverage information
|
|
265
262
|
*/
|
|
266
263
|
extractLines(clz) {
|
|
267
|
-
var _a;
|
|
268
264
|
const classLines = clz.lines.flatMap((l) => l.line);
|
|
269
|
-
const methodLines =
|
|
265
|
+
const methodLines = clz.methods?.flatMap((m) => m.method).filter(Boolean).flatMap((m) => m.lines).filter(Boolean).flatMap((l) => l.line).filter(
|
|
270
266
|
({ $: methodLine }) => classLines.some(
|
|
271
267
|
({ $: classLine }) => methodLine.number === classLine.number
|
|
272
268
|
) === false
|
|
@@ -333,9 +329,8 @@ class Jacoco {
|
|
|
333
329
|
return jscov;
|
|
334
330
|
}
|
|
335
331
|
extractLines(sourcefile) {
|
|
336
|
-
var _a;
|
|
337
332
|
const parsed = [];
|
|
338
|
-
|
|
333
|
+
sourcefile.line?.forEach((l) => {
|
|
339
334
|
parsed.push({
|
|
340
335
|
number: parseInt(l.$.nr, 10),
|
|
341
336
|
missed_instructions: parseInt(l.$.mi, 10),
|
|
@@ -410,8 +405,7 @@ class Lcov {
|
|
|
410
405
|
* @param value - line coverage information
|
|
411
406
|
*/
|
|
412
407
|
processLineHit(currentFile, value) {
|
|
413
|
-
if (!currentFile)
|
|
414
|
-
return;
|
|
408
|
+
if (!currentFile) return;
|
|
415
409
|
const [lineNumber, hits] = value.split(",");
|
|
416
410
|
currentFile.lineHits[Number(lineNumber)] = Number(hits);
|
|
417
411
|
}
|
|
@@ -422,8 +416,7 @@ class Lcov {
|
|
|
422
416
|
* @param value - branch coverage information
|
|
423
417
|
*/
|
|
424
418
|
processBranchHit(currentFile, value) {
|
|
425
|
-
if (!currentFile)
|
|
426
|
-
return;
|
|
419
|
+
if (!currentFile) return;
|
|
427
420
|
const [lineNumber, , , hits] = value.split(",");
|
|
428
421
|
const lineNumberNum = Number(lineNumber);
|
|
429
422
|
const isHit = Number(hits) > 0;
|
|
@@ -440,14 +433,13 @@ class Lcov {
|
|
|
440
433
|
}
|
|
441
434
|
|
|
442
435
|
const makeRouter = async (options) => {
|
|
443
|
-
var _a, _b;
|
|
444
436
|
const { config, logger, discovery, database, urlReader } = options;
|
|
445
437
|
const codeCoverageDatabase = await CodeCoverageDatabase.create(database);
|
|
446
438
|
const codecovUrl = await discovery.getExternalBaseUrl("code-coverage");
|
|
447
|
-
const catalogApi =
|
|
439
|
+
const catalogApi = options.catalogApi ?? new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
448
440
|
const scm = integration.ScmIntegrations.fromConfig(config);
|
|
449
441
|
const { auth, httpAuth } = backendCommon.createLegacyAuthAdapters(options);
|
|
450
|
-
const bodySizeLimit =
|
|
442
|
+
const bodySizeLimit = config.getOptionalString("codeCoverage.bodySizeLimit") ?? "100kb";
|
|
451
443
|
bodyParserXml__default.default(BodyParser__default.default);
|
|
452
444
|
const router = Router__default.default();
|
|
453
445
|
router.use(
|
|
@@ -502,7 +494,7 @@ const makeRouter = async (options) => {
|
|
|
502
494
|
const { limit } = req.query;
|
|
503
495
|
const history = await codeCoverageDatabase.getHistory(
|
|
504
496
|
entity,
|
|
505
|
-
parseInt(
|
|
497
|
+
parseInt(limit?.toString() || "10", 10)
|
|
506
498
|
);
|
|
507
499
|
res.status(200).json(history);
|
|
508
500
|
});
|
|
@@ -541,7 +533,7 @@ const makeRouter = async (options) => {
|
|
|
541
533
|
});
|
|
542
534
|
return;
|
|
543
535
|
}
|
|
544
|
-
const content = await
|
|
536
|
+
const content = await scmFile?.content();
|
|
545
537
|
if (!content) {
|
|
546
538
|
res.status(400).json({
|
|
547
539
|
message: "Couldn't process content of file in SCM",
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/service/CoverageUtils.ts","../src/service/CodeCoverageDatabase.ts","../src/service/converter/cobertura.ts","../src/service/converter/jacoco.ts","../src/service/converter/lcov.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Request } from 'express';\nimport { UrlReader } from '@backstage/backend-common';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport {\n Entity,\n getEntitySourceLocation,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { ScmIntegration, ScmIntegrations } from '@backstage/integration';\nimport { AggregateCoverage, FileEntry, JsonCodeCoverage } from './types';\n\nexport const calculatePercentage = (\n available: number,\n covered: number,\n): number => {\n if (available === 0) {\n return 0;\n }\n return parseFloat(((covered / available) * 100).toFixed(2));\n};\n\nexport const aggregateCoverage = (c: JsonCodeCoverage): AggregateCoverage => {\n let availableLine = 0;\n let coveredLine = 0;\n let availableBranch = 0;\n let coveredBranch = 0;\n c.files.forEach(f => {\n availableLine += Object.keys(f.lineHits).length;\n coveredLine += Object.values(f.lineHits).filter(l => l > 0).length;\n\n availableBranch += Object.keys(f.branchHits)\n .map(b => parseInt(b, 10))\n .map((b: number) => f.branchHits[b].available)\n .filter(Boolean)\n .reduce((acc, curr) => acc + curr, 0);\n coveredBranch += Object.keys(f.branchHits)\n .map(b => parseInt(b, 10))\n .map((b: number) => f.branchHits[b].covered)\n .filter(Boolean)\n .reduce((acc, curr) => acc + curr, 0);\n });\n\n return {\n timestamp: c.metadata.generationTime,\n branch: {\n available: availableBranch,\n covered: coveredBranch,\n missed: availableBranch - coveredBranch,\n percentage: calculatePercentage(availableBranch, coveredBranch),\n },\n line: {\n available: availableLine,\n covered: coveredLine,\n missed: availableLine - coveredLine,\n percentage: calculatePercentage(availableLine, coveredLine),\n },\n };\n};\n\nexport class CoverageUtils {\n constructor(\n readonly scm: Partial<ScmIntegrations>,\n readonly urlReader: Partial<UrlReader>,\n ) {}\n\n async processCoveragePayload(\n entity: Entity,\n req: Request,\n ): Promise<{\n sourceLocation?: string;\n vcs?: ScmIntegration;\n scmFiles: string[];\n body: {};\n }> {\n const enforceScmFiles =\n entity.metadata.annotations?.['backstage.io/code-coverage'] ===\n 'scm-only' || false;\n\n let sourceLocation: string | undefined = undefined;\n let vcs: ScmIntegration | undefined = undefined;\n let scmFiles: string[] = [];\n\n if (enforceScmFiles) {\n try {\n const sl = getEntitySourceLocation(entity);\n sourceLocation = sl.target;\n } catch (e: unknown) {\n // TODO: logging\n }\n\n if (!sourceLocation) {\n throw new InputError(\n `No \"backstage.io/source-location\" annotation on entity ${stringifyEntityRef(\n entity,\n )}`,\n );\n }\n\n vcs = this.scm.byUrl?.(sourceLocation);\n if (!vcs) {\n throw new InputError(`Unable to determine SCM from ${sourceLocation}`);\n }\n\n const scmTree = await this.urlReader.readTree?.(sourceLocation);\n if (!scmTree) {\n throw new NotFoundError(`Unable to read tree from ${sourceLocation}`);\n }\n scmFiles = (await scmTree.files()).map(f => f.path);\n }\n\n const body = this.validateRequestBody(req);\n if (Object.keys(body).length === 0) {\n throw new InputError('Unable to parse body');\n }\n\n return {\n sourceLocation,\n vcs,\n scmFiles,\n body,\n };\n }\n\n async buildCoverage(\n entity: Entity,\n sourceLocation: string | undefined,\n vcs: ScmIntegration | undefined,\n files: FileEntry[],\n ): Promise<JsonCodeCoverage> {\n return {\n metadata: {\n vcs: {\n type: vcs?.type || 'unknown',\n location: sourceLocation || 'unknown',\n },\n generationTime: Date.now(),\n },\n entity: {\n name: entity.metadata.name,\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n },\n files,\n };\n }\n\n validateRequestBody(req: Request) {\n const contentType = req.headers['content-type'];\n if (!contentType) {\n throw new InputError('Content-Type header missing');\n // text/xml or text/plain is allowed\n } else if (!contentType.match(/^text\\/xml|plain($|;)/)) {\n throw new InputError(\n `Content-Type header \"${contentType}\" not supported, expected \"text/xml\" or \"text/plain\" possibly followed by a charset`,\n );\n }\n const body = req.body;\n if (!body) {\n throw new InputError('Missing request body');\n }\n return body;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n PluginDatabaseManager,\n resolvePackagePath,\n} from '@backstage/backend-common';\nimport { NotFoundError } from '@backstage/errors';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\nimport { aggregateCoverage } from './CoverageUtils';\nimport { JsonCodeCoverage, JsonCoverageHistory } from './types';\n\nexport type RawDbCoverageRow = {\n id: string;\n entity: string;\n coverage: string;\n};\n\nexport interface CodeCoverageStore {\n insertCodeCoverage(\n coverage: JsonCodeCoverage,\n ): Promise<{ codeCoverageId: string }>;\n getCodeCoverage(entity: string): Promise<JsonCodeCoverage>;\n getHistory(entity: string, limit: number): Promise<JsonCoverageHistory>;\n}\n\nconst migrationsDir = resolvePackagePath(\n '@backstage-community/plugin-code-coverage-backend',\n 'migrations',\n);\n\nexport class CodeCoverageDatabase implements CodeCoverageStore {\n static async create(\n database: PluginDatabaseManager,\n ): Promise<CodeCoverageStore> {\n const knex = await database.getClient();\n\n if (!database.migrations?.skip) {\n await knex.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n return new CodeCoverageDatabase(knex);\n }\n\n constructor(private readonly db: Knex) {}\n\n async insertCodeCoverage(\n coverage: JsonCodeCoverage,\n ): Promise<{ codeCoverageId: string }> {\n const codeCoverageId = uuid();\n const entity = stringifyEntityRef({\n kind: coverage.entity.kind,\n namespace: coverage.entity.namespace,\n name: coverage.entity.name,\n });\n\n await this.db<RawDbCoverageRow>('code_coverage').insert({\n id: codeCoverageId,\n entity: entity,\n coverage: JSON.stringify(coverage),\n });\n\n return { codeCoverageId };\n }\n\n async getCodeCoverage(entity: string): Promise<JsonCodeCoverage> {\n const [result] = await this.db<RawDbCoverageRow>('code_coverage')\n .where({ entity: entity })\n .orderBy('index', 'desc')\n .limit(1)\n .select();\n\n if (!result) {\n throw new NotFoundError(\n `No coverage for entity '${JSON.stringify(entity)}' found`,\n );\n }\n\n try {\n return JSON.parse(result.coverage);\n } catch (error) {\n throw new Error(`Failed to parse coverage for '${entity}', ${error}`);\n }\n }\n\n async getHistory(\n entity: string,\n limit: number,\n ): Promise<JsonCoverageHistory> {\n const res = await this.db<RawDbCoverageRow>('code_coverage')\n .where({ entity: entity })\n .orderBy('index', 'desc')\n .limit(limit)\n .select();\n\n const history = res\n .map(r => JSON.parse(r.coverage))\n .map(c => aggregateCoverage(c));\n\n const entityName = parseEntityRef(entity);\n\n return {\n entity: {\n name: entityName.name,\n kind: entityName.kind,\n namespace: entityName.namespace,\n },\n history: history,\n };\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { BranchHit, FileEntry } from '../types';\nimport { CoberturaXML, InnerClass, LineHit } from './types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport class Cobertura implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * convert cobertura into shared json coverage format\n *\n * @param xml - cobertura xml object\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(xml: CoberturaXML, scmFiles: string[]): FileEntry[] {\n const ppc = xml.coverage.packages\n ?.flatMap(p => p.package)\n .filter(Boolean)\n .flatMap(p => p.classes);\n const pc = xml.coverage.package?.filter(Boolean).flatMap(p => p.classes);\n\n const classes = [ppc, pc]\n .flat()\n .filter(Boolean)\n .flatMap(c => c.class)\n .filter(Boolean);\n const jscov: Array<FileEntry> = [];\n\n classes.forEach(c => {\n const packageAndFilename = c.$.filename;\n const lines = this.extractLines(c);\n const lineHits: Record<number, number> = {};\n const branchHits: Record<number, BranchHit> = {};\n\n lines.forEach(l => {\n if (!lineHits[l.number]) {\n lineHits[l.number] = 0;\n }\n lineHits[l.number] += l.hits;\n if (l.branch && l['condition-coverage']) {\n const bh = this.parseBranch(l['condition-coverage']);\n if (bh) {\n branchHits[l.number] = bh;\n }\n }\n });\n\n const currentFile = scmFiles\n .map(f => f.trimEnd())\n .find(f => f.endsWith(packageAndFilename));\n this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`);\n if (\n scmFiles.length === 0 ||\n (Object.keys(lineHits).length > 0 && currentFile)\n ) {\n jscov.push({\n filename: currentFile || packageAndFilename,\n branchHits: branchHits,\n lineHits: lineHits,\n });\n }\n });\n\n return jscov;\n }\n\n /**\n * Parses branch coverage information from condition-coverage\n *\n * @param condition - condition-coverage value from line coverage\n */\n private parseBranch(condition: string): BranchHit | null {\n const pattern = /[0-9\\.]+\\%\\s\\(([0-9]+)\\/([0-9]+)\\)/;\n const match = condition.match(pattern);\n if (!match) {\n return null;\n }\n const covered = parseInt(match[1], 10);\n const available = parseInt(match[2], 10);\n return {\n covered: covered,\n missed: available - covered,\n available: available,\n };\n }\n\n /**\n * Extract line hits from a class coverage entry\n *\n * @param clz - class coverage information\n */\n private extractLines(clz: InnerClass): Array<LineHit> {\n const classLines = clz.lines.flatMap(l => l.line);\n const methodLines = clz.methods\n ?.flatMap(m => m.method)\n .filter(Boolean)\n .flatMap(m => m.lines)\n .filter(Boolean)\n .flatMap(l => l.line)\n .filter(\n ({ $: methodLine }) =>\n classLines.some(\n ({ $: classLine }) => methodLine.number === classLine.number,\n ) === false,\n );\n const lines = [classLines, methodLines].flat().filter(Boolean);\n const lineHits = lines.map(l => {\n return {\n number: parseInt(l.$.number as unknown as string, 10),\n hits: parseInt(l.$.hits as unknown as string, 10),\n 'condition-coverage': l.$['condition-coverage'],\n branch: l.$.branch,\n };\n });\n return lineHits;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BranchHit, FileEntry } from '../types';\nimport { JacocoSourceFile, JacocoXML } from './types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\ntype ParsedLine = {\n number: number;\n missed_instructions: number;\n covered_instructions: number;\n missed_branches: number;\n covered_branches: number;\n};\n\nexport class Jacoco implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * Converts jacoco into shared json coverage format\n *\n * @param xml - jacoco xml object\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(xml: JacocoXML, scmFiles: Array<string>): Array<FileEntry> {\n const jscov: Array<FileEntry> = [];\n xml.report.package.forEach(r => {\n const packageName = r.$.name;\n r.sourcefile.forEach(sf => {\n const fileName = sf.$.name;\n const lines = this.extractLines(sf);\n const lineHits: Record<number, number> = {};\n const branchHits: Record<number, BranchHit> = {};\n lines.forEach(l => {\n if (!lineHits[l.number]) {\n lineHits[l.number] = 0;\n }\n lineHits[l.number] += l.covered_instructions;\n const ab = l.covered_branches + l.missed_branches;\n if (ab > 0) {\n branchHits[l.number] = {\n covered: l.covered_branches,\n missed: l.missed_branches,\n available: ab,\n };\n }\n });\n\n const packageAndFilename = `${packageName}/${fileName}`;\n const currentFile = scmFiles\n .map(f => f.trimEnd())\n .find(f => f.endsWith(packageAndFilename));\n this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`);\n if (\n scmFiles.length === 0 ||\n (Object.keys(lineHits).length > 0 && currentFile)\n ) {\n jscov.push({\n filename: currentFile || packageAndFilename,\n branchHits: branchHits,\n lineHits: lineHits,\n });\n }\n });\n });\n\n return jscov;\n }\n\n private extractLines(sourcefile: JacocoSourceFile): ParsedLine[] {\n const parsed: ParsedLine[] = [];\n\n sourcefile.line?.forEach(l => {\n parsed.push({\n number: parseInt(l.$.nr, 10),\n missed_instructions: parseInt(l.$.mi, 10),\n covered_instructions: parseInt(l.$.ci, 10),\n missed_branches: parseInt(l.$.mb, 10),\n covered_branches: parseInt(l.$.cb, 10),\n });\n });\n\n return parsed;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { FileEntry } from '../types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport class Lcov implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * convert lcov into shared json coverage format\n *\n * @param raw - raw lcov report\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(raw: string, scmFiles: string[]): FileEntry[] {\n const lines = raw.split(/\\r?\\n/);\n const jscov: Array<FileEntry> = [];\n let currentFile: FileEntry | null = null;\n\n lines.forEach(line => {\n const [section, value] = line.split(':');\n\n switch (section) {\n // If the line starts with SF, it's a new file\n case 'SF':\n currentFile = this.processNewFile(value, scmFiles);\n break;\n // If the line starts with DA, it's a line hit\n case 'DA':\n this.processLineHit(currentFile, value);\n break;\n // If the line starts with BRDA, it's a branch line\n case 'BRDA':\n this.processBranchHit(currentFile, value);\n break;\n // If the line starts with end_of_record, it's the end of current file\n case 'end_of_record':\n if (currentFile) {\n jscov.push(currentFile);\n currentFile = null;\n }\n break;\n default:\n break;\n }\n });\n\n return jscov;\n }\n\n /**\n * Parses a new file entry\n *\n * @param file - file name from coverage report\n * @param scmFiles - list of files that are committed to SCM\n */\n private processNewFile(file: string, scmFiles: string[]): FileEntry | null {\n const filename = scmFiles.map(f => f.trimEnd()).find(f => file.endsWith(f));\n\n this.logger.debug(`matched ${file} to ${filename}`);\n\n if (scmFiles.length === 0 || filename) {\n return {\n filename: filename || file,\n lineHits: {},\n branchHits: {},\n };\n }\n\n return null;\n }\n\n /**\n * Parses line coverage information\n *\n * @param currentFile - current file entry\n * @param value - line coverage information\n */\n private processLineHit(currentFile: FileEntry | null, value: string): void {\n if (!currentFile) return;\n\n const [lineNumber, hits] = value.split(',');\n currentFile.lineHits[Number(lineNumber)] = Number(hits);\n }\n\n /**\n * Parses branch coverage information\n *\n * @param currentFile - current file entry\n * @param value - branch coverage information\n */\n private processBranchHit(currentFile: FileEntry | null, value: string): void {\n if (!currentFile) return;\n\n const [lineNumber, , , hits] = value.split(',');\n const lineNumberNum = Number(lineNumber);\n const isHit = Number(hits) > 0;\n const branch = currentFile.branchHits[lineNumberNum] || {\n covered: 0,\n available: 0,\n missed: 0,\n };\n\n branch.available++;\n branch.covered += isHit ? 1 : 0;\n branch.missed += isHit ? 0 : 1;\n\n currentFile.branchHits[lineNumberNum] = branch;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport BodyParser from 'body-parser';\nimport bodyParserXml from 'body-parser-xml';\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport {\n createLegacyAuthAdapters,\n errorHandler,\n PluginDatabaseManager,\n PluginEndpointDiscovery,\n UrlReader,\n} from '@backstage/backend-common';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport { Config } from '@backstage/config';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { CodeCoverageDatabase } from './CodeCoverageDatabase';\nimport { aggregateCoverage, CoverageUtils } from './CoverageUtils';\nimport { Cobertura, Converter, Jacoco, Lcov } from './converter';\nimport { getEntitySourceLocation } from '@backstage/catalog-model';\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n config: Config;\n discovery: PluginEndpointDiscovery;\n database: PluginDatabaseManager;\n urlReader: UrlReader;\n logger: LoggerService;\n catalogApi?: CatalogApi;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n}\n\nexport interface CodeCoverageApi {\n name: string;\n}\n\nexport const makeRouter = async (\n options: RouterOptions,\n): Promise<express.Router> => {\n const { config, logger, discovery, database, urlReader } = options;\n\n const codeCoverageDatabase = await CodeCoverageDatabase.create(database);\n const codecovUrl = await discovery.getExternalBaseUrl('code-coverage');\n const catalogApi =\n options.catalogApi ?? new CatalogClient({ discoveryApi: discovery });\n const scm = ScmIntegrations.fromConfig(config);\n const { auth, httpAuth } = createLegacyAuthAdapters(options);\n\n const bodySizeLimit =\n config.getOptionalString('codeCoverage.bodySizeLimit') ?? '100kb';\n\n bodyParserXml(BodyParser);\n const router = Router();\n router.use(\n BodyParser.xml({\n limit: bodySizeLimit,\n }),\n );\n router.use(\n BodyParser.text({\n limit: bodySizeLimit,\n }),\n );\n router.use(express.json());\n\n const utils = new CoverageUtils(scm, urlReader);\n\n router.get('/health', async (_req, res) => {\n res.status(200).json({ status: 'ok' });\n });\n\n /**\n * /report?entity=component:default/mycomponent\n */\n router.get('/report', async (req, res) => {\n const { entity } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n const stored = await codeCoverageDatabase.getCodeCoverage(entity as string);\n\n const aggregate = aggregateCoverage(stored);\n\n res.status(200).json({\n ...stored,\n aggregate: {\n line: aggregate.line,\n branch: aggregate.branch,\n },\n });\n });\n\n /**\n * /history?entity=component:default/mycomponent\n */\n router.get('/history', async (req, res) => {\n const { entity } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n const { limit } = req.query;\n const history = await codeCoverageDatabase.getHistory(\n entity as string,\n parseInt(limit?.toString() || '10', 10),\n );\n\n res.status(200).json(history);\n });\n\n /**\n * /file-content?entity=component:default/mycomponent&path=src/some-file.go\n */\n router.get('/file-content', async (req, res) => {\n const { entity, path } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n\n if (!path) {\n throw new InputError('Need path query parameter');\n }\n\n const sourceLocation = getEntitySourceLocation(entityLookup);\n\n if (!sourceLocation) {\n throw new InputError(\n `No \"backstage.io/source-location\" annotation on entity ${entity}`,\n );\n }\n\n const vcs = scm.byUrl(sourceLocation.target);\n if (!vcs) {\n throw new InputError(`Unable to determine SCM from ${sourceLocation}`);\n }\n\n const scmTree = await urlReader.readTree(sourceLocation.target);\n const scmFile = (await scmTree.files()).find(f => f.path === path);\n if (!scmFile) {\n res.status(404).json({\n message: \"Couldn't find file in SCM\",\n file: path,\n scm: vcs.title,\n });\n return;\n }\n const content = await scmFile?.content();\n if (!content) {\n res.status(400).json({\n message: \"Couldn't process content of file in SCM\",\n file: path,\n scm: vcs.title,\n });\n return;\n }\n\n const data = content.toString();\n res.status(200).contentType('text/plain').send(data);\n });\n\n /**\n * /report?entity=component:default/mycomponent&coverageType=cobertura\n */\n router.post('/report', async (req, res) => {\n const { entity: entityRef, coverageType } = req.query;\n const entity = await catalogApi.getEntityByRef(\n entityRef as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entity) {\n throw new NotFoundError(`No entity found matching ${entityRef}`);\n }\n\n let converter: Converter;\n if (!coverageType) {\n throw new InputError('Need coverageType query parameter');\n } else if (coverageType === 'jacoco') {\n converter = new Jacoco(logger);\n } else if (coverageType === 'cobertura') {\n converter = new Cobertura(logger);\n } else if (coverageType === 'lcov') {\n converter = new Lcov(logger);\n } else {\n throw new InputError(`Unsupported coverage type '${coverageType}`);\n }\n\n const { sourceLocation, vcs, scmFiles, body } =\n await utils.processCoveragePayload(entity, req);\n\n const files = converter.convert(body, scmFiles);\n if (!files || files.length === 0) {\n throw new InputError(`Unable to parse body as ${coverageType}`);\n }\n\n const coverage = await utils.buildCoverage(\n entity,\n sourceLocation,\n vcs,\n files,\n );\n await codeCoverageDatabase.insertCodeCoverage(coverage);\n\n res.status(201).json({\n links: [\n {\n rel: 'coverage',\n href: `${codecovUrl}/report?entity=${entityRef}`,\n },\n ],\n });\n });\n\n router.use(errorHandler());\n return router;\n};\n\n/**\n * Creates a code-coverage plugin backend router.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const logger = options.logger;\n\n logger.info('Initializing Code Coverage backend');\n\n return makeRouter(options);\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * Code coverage backend plugin\n *\n * @public\n */\nexport const codeCoveragePlugin = createBackendPlugin({\n pluginId: 'codeCoverage',\n register(env) {\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n urlReader: coreServices.urlReader,\n httpRouter: coreServices.httpRouter,\n discovery: coreServices.discovery,\n database: coreServices.database,\n },\n async init({\n config,\n logger,\n urlReader,\n httpRouter,\n discovery,\n database,\n }) {\n httpRouter.use(\n await createRouter({\n config,\n logger,\n urlReader,\n discovery,\n database,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["getEntitySourceLocation","InputError","stringifyEntityRef","NotFoundError","resolvePackagePath","uuid","parseEntityRef","CatalogClient","ScmIntegrations","createLegacyAuthAdapters","bodyParserXml","BodyParser","Router","express","errorHandler","createBackendPlugin","coreServices"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/service/CoverageUtils.ts","../src/service/CodeCoverageDatabase.ts","../src/service/converter/cobertura.ts","../src/service/converter/jacoco.ts","../src/service/converter/lcov.ts","../src/service/router.ts","../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Request } from 'express';\nimport { UrlReader } from '@backstage/backend-common';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport {\n Entity,\n getEntitySourceLocation,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { ScmIntegration, ScmIntegrations } from '@backstage/integration';\nimport { AggregateCoverage, FileEntry, JsonCodeCoverage } from './types';\n\nexport const calculatePercentage = (\n available: number,\n covered: number,\n): number => {\n if (available === 0) {\n return 0;\n }\n return parseFloat(((covered / available) * 100).toFixed(2));\n};\n\nexport const aggregateCoverage = (c: JsonCodeCoverage): AggregateCoverage => {\n let availableLine = 0;\n let coveredLine = 0;\n let availableBranch = 0;\n let coveredBranch = 0;\n c.files.forEach(f => {\n availableLine += Object.keys(f.lineHits).length;\n coveredLine += Object.values(f.lineHits).filter(l => l > 0).length;\n\n availableBranch += Object.keys(f.branchHits)\n .map(b => parseInt(b, 10))\n .map((b: number) => f.branchHits[b].available)\n .filter(Boolean)\n .reduce((acc, curr) => acc + curr, 0);\n coveredBranch += Object.keys(f.branchHits)\n .map(b => parseInt(b, 10))\n .map((b: number) => f.branchHits[b].covered)\n .filter(Boolean)\n .reduce((acc, curr) => acc + curr, 0);\n });\n\n return {\n timestamp: c.metadata.generationTime,\n branch: {\n available: availableBranch,\n covered: coveredBranch,\n missed: availableBranch - coveredBranch,\n percentage: calculatePercentage(availableBranch, coveredBranch),\n },\n line: {\n available: availableLine,\n covered: coveredLine,\n missed: availableLine - coveredLine,\n percentage: calculatePercentage(availableLine, coveredLine),\n },\n };\n};\n\nexport class CoverageUtils {\n constructor(\n readonly scm: Partial<ScmIntegrations>,\n readonly urlReader: Partial<UrlReader>,\n ) {}\n\n async processCoveragePayload(\n entity: Entity,\n req: Request,\n ): Promise<{\n sourceLocation?: string;\n vcs?: ScmIntegration;\n scmFiles: string[];\n body: {};\n }> {\n const enforceScmFiles =\n entity.metadata.annotations?.['backstage.io/code-coverage'] ===\n 'scm-only' || false;\n\n let sourceLocation: string | undefined = undefined;\n let vcs: ScmIntegration | undefined = undefined;\n let scmFiles: string[] = [];\n\n if (enforceScmFiles) {\n try {\n const sl = getEntitySourceLocation(entity);\n sourceLocation = sl.target;\n } catch (e: unknown) {\n // TODO: logging\n }\n\n if (!sourceLocation) {\n throw new InputError(\n `No \"backstage.io/source-location\" annotation on entity ${stringifyEntityRef(\n entity,\n )}`,\n );\n }\n\n vcs = this.scm.byUrl?.(sourceLocation);\n if (!vcs) {\n throw new InputError(`Unable to determine SCM from ${sourceLocation}`);\n }\n\n const scmTree = await this.urlReader.readTree?.(sourceLocation);\n if (!scmTree) {\n throw new NotFoundError(`Unable to read tree from ${sourceLocation}`);\n }\n scmFiles = (await scmTree.files()).map(f => f.path);\n }\n\n const body = this.validateRequestBody(req);\n if (Object.keys(body).length === 0) {\n throw new InputError('Unable to parse body');\n }\n\n return {\n sourceLocation,\n vcs,\n scmFiles,\n body,\n };\n }\n\n async buildCoverage(\n entity: Entity,\n sourceLocation: string | undefined,\n vcs: ScmIntegration | undefined,\n files: FileEntry[],\n ): Promise<JsonCodeCoverage> {\n return {\n metadata: {\n vcs: {\n type: vcs?.type || 'unknown',\n location: sourceLocation || 'unknown',\n },\n generationTime: Date.now(),\n },\n entity: {\n name: entity.metadata.name,\n namespace: entity.metadata.namespace || 'default',\n kind: entity.kind,\n },\n files,\n };\n }\n\n validateRequestBody(req: Request) {\n const contentType = req.headers['content-type'];\n if (!contentType) {\n throw new InputError('Content-Type header missing');\n // text/xml or text/plain is allowed\n } else if (!contentType.match(/^text\\/xml|plain($|;)/)) {\n throw new InputError(\n `Content-Type header \"${contentType}\" not supported, expected \"text/xml\" or \"text/plain\" possibly followed by a charset`,\n );\n }\n const body = req.body;\n if (!body) {\n throw new InputError('Missing request body');\n }\n return body;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n PluginDatabaseManager,\n resolvePackagePath,\n} from '@backstage/backend-common';\nimport { NotFoundError } from '@backstage/errors';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { Knex } from 'knex';\nimport { v4 as uuid } from 'uuid';\nimport { aggregateCoverage } from './CoverageUtils';\nimport { JsonCodeCoverage, JsonCoverageHistory } from './types';\n\nexport type RawDbCoverageRow = {\n id: string;\n entity: string;\n coverage: string;\n};\n\nexport interface CodeCoverageStore {\n insertCodeCoverage(\n coverage: JsonCodeCoverage,\n ): Promise<{ codeCoverageId: string }>;\n getCodeCoverage(entity: string): Promise<JsonCodeCoverage>;\n getHistory(entity: string, limit: number): Promise<JsonCoverageHistory>;\n}\n\nconst migrationsDir = resolvePackagePath(\n '@backstage-community/plugin-code-coverage-backend',\n 'migrations',\n);\n\nexport class CodeCoverageDatabase implements CodeCoverageStore {\n static async create(\n database: PluginDatabaseManager,\n ): Promise<CodeCoverageStore> {\n const knex = await database.getClient();\n\n if (!database.migrations?.skip) {\n await knex.migrate.latest({\n directory: migrationsDir,\n });\n }\n\n return new CodeCoverageDatabase(knex);\n }\n\n constructor(private readonly db: Knex) {}\n\n async insertCodeCoverage(\n coverage: JsonCodeCoverage,\n ): Promise<{ codeCoverageId: string }> {\n const codeCoverageId = uuid();\n const entity = stringifyEntityRef({\n kind: coverage.entity.kind,\n namespace: coverage.entity.namespace,\n name: coverage.entity.name,\n });\n\n await this.db<RawDbCoverageRow>('code_coverage').insert({\n id: codeCoverageId,\n entity: entity,\n coverage: JSON.stringify(coverage),\n });\n\n return { codeCoverageId };\n }\n\n async getCodeCoverage(entity: string): Promise<JsonCodeCoverage> {\n const [result] = await this.db<RawDbCoverageRow>('code_coverage')\n .where({ entity: entity })\n .orderBy('index', 'desc')\n .limit(1)\n .select();\n\n if (!result) {\n throw new NotFoundError(\n `No coverage for entity '${JSON.stringify(entity)}' found`,\n );\n }\n\n try {\n return JSON.parse(result.coverage);\n } catch (error) {\n throw new Error(`Failed to parse coverage for '${entity}', ${error}`);\n }\n }\n\n async getHistory(\n entity: string,\n limit: number,\n ): Promise<JsonCoverageHistory> {\n const res = await this.db<RawDbCoverageRow>('code_coverage')\n .where({ entity: entity })\n .orderBy('index', 'desc')\n .limit(limit)\n .select();\n\n const history = res\n .map(r => JSON.parse(r.coverage))\n .map(c => aggregateCoverage(c));\n\n const entityName = parseEntityRef(entity);\n\n return {\n entity: {\n name: entityName.name,\n kind: entityName.kind,\n namespace: entityName.namespace,\n },\n history: history,\n };\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { BranchHit, FileEntry } from '../types';\nimport { CoberturaXML, InnerClass, LineHit } from './types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport class Cobertura implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * convert cobertura into shared json coverage format\n *\n * @param xml - cobertura xml object\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(xml: CoberturaXML, scmFiles: string[]): FileEntry[] {\n const ppc = xml.coverage.packages\n ?.flatMap(p => p.package)\n .filter(Boolean)\n .flatMap(p => p.classes);\n const pc = xml.coverage.package?.filter(Boolean).flatMap(p => p.classes);\n\n const classes = [ppc, pc]\n .flat()\n .filter(Boolean)\n .flatMap(c => c.class)\n .filter(Boolean);\n const jscov: Array<FileEntry> = [];\n\n classes.forEach(c => {\n const packageAndFilename = c.$.filename;\n const lines = this.extractLines(c);\n const lineHits: Record<number, number> = {};\n const branchHits: Record<number, BranchHit> = {};\n\n lines.forEach(l => {\n if (!lineHits[l.number]) {\n lineHits[l.number] = 0;\n }\n lineHits[l.number] += l.hits;\n if (l.branch && l['condition-coverage']) {\n const bh = this.parseBranch(l['condition-coverage']);\n if (bh) {\n branchHits[l.number] = bh;\n }\n }\n });\n\n const currentFile = scmFiles\n .map(f => f.trimEnd())\n .find(f => f.endsWith(packageAndFilename));\n this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`);\n if (\n scmFiles.length === 0 ||\n (Object.keys(lineHits).length > 0 && currentFile)\n ) {\n jscov.push({\n filename: currentFile || packageAndFilename,\n branchHits: branchHits,\n lineHits: lineHits,\n });\n }\n });\n\n return jscov;\n }\n\n /**\n * Parses branch coverage information from condition-coverage\n *\n * @param condition - condition-coverage value from line coverage\n */\n private parseBranch(condition: string): BranchHit | null {\n const pattern = /[0-9\\.]+\\%\\s\\(([0-9]+)\\/([0-9]+)\\)/;\n const match = condition.match(pattern);\n if (!match) {\n return null;\n }\n const covered = parseInt(match[1], 10);\n const available = parseInt(match[2], 10);\n return {\n covered: covered,\n missed: available - covered,\n available: available,\n };\n }\n\n /**\n * Extract line hits from a class coverage entry\n *\n * @param clz - class coverage information\n */\n private extractLines(clz: InnerClass): Array<LineHit> {\n const classLines = clz.lines.flatMap(l => l.line);\n const methodLines = clz.methods\n ?.flatMap(m => m.method)\n .filter(Boolean)\n .flatMap(m => m.lines)\n .filter(Boolean)\n .flatMap(l => l.line)\n .filter(\n ({ $: methodLine }) =>\n classLines.some(\n ({ $: classLine }) => methodLine.number === classLine.number,\n ) === false,\n );\n const lines = [classLines, methodLines].flat().filter(Boolean);\n const lineHits = lines.map(l => {\n return {\n number: parseInt(l.$.number as unknown as string, 10),\n hits: parseInt(l.$.hits as unknown as string, 10),\n 'condition-coverage': l.$['condition-coverage'],\n branch: l.$.branch,\n };\n });\n return lineHits;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BranchHit, FileEntry } from '../types';\nimport { JacocoSourceFile, JacocoXML } from './types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\ntype ParsedLine = {\n number: number;\n missed_instructions: number;\n covered_instructions: number;\n missed_branches: number;\n covered_branches: number;\n};\n\nexport class Jacoco implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * Converts jacoco into shared json coverage format\n *\n * @param xml - jacoco xml object\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(xml: JacocoXML, scmFiles: Array<string>): Array<FileEntry> {\n const jscov: Array<FileEntry> = [];\n xml.report.package.forEach(r => {\n const packageName = r.$.name;\n r.sourcefile.forEach(sf => {\n const fileName = sf.$.name;\n const lines = this.extractLines(sf);\n const lineHits: Record<number, number> = {};\n const branchHits: Record<number, BranchHit> = {};\n lines.forEach(l => {\n if (!lineHits[l.number]) {\n lineHits[l.number] = 0;\n }\n lineHits[l.number] += l.covered_instructions;\n const ab = l.covered_branches + l.missed_branches;\n if (ab > 0) {\n branchHits[l.number] = {\n covered: l.covered_branches,\n missed: l.missed_branches,\n available: ab,\n };\n }\n });\n\n const packageAndFilename = `${packageName}/${fileName}`;\n const currentFile = scmFiles\n .map(f => f.trimEnd())\n .find(f => f.endsWith(packageAndFilename));\n this.logger.debug(`matched ${packageAndFilename} to ${currentFile}`);\n if (\n scmFiles.length === 0 ||\n (Object.keys(lineHits).length > 0 && currentFile)\n ) {\n jscov.push({\n filename: currentFile || packageAndFilename,\n branchHits: branchHits,\n lineHits: lineHits,\n });\n }\n });\n });\n\n return jscov;\n }\n\n private extractLines(sourcefile: JacocoSourceFile): ParsedLine[] {\n const parsed: ParsedLine[] = [];\n\n sourcefile.line?.forEach(l => {\n parsed.push({\n number: parseInt(l.$.nr, 10),\n missed_instructions: parseInt(l.$.mi, 10),\n covered_instructions: parseInt(l.$.ci, 10),\n missed_branches: parseInt(l.$.mb, 10),\n covered_branches: parseInt(l.$.cb, 10),\n });\n });\n\n return parsed;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { FileEntry } from '../types';\nimport { Converter } from './Converter';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport class Lcov implements Converter {\n constructor(readonly logger: LoggerService) {\n this.logger = logger;\n }\n\n /**\n * convert lcov into shared json coverage format\n *\n * @param raw - raw lcov report\n * @param scmFiles - list of files that are committed to SCM\n */\n convert(raw: string, scmFiles: string[]): FileEntry[] {\n const lines = raw.split(/\\r?\\n/);\n const jscov: Array<FileEntry> = [];\n let currentFile: FileEntry | null = null;\n\n lines.forEach(line => {\n const [section, value] = line.split(':');\n\n switch (section) {\n // If the line starts with SF, it's a new file\n case 'SF':\n currentFile = this.processNewFile(value, scmFiles);\n break;\n // If the line starts with DA, it's a line hit\n case 'DA':\n this.processLineHit(currentFile, value);\n break;\n // If the line starts with BRDA, it's a branch line\n case 'BRDA':\n this.processBranchHit(currentFile, value);\n break;\n // If the line starts with end_of_record, it's the end of current file\n case 'end_of_record':\n if (currentFile) {\n jscov.push(currentFile);\n currentFile = null;\n }\n break;\n default:\n break;\n }\n });\n\n return jscov;\n }\n\n /**\n * Parses a new file entry\n *\n * @param file - file name from coverage report\n * @param scmFiles - list of files that are committed to SCM\n */\n private processNewFile(file: string, scmFiles: string[]): FileEntry | null {\n const filename = scmFiles.map(f => f.trimEnd()).find(f => file.endsWith(f));\n\n this.logger.debug(`matched ${file} to ${filename}`);\n\n if (scmFiles.length === 0 || filename) {\n return {\n filename: filename || file,\n lineHits: {},\n branchHits: {},\n };\n }\n\n return null;\n }\n\n /**\n * Parses line coverage information\n *\n * @param currentFile - current file entry\n * @param value - line coverage information\n */\n private processLineHit(currentFile: FileEntry | null, value: string): void {\n if (!currentFile) return;\n\n const [lineNumber, hits] = value.split(',');\n currentFile.lineHits[Number(lineNumber)] = Number(hits);\n }\n\n /**\n * Parses branch coverage information\n *\n * @param currentFile - current file entry\n * @param value - branch coverage information\n */\n private processBranchHit(currentFile: FileEntry | null, value: string): void {\n if (!currentFile) return;\n\n const [lineNumber, , , hits] = value.split(',');\n const lineNumberNum = Number(lineNumber);\n const isHit = Number(hits) > 0;\n const branch = currentFile.branchHits[lineNumberNum] || {\n covered: 0,\n available: 0,\n missed: 0,\n };\n\n branch.available++;\n branch.covered += isHit ? 1 : 0;\n branch.missed += isHit ? 0 : 1;\n\n currentFile.branchHits[lineNumberNum] = branch;\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport BodyParser from 'body-parser';\nimport bodyParserXml from 'body-parser-xml';\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport {\n createLegacyAuthAdapters,\n errorHandler,\n PluginDatabaseManager,\n PluginEndpointDiscovery,\n UrlReader,\n} from '@backstage/backend-common';\nimport { InputError, NotFoundError } from '@backstage/errors';\nimport { Config } from '@backstage/config';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { CodeCoverageDatabase } from './CodeCoverageDatabase';\nimport { aggregateCoverage, CoverageUtils } from './CoverageUtils';\nimport { Cobertura, Converter, Jacoco, Lcov } from './converter';\nimport { getEntitySourceLocation } from '@backstage/catalog-model';\nimport {\n AuthService,\n HttpAuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n config: Config;\n discovery: PluginEndpointDiscovery;\n database: PluginDatabaseManager;\n urlReader: UrlReader;\n logger: LoggerService;\n catalogApi?: CatalogApi;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n}\n\nexport interface CodeCoverageApi {\n name: string;\n}\n\nexport const makeRouter = async (\n options: RouterOptions,\n): Promise<express.Router> => {\n const { config, logger, discovery, database, urlReader } = options;\n\n const codeCoverageDatabase = await CodeCoverageDatabase.create(database);\n const codecovUrl = await discovery.getExternalBaseUrl('code-coverage');\n const catalogApi =\n options.catalogApi ?? new CatalogClient({ discoveryApi: discovery });\n const scm = ScmIntegrations.fromConfig(config);\n const { auth, httpAuth } = createLegacyAuthAdapters(options);\n\n const bodySizeLimit =\n config.getOptionalString('codeCoverage.bodySizeLimit') ?? '100kb';\n\n bodyParserXml(BodyParser);\n const router = Router();\n router.use(\n BodyParser.xml({\n limit: bodySizeLimit,\n }),\n );\n router.use(\n BodyParser.text({\n limit: bodySizeLimit,\n }),\n );\n router.use(express.json());\n\n const utils = new CoverageUtils(scm, urlReader);\n\n router.get('/health', async (_req, res) => {\n res.status(200).json({ status: 'ok' });\n });\n\n /**\n * /report?entity=component:default/mycomponent\n */\n router.get('/report', async (req, res) => {\n const { entity } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n const stored = await codeCoverageDatabase.getCodeCoverage(entity as string);\n\n const aggregate = aggregateCoverage(stored);\n\n res.status(200).json({\n ...stored,\n aggregate: {\n line: aggregate.line,\n branch: aggregate.branch,\n },\n });\n });\n\n /**\n * /history?entity=component:default/mycomponent\n */\n router.get('/history', async (req, res) => {\n const { entity } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n const { limit } = req.query;\n const history = await codeCoverageDatabase.getHistory(\n entity as string,\n parseInt(limit?.toString() || '10', 10),\n );\n\n res.status(200).json(history);\n });\n\n /**\n * /file-content?entity=component:default/mycomponent&path=src/some-file.go\n */\n router.get('/file-content', async (req, res) => {\n const { entity, path } = req.query;\n const entityLookup = await catalogApi.getEntityByRef(\n entity as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entityLookup) {\n throw new NotFoundError(`No entity found matching ${entity}`);\n }\n\n if (!path) {\n throw new InputError('Need path query parameter');\n }\n\n const sourceLocation = getEntitySourceLocation(entityLookup);\n\n if (!sourceLocation) {\n throw new InputError(\n `No \"backstage.io/source-location\" annotation on entity ${entity}`,\n );\n }\n\n const vcs = scm.byUrl(sourceLocation.target);\n if (!vcs) {\n throw new InputError(`Unable to determine SCM from ${sourceLocation}`);\n }\n\n const scmTree = await urlReader.readTree(sourceLocation.target);\n const scmFile = (await scmTree.files()).find(f => f.path === path);\n if (!scmFile) {\n res.status(404).json({\n message: \"Couldn't find file in SCM\",\n file: path,\n scm: vcs.title,\n });\n return;\n }\n const content = await scmFile?.content();\n if (!content) {\n res.status(400).json({\n message: \"Couldn't process content of file in SCM\",\n file: path,\n scm: vcs.title,\n });\n return;\n }\n\n const data = content.toString();\n res.status(200).contentType('text/plain').send(data);\n });\n\n /**\n * /report?entity=component:default/mycomponent&coverageType=cobertura\n */\n router.post('/report', async (req, res) => {\n const { entity: entityRef, coverageType } = req.query;\n const entity = await catalogApi.getEntityByRef(\n entityRef as string,\n await auth.getPluginRequestToken({\n onBehalfOf: await httpAuth.credentials(req),\n targetPluginId: 'catalog',\n }),\n );\n if (!entity) {\n throw new NotFoundError(`No entity found matching ${entityRef}`);\n }\n\n let converter: Converter;\n if (!coverageType) {\n throw new InputError('Need coverageType query parameter');\n } else if (coverageType === 'jacoco') {\n converter = new Jacoco(logger);\n } else if (coverageType === 'cobertura') {\n converter = new Cobertura(logger);\n } else if (coverageType === 'lcov') {\n converter = new Lcov(logger);\n } else {\n throw new InputError(`Unsupported coverage type '${coverageType}`);\n }\n\n const { sourceLocation, vcs, scmFiles, body } =\n await utils.processCoveragePayload(entity, req);\n\n const files = converter.convert(body, scmFiles);\n if (!files || files.length === 0) {\n throw new InputError(`Unable to parse body as ${coverageType}`);\n }\n\n const coverage = await utils.buildCoverage(\n entity,\n sourceLocation,\n vcs,\n files,\n );\n await codeCoverageDatabase.insertCodeCoverage(coverage);\n\n res.status(201).json({\n links: [\n {\n rel: 'coverage',\n href: `${codecovUrl}/report?entity=${entityRef}`,\n },\n ],\n });\n });\n\n router.use(errorHandler());\n return router;\n};\n\n/**\n * Creates a code-coverage plugin backend router.\n *\n * @public\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const logger = options.logger;\n\n logger.info('Initializing Code Coverage backend');\n\n return makeRouter(options);\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * Code coverage backend plugin\n *\n * @public\n */\nexport const codeCoveragePlugin = createBackendPlugin({\n pluginId: 'codeCoverage',\n register(env) {\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n urlReader: coreServices.urlReader,\n httpRouter: coreServices.httpRouter,\n discovery: coreServices.discovery,\n database: coreServices.database,\n },\n async init({\n config,\n logger,\n urlReader,\n httpRouter,\n discovery,\n database,\n }) {\n httpRouter.use(\n await createRouter({\n config,\n logger,\n urlReader,\n discovery,\n database,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n },\n });\n },\n});\n"],"names":["getEntitySourceLocation","InputError","stringifyEntityRef","NotFoundError","resolvePackagePath","uuid","parseEntityRef","CatalogClient","ScmIntegrations","createLegacyAuthAdapters","bodyParserXml","BodyParser","Router","express","errorHandler","createBackendPlugin","coreServices"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,6 @@ declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
|
32
32
|
*
|
|
33
33
|
* @public
|
|
34
34
|
*/
|
|
35
|
-
declare const codeCoveragePlugin:
|
|
35
|
+
declare const codeCoveragePlugin: _backstage_backend_plugin_api.BackendFeatureCompat;
|
|
36
36
|
|
|
37
37
|
export { type RouterOptions, createRouter, codeCoveragePlugin as default };
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-code-coverage-backend",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.34",
|
|
4
4
|
"description": "A Backstage backend plugin that helps you keep track of your code coverage",
|
|
5
5
|
"backstage": {
|
|
6
|
-
"role": "backend-plugin"
|
|
6
|
+
"role": "backend-plugin",
|
|
7
|
+
"pluginId": "code-coverage",
|
|
8
|
+
"pluginPackages": [
|
|
9
|
+
"@backstage-community/plugin-code-coverage",
|
|
10
|
+
"@backstage-community/plugin-code-coverage-backend"
|
|
11
|
+
]
|
|
7
12
|
},
|
|
8
13
|
"publishConfig": {
|
|
9
14
|
"access": "public",
|
|
@@ -33,13 +38,13 @@
|
|
|
33
38
|
"test": "backstage-cli package test"
|
|
34
39
|
},
|
|
35
40
|
"dependencies": {
|
|
36
|
-
"@backstage/backend-common": "^0.
|
|
37
|
-
"@backstage/backend-plugin-api": "^0.
|
|
38
|
-
"@backstage/catalog-client": "^1.6.
|
|
39
|
-
"@backstage/catalog-model": "^1.
|
|
41
|
+
"@backstage/backend-common": "^0.23.3",
|
|
42
|
+
"@backstage/backend-plugin-api": "^0.7.0",
|
|
43
|
+
"@backstage/catalog-client": "^1.6.5",
|
|
44
|
+
"@backstage/catalog-model": "^1.5.0",
|
|
40
45
|
"@backstage/config": "^1.2.0",
|
|
41
46
|
"@backstage/errors": "^1.2.4",
|
|
42
|
-
"@backstage/integration": "^1.
|
|
47
|
+
"@backstage/integration": "^1.13.0",
|
|
43
48
|
"@types/express": "^4.17.6",
|
|
44
49
|
"body-parser": "^1.20.0",
|
|
45
50
|
"body-parser-xml": "^2.0.5",
|
|
@@ -50,12 +55,12 @@
|
|
|
50
55
|
"yn": "^4.0.0"
|
|
51
56
|
},
|
|
52
57
|
"devDependencies": {
|
|
53
|
-
"@backstage/backend-test-utils": "^0.
|
|
54
|
-
"@backstage/cli": "^0.26.
|
|
58
|
+
"@backstage/backend-test-utils": "^0.4.4",
|
|
59
|
+
"@backstage/cli": "^0.26.11",
|
|
55
60
|
"@types/body-parser-xml": "^2.0.2",
|
|
56
|
-
"@types/supertest": "^
|
|
61
|
+
"@types/supertest": "^6.0.0",
|
|
57
62
|
"@types/uuid": "^9.0.0",
|
|
58
|
-
"supertest": "^
|
|
63
|
+
"supertest": "^7.0.0",
|
|
59
64
|
"xml2js": "^0.6.0"
|
|
60
65
|
}
|
|
61
66
|
}
|