@backstage-community/plugin-code-coverage-backend 0.3.2 → 0.3.3

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @backstage-community/plugin-code-coverage-backend
2
2
 
3
+ ## 0.3.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 37bd870: Deprecated `createRouter` and its router options in favour of the new backend system.
8
+
3
9
  ## 0.3.2
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
5
5
  import { DiscoveryService, DatabaseService, UrlReaderService, LoggerService, AuthService, HttpAuthService } from '@backstage/backend-plugin-api';
6
6
 
7
7
  /**
8
+ * @deprecated Please migrate to the new backend system as this will be removed in the future.
9
+ *
8
10
  * Options for {@link createRouter}.
9
11
  *
10
12
  * @public
@@ -20,6 +22,8 @@ interface RouterOptions {
20
22
  httpAuth?: HttpAuthService;
21
23
  }
22
24
  /**
25
+ * @deprecated Please migrate to the new backend system as this will be removed in the future.
26
+ *
23
27
  * Creates a code-coverage plugin backend router.
24
28
  *
25
29
  * @public
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.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 */\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 { createLegacyAuthAdapters } 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 DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\n\n/**\n * Options for {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n config: Config;\n discovery: DiscoveryService;\n database: DatabaseService;\n urlReader: UrlReaderService;\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 const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\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"],"names":["CodeCoverageDatabase","CatalogClient","ScmIntegrations","createLegacyAuthAdapters","bodyParserXml","BodyParser","Router","express","CoverageUtils","NotFoundError","aggregateCoverage","InputError","getEntitySourceLocation","Jacoco","Cobertura","Lcov","MiddlewareFactory"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA2Da,MAAA,UAAA,GAAa,OACxB,OAC4B,KAAA;AAC5B,EAAA,MAAM,EAAE,MAAQ,EAAA,MAAA,EAAQ,SAAW,EAAA,QAAA,EAAU,WAAc,GAAA,OAAA,CAAA;AAE3D,EAAA,MAAM,oBAAuB,GAAA,MAAMA,yCAAqB,CAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AACvE,EAAA,MAAM,UAAa,GAAA,MAAM,SAAU,CAAA,kBAAA,CAAmB,eAAe,CAAA,CAAA;AACrE,EAAM,MAAA,UAAA,GACJ,QAAQ,UAAc,IAAA,IAAIC,4BAAc,EAAE,YAAA,EAAc,WAAW,CAAA,CAAA;AACrE,EAAM,MAAA,GAAA,GAAMC,2BAAgB,CAAA,UAAA,CAAW,MAAM,CAAA,CAAA;AAC7C,EAAA,MAAM,EAAE,IAAA,EAAM,QAAS,EAAA,GAAIC,uCAAyB,OAAO,CAAA,CAAA;AAE3D,EAAA,MAAM,aACJ,GAAA,MAAA,CAAO,iBAAkB,CAAA,4BAA4B,CAAK,IAAA,OAAA,CAAA;AAE5D,EAAAC,8BAAA,CAAcC,2BAAU,CAAA,CAAA;AACxB,EAAA,MAAM,SAASC,uBAAO,EAAA,CAAA;AACtB,EAAO,MAAA,CAAA,GAAA;AAAA,IACLD,4BAAW,GAAI,CAAA;AAAA,MACb,KAAO,EAAA,aAAA;AAAA,KACR,CAAA;AAAA,GACH,CAAA;AACA,EAAO,MAAA,CAAA,GAAA;AAAA,IACLA,4BAAW,IAAK,CAAA;AAAA,MACd,KAAO,EAAA,aAAA;AAAA,KACR,CAAA;AAAA,GACH,CAAA;AACA,EAAO,MAAA,CAAA,GAAA,CAAIE,wBAAQ,CAAA,IAAA,EAAM,CAAA,CAAA;AAEzB,EAAA,MAAM,KAAQ,GAAA,IAAIC,2BAAc,CAAA,GAAA,EAAK,SAAS,CAAA,CAAA;AAE9C,EAAA,MAAA,CAAO,GAAI,CAAA,SAAA,EAAW,OAAO,IAAA,EAAM,GAAQ,KAAA;AACzC,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,MAAA,EAAQ,MAAM,CAAA,CAAA;AAAA,GACtC,CAAA,CAAA;AAKD,EAAA,MAAA,CAAO,GAAI,CAAA,SAAA,EAAW,OAAO,GAAA,EAAK,GAAQ,KAAA;AACxC,IAAM,MAAA,EAAE,MAAO,EAAA,GAAI,GAAI,CAAA,KAAA,CAAA;AACvB,IAAM,MAAA,YAAA,GAAe,MAAM,UAAW,CAAA,cAAA;AAAA,MACpC,MAAA;AAAA,MACA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QAC/B,UAAY,EAAA,MAAM,QAAS,CAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QAC1C,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA;AAAA,KACH,CAAA;AACA,IAAA,IAAI,CAAC,YAAc,EAAA;AACjB,MAAA,MAAM,IAAIC,oBAAA,CAAc,CAA4B,yBAAA,EAAA,MAAM,CAAE,CAAA,CAAA,CAAA;AAAA,KAC9D;AACA,IAAA,MAAM,MAAS,GAAA,MAAM,oBAAqB,CAAA,eAAA,CAAgB,MAAgB,CAAA,CAAA;AAE1E,IAAM,MAAA,SAAA,GAAYC,gCAAkB,MAAM,CAAA,CAAA;AAE1C,IAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,MACnB,GAAG,MAAA;AAAA,MACH,SAAW,EAAA;AAAA,QACT,MAAM,SAAU,CAAA,IAAA;AAAA,QAChB,QAAQ,SAAU,CAAA,MAAA;AAAA,OACpB;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AAKD,EAAA,MAAA,CAAO,GAAI,CAAA,UAAA,EAAY,OAAO,GAAA,EAAK,GAAQ,KAAA;AACzC,IAAM,MAAA,EAAE,MAAO,EAAA,GAAI,GAAI,CAAA,KAAA,CAAA;AACvB,IAAM,MAAA,YAAA,GAAe,MAAM,UAAW,CAAA,cAAA;AAAA,MACpC,MAAA;AAAA,MACA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QAC/B,UAAY,EAAA,MAAM,QAAS,CAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QAC1C,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA;AAAA,KACH,CAAA;AACA,IAAA,IAAI,CAAC,YAAc,EAAA;AACjB,MAAA,MAAM,IAAID,oBAAA,CAAc,CAA4B,yBAAA,EAAA,MAAM,CAAE,CAAA,CAAA,CAAA;AAAA,KAC9D;AACA,IAAM,MAAA,EAAE,KAAM,EAAA,GAAI,GAAI,CAAA,KAAA,CAAA;AACtB,IAAM,MAAA,OAAA,GAAU,MAAM,oBAAqB,CAAA,UAAA;AAAA,MACzC,MAAA;AAAA,MACA,QAAS,CAAA,KAAA,EAAO,QAAS,EAAA,IAAK,MAAM,EAAE,CAAA;AAAA,KACxC,CAAA;AAEA,IAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,OAAO,CAAA,CAAA;AAAA,GAC7B,CAAA,CAAA;AAKD,EAAA,MAAA,CAAO,GAAI,CAAA,eAAA,EAAiB,OAAO,GAAA,EAAK,GAAQ,KAAA;AAC9C,IAAA,MAAM,EAAE,MAAA,EAAQ,IAAK,EAAA,GAAI,GAAI,CAAA,KAAA,CAAA;AAC7B,IAAM,MAAA,YAAA,GAAe,MAAM,UAAW,CAAA,cAAA;AAAA,MACpC,MAAA;AAAA,MACA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QAC/B,UAAY,EAAA,MAAM,QAAS,CAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QAC1C,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA;AAAA,KACH,CAAA;AACA,IAAA,IAAI,CAAC,YAAc,EAAA;AACjB,MAAA,MAAM,IAAIA,oBAAA,CAAc,CAA4B,yBAAA,EAAA,MAAM,CAAE,CAAA,CAAA,CAAA;AAAA,KAC9D;AAEA,IAAA,IAAI,CAAC,IAAM,EAAA;AACT,MAAM,MAAA,IAAIE,kBAAW,2BAA2B,CAAA,CAAA;AAAA,KAClD;AAEA,IAAM,MAAA,cAAA,GAAiBC,qCAAwB,YAAY,CAAA,CAAA;AAE3D,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAA,MAAM,IAAID,iBAAA;AAAA,QACR,0DAA0D,MAAM,CAAA,CAAA;AAAA,OAClE,CAAA;AAAA,KACF;AAEA,IAAA,MAAM,GAAM,GAAA,GAAA,CAAI,KAAM,CAAA,cAAA,CAAe,MAAM,CAAA,CAAA;AAC3C,IAAA,IAAI,CAAC,GAAK,EAAA;AACR,MAAA,MAAM,IAAIA,iBAAA,CAAW,CAAgC,6BAAA,EAAA,cAAc,CAAE,CAAA,CAAA,CAAA;AAAA,KACvE;AAEA,IAAA,MAAM,OAAU,GAAA,MAAM,SAAU,CAAA,QAAA,CAAS,eAAe,MAAM,CAAA,CAAA;AAC9D,IAAM,MAAA,OAAA,GAAA,CAAW,MAAM,OAAQ,CAAA,KAAA,IAAS,IAAK,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAA,KAAS,IAAI,CAAA,CAAA;AACjE,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,QACnB,OAAS,EAAA,2BAAA;AAAA,QACT,IAAM,EAAA,IAAA;AAAA,QACN,KAAK,GAAI,CAAA,KAAA;AAAA,OACV,CAAA,CAAA;AACD,MAAA,OAAA;AAAA,KACF;AACA,IAAM,MAAA,OAAA,GAAU,MAAM,OAAA,EAAS,OAAQ,EAAA,CAAA;AACvC,IAAA,IAAI,CAAC,OAAS,EAAA;AACZ,MAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,QACnB,OAAS,EAAA,yCAAA;AAAA,QACT,IAAM,EAAA,IAAA;AAAA,QACN,KAAK,GAAI,CAAA,KAAA;AAAA,OACV,CAAA,CAAA;AACD,MAAA,OAAA;AAAA,KACF;AAEA,IAAM,MAAA,IAAA,GAAO,QAAQ,QAAS,EAAA,CAAA;AAC9B,IAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,YAAY,YAAY,CAAA,CAAE,KAAK,IAAI,CAAA,CAAA;AAAA,GACpD,CAAA,CAAA;AAKD,EAAA,MAAA,CAAO,IAAK,CAAA,SAAA,EAAW,OAAO,GAAA,EAAK,GAAQ,KAAA;AACzC,IAAA,MAAM,EAAE,MAAA,EAAQ,SAAW,EAAA,YAAA,KAAiB,GAAI,CAAA,KAAA,CAAA;AAChD,IAAM,MAAA,MAAA,GAAS,MAAM,UAAW,CAAA,cAAA;AAAA,MAC9B,SAAA;AAAA,MACA,MAAM,KAAK,qBAAsB,CAAA;AAAA,QAC/B,UAAY,EAAA,MAAM,QAAS,CAAA,WAAA,CAAY,GAAG,CAAA;AAAA,QAC1C,cAAgB,EAAA,SAAA;AAAA,OACjB,CAAA;AAAA,KACH,CAAA;AACA,IAAA,IAAI,CAAC,MAAQ,EAAA;AACX,MAAA,MAAM,IAAIF,oBAAA,CAAc,CAA4B,yBAAA,EAAA,SAAS,CAAE,CAAA,CAAA,CAAA;AAAA,KACjE;AAEA,IAAI,IAAA,SAAA,CAAA;AACJ,IAAA,IAAI,CAAC,YAAc,EAAA;AACjB,MAAM,MAAA,IAAIE,kBAAW,mCAAmC,CAAA,CAAA;AAAA,KAC1D,MAAA,IAAW,iBAAiB,QAAU,EAAA;AACpC,MAAY,SAAA,GAAA,IAAIE,cAAO,MAAM,CAAA,CAAA;AAAA,KAC/B,MAAA,IAAW,iBAAiB,WAAa,EAAA;AACvC,MAAY,SAAA,GAAA,IAAIC,oBAAU,MAAM,CAAA,CAAA;AAAA,KAClC,MAAA,IAAW,iBAAiB,MAAQ,EAAA;AAClC,MAAY,SAAA,GAAA,IAAIC,UAAK,MAAM,CAAA,CAAA;AAAA,KACtB,MAAA;AACL,MAAA,MAAM,IAAIJ,iBAAA,CAAW,CAA8B,2BAAA,EAAA,YAAY,CAAE,CAAA,CAAA,CAAA;AAAA,KACnE;AAEA,IAAM,MAAA,EAAE,cAAgB,EAAA,GAAA,EAAK,QAAU,EAAA,IAAA,KACrC,MAAM,KAAA,CAAM,sBAAuB,CAAA,MAAA,EAAQ,GAAG,CAAA,CAAA;AAEhD,IAAA,MAAM,KAAQ,GAAA,SAAA,CAAU,OAAQ,CAAA,IAAA,EAAM,QAAQ,CAAA,CAAA;AAC9C,IAAA,IAAI,CAAC,KAAA,IAAS,KAAM,CAAA,MAAA,KAAW,CAAG,EAAA;AAChC,MAAA,MAAM,IAAIA,iBAAA,CAAW,CAA2B,wBAAA,EAAA,YAAY,CAAE,CAAA,CAAA,CAAA;AAAA,KAChE;AAEA,IAAM,MAAA,QAAA,GAAW,MAAM,KAAM,CAAA,aAAA;AAAA,MAC3B,MAAA;AAAA,MACA,cAAA;AAAA,MACA,GAAA;AAAA,MACA,KAAA;AAAA,KACF,CAAA;AACA,IAAM,MAAA,oBAAA,CAAqB,mBAAmB,QAAQ,CAAA,CAAA;AAEtD,IAAI,GAAA,CAAA,MAAA,CAAO,GAAG,CAAA,CAAE,IAAK,CAAA;AAAA,MACnB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,GAAK,EAAA,UAAA;AAAA,UACL,IAAM,EAAA,CAAA,EAAG,UAAU,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA;AAAA,SAChD;AAAA,OACF;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AAED,EAAA,MAAM,aAAaK,gCAAkB,CAAA,MAAA,CAAO,EAAE,MAAA,EAAQ,QAAQ,CAAA,CAAA;AAE9D,EAAO,MAAA,CAAA,GAAA,CAAI,UAAW,CAAA,KAAA,EAAO,CAAA,CAAA;AAC7B,EAAO,OAAA,MAAA,CAAA;AACT,EAAA;AAOA,eAAsB,aACpB,OACyB,EAAA;AACzB,EAAA,MAAM,SAAS,OAAQ,CAAA,MAAA,CAAA;AAEvB,EAAA,MAAA,CAAO,KAAK,oCAAoC,CAAA,CAAA;AAEhD,EAAA,OAAO,WAAW,OAAO,CAAA,CAAA;AAC3B;;;;;"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.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 */\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 { createLegacyAuthAdapters } 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 DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\n\n/**\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n *\n * Options for {@link createRouter}.\n *\n * @public\n */\nexport interface RouterOptions {\n config: Config;\n discovery: DiscoveryService;\n database: DatabaseService;\n urlReader: UrlReaderService;\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 const middleware = MiddlewareFactory.create({ logger, config });\n\n router.use(middleware.error());\n return router;\n};\n\n/**\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\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"],"names":["CodeCoverageDatabase","CatalogClient","ScmIntegrations","createLegacyAuthAdapters","bodyParserXml","BodyParser","Router","express","CoverageUtils","NotFoundError","aggregateCoverage","InputError","getEntitySourceLocation","Jacoco","Cobertura","Lcov","MiddlewareFactory"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-code-coverage-backend",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "A Backstage backend plugin that helps you keep track of your code coverage",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",