Initial commit of the airbrake-backend plugin

Signed-off-by: Karan Shah <karan.shah@simplybusiness.co.uk>
This commit is contained in:
Karan Shah
2022-02-02 14:33:50 +00:00
parent 74298c1ae3
commit 2a8fee1a51
11 changed files with 312 additions and 11 deletions
+6 -5
View File
@@ -38,8 +38,8 @@
"@backstage/plugin-code-coverage-backend": "^0.1.20",
"@backstage/plugin-graphql-backend": "^0.1.12",
"@backstage/plugin-jenkins-backend": "^0.1.11",
"@backstage/plugin-kubernetes-backend": "^0.4.5",
"@backstage/plugin-kafka-backend": "^0.2.15",
"@backstage/plugin-kubernetes-backend": "^0.4.5",
"@backstage/plugin-permission-backend": "^0.4.2-next.0",
"@backstage/plugin-permission-common": "^0.4.0",
"@backstage/plugin-permission-node": "^0.4.2-next.0",
@@ -48,22 +48,23 @@
"@backstage/plugin-scaffolder-backend": "^0.15.23-next.0",
"@backstage/plugin-scaffolder-backend-module-rails": "^0.2.5-next.0",
"@backstage/plugin-search-backend": "^0.4.1-next.0",
"@backstage/plugin-search-backend-node": "^0.4.5",
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.8",
"@backstage/plugin-search-backend-module-pg": "^0.2.4",
"@backstage/plugin-techdocs-backend": "^0.13.1",
"@backstage/plugin-search-backend-node": "^0.4.5",
"@backstage/plugin-tech-insights-backend": "^0.2.2",
"@backstage/plugin-tech-insights-node": "^0.2.0",
"@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.6",
"@backstage/plugin-tech-insights-node": "^0.2.0",
"@backstage/plugin-techdocs-backend": "^0.13.1",
"@backstage/plugin-todo-backend": "^0.1.19",
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^18.5.3",
"azure-devops-node-api": "^11.0.1",
"backstage-plugin-airbrake-backend": "^0.0.0",
"dockerode": "^3.3.1",
"example-app": "file:../app",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"express-prom-bundle": "^6.3.6",
"express-promise-router": "^4.1.0",
"knex": "^0.95.1",
"pg": "^8.3.0",
"pg-connection-string": "^2.3.0",
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
};
+16
View File
@@ -0,0 +1,16 @@
# airbrake-backend
Welcome to the airbrake-backend backend plugin!
_This plugin was created through the Backstage CLI_
## Getting started
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/airbrake-backend](http://localhost:7007/airbrake-backend).
Here is an example endpoint: http://localhost:7007/airbrake-backend/health
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
It is only meant for local development.
+50
View File
@@ -0,0 +1,50 @@
{
"name": "backstage-plugin-airbrake-backend",
"version": "0.0.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"scripts": {
"start": "backstage-cli backend:dev",
"build": "backstage-cli backend:build",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/backend-common": "^0.10.5",
"@backstage/config": "^0.1.13",
"@types/express": "*",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"winston": "^3.2.1",
"cross-fetch": "^3.0.6",
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.13.1-next.0",
"@types/supertest": "^2.0.8",
"supertest": "^4.0.2",
"msw": "^0.35.0"
},
"files": [
"dist"
],
"jest": {
"coverageThreshold": {
"global": {
"functions": 100,
"lines": 100,
"statements": 100
}
}
}
}
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './service/router';
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -0,0 +1,45 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { getVoidLogger } from '@backstage/backend-common';
import express from 'express';
import request from 'supertest';
import { createRouter } from './router';
describe('createRouter', () => {
let app: express.Express;
beforeAll(async () => {
const router = await createRouter({
logger: getVoidLogger(),
});
app = express().use(router);
});
beforeEach(() => {
jest.resetAllMocks();
});
describe('GET /health', () => {
it('returns ok', async () => {
const response = await request(app).get('/health');
expect(response.status).toEqual(200);
expect(response.body).toEqual({ status: 'ok' });
});
});
});
@@ -0,0 +1,40 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { errorHandler } from '@backstage/backend-common';
import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
export interface RouterOptions {
logger: Logger;
}
export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
const { logger } = options;
const router = Router();
router.use(express.json());
router.get('/health', (_, response) => {
logger.info('PONG!');
response.send({ status: 'ok' });
});
router.use(errorHandler());
return router;
}
@@ -0,0 +1,50 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createServiceBuilder } from '@backstage/backend-common';
import { Server } from 'http';
import { Logger } from 'winston';
import { createRouter } from './router';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: Logger;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'airbrake-backend-backend' });
logger.debug('Starting application server...');
const router = await createRouter({
logger,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/airbrake-backend', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
@@ -0,0 +1,17 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export {};
+35 -6
View File
@@ -9026,7 +9026,7 @@ compare-func@^2.0.0:
array-ify "^1.0.0"
dot-prop "^5.1.0"
component-emitter@^1.2.1, component-emitter@^1.3.0:
component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
@@ -9307,7 +9307,7 @@ cookie@0.4.1, cookie@^0.4.1, cookie@~0.4.1:
resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
cookiejar@^2.1.3:
cookiejar@^2.1.0, cookiejar@^2.1.3:
version "2.1.3"
resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc"
integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==
@@ -12344,7 +12344,7 @@ form-data@4.0.0, form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@^2.3.2, form-data@^2.5.0:
form-data@^2.3.1, form-data@^2.3.2, form-data@^2.5.0:
version "2.5.1"
resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
@@ -12392,6 +12392,11 @@ formdata-node@^4.3.1:
node-domexception "1.0.0"
web-streams-polyfill "4.0.0-beta.1"
formidable@^1.2.0:
version "1.2.6"
resolved "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168"
integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==
formidable@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff"
@@ -16969,7 +16974,7 @@ meros@1.1.4, meros@^1.1.4:
resolved "https://registry.npmjs.org/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948"
integrity sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ==
methods@^1.0.0, methods@^1.1.2, methods@~1.1.2:
methods@^1.0.0, methods@^1.1.1, methods@^1.1.2, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
@@ -17324,7 +17329,7 @@ mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, m
dependencies:
mime-db "1.51.0"
mime@1.6.0:
mime@1.6.0, mime@^1.4.1:
version "1.6.0"
resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
@@ -20105,7 +20110,7 @@ qs@6.9.6:
resolved "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
qs@^6.10.1, qs@^6.10.2, qs@^6.9.1, qs@^6.9.4, qs@^6.9.6:
qs@^6.10.1, qs@^6.10.2, qs@^6.5.1, qs@^6.9.1, qs@^6.9.4, qs@^6.9.6:
version "6.10.3"
resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
@@ -22855,6 +22860,22 @@ sucrase@^3.18.0, sucrase@^3.20.2:
pirates "^4.0.1"
ts-interface-checker "^0.1.9"
superagent@^3.8.3:
version "3.8.3"
resolved "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128"
integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==
dependencies:
component-emitter "^1.2.0"
cookiejar "^2.1.0"
debug "^3.1.0"
extend "^3.0.0"
form-data "^2.3.1"
formidable "^1.2.0"
methods "^1.1.1"
mime "^1.4.1"
qs "^6.5.1"
readable-stream "^2.3.5"
superagent@^7.1.0:
version "7.1.1"
resolved "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz#2ab187d38c3078c31c3771c0b751f10163a27136"
@@ -22872,6 +22893,14 @@ superagent@^7.1.0:
readable-stream "^3.6.0"
semver "^7.3.5"
supertest@^4.0.2:
version "4.0.2"
resolved "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz#c2234dbdd6dc79b6f15b99c8d6577b90e4ce3f36"
integrity sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==
dependencies:
methods "^1.1.2"
superagent "^3.8.3"
supertest@^6.1.3, supertest@^6.1.6:
version "6.2.2"
resolved "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz#04a5998fd3efaff187cb69f07a169755d655b001"