From 283c3f14760c925fe9bf51a2db6f2d567dedb4fe Mon Sep 17 00:00:00 2001 From: Kevin J Hoerr Date: Sat, 25 Sep 2021 17:33:23 +0000 Subject: Add lint check to pipeline --- .drone.yml | 1 + src/.prettierrc.json | 1 - src/errors.ts | 2 +- src/formats.ts | 12 +++---- src/index.ts | 9 +++-- src/metadata.ts | 6 ++-- src/routes.test.ts | 95 ++++++++++++++++++++++++++++++------------------- src/routes.ts | 28 +++++++-------- src/templates.test.ts | 2 +- src/templates.ts | 31 ++++++++-------- src/util/config.test.ts | 88 +++++++++++++++++++++++++++------------------ src/util/config.ts | 42 +++++++++++----------- src/util/logger.test.ts | 6 ++-- src/util/logger.ts | 2 +- 14 files changed, 181 insertions(+), 144 deletions(-) diff --git a/.drone.yml b/.drone.yml index 7e4f3d8..cb81f80 100644 --- a/.drone.yml +++ b/.drone.yml @@ -15,6 +15,7 @@ steps: commands: - mkdir -p $HOST_DIR && chown $USER:$USER $HOST_DIR - yarn install --immutable --immutable-cache --check-cache + - yarn run lint - yarn run test:coverage - curl --proto '=https' --tlsv1.2 -sSf https://cov.submelon.dev/sh | sh diff --git a/src/.prettierrc.json b/src/.prettierrc.json index fca24df..c3fef9a 100644 --- a/src/.prettierrc.json +++ b/src/.prettierrc.json @@ -1,5 +1,4 @@ { - "trailingComma": "none", "tabWidth": 2, "semi": true, "singleQuote": false diff --git a/src/errors.ts b/src/errors.ts index 6e8c32f..822f98e 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -19,5 +19,5 @@ export const Messages = { FileTooLarge: "Uploaded file is too large", InvalidFormat: "Invalid reporting format", InvalidToken: "Invalid token", - UnknownError: "Unknown error occurred" + UnknownError: "Unknown error occurred", }; diff --git a/src/formats.ts b/src/formats.ts index db13fa6..ff24061 100644 --- a/src/formats.ts +++ b/src/formats.ts @@ -75,7 +75,7 @@ const FormatsObj: FormatObj = { return (100 * covered) / coverable; }, matchColor: defaultColorMatches, - fileName: "index.html" + fileName: "index.html", }, cobertura: { parseCoverage: async (contents: string): Promise => { @@ -98,17 +98,17 @@ const FormatsObj: FormatObj = { } }, matchColor: defaultColorMatches, - fileName: "index.xml" - } + fileName: "index.xml", + }, }, - listFormats: function() { + listFormats: function () { return Object.keys(this.formats); }, - getFormat: function(format: string) { + getFormat: function (format: string) { return this.formats[format]; - } + }, }; export default FormatsObj; diff --git a/src/index.ts b/src/index.ts index 5f688f8..1de4b10 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ import { configOrError, handleStartup, handleShutdown, - initializeToken + initializeToken, } from "./util/config"; // Start-up configuration @@ -28,12 +28,12 @@ const ENV_CONFIG: EnvConfig = { publicDir: path.join(__dirname, "..", "public"), hostDir: configOrError("HOST_DIR"), stage1: Number(process.env.STAGE_1 ?? 95), - stage2: Number(process.env.STAGE_2 ?? 80) + stage2: Number(process.env.STAGE_2 ?? 80), }; const logger = winston.createLogger(loggerConfig("ROOT")); -handleStartup(MONGO_URI, ENV_CONFIG, TARGET_URL).then(mongo => { +handleStartup(MONGO_URI, ENV_CONFIG, TARGET_URL).then((mongo) => { const app: express.Application = express(); const metadata = new Metadata(mongo.db(MONGO_DB), ENV_CONFIG); @@ -42,8 +42,7 @@ handleStartup(MONGO_URI, ENV_CONFIG, TARGET_URL).then(mongo => { ...loggerConfig("HTTP"), colorize: true, // filter out token query param from URL - msg: - '{{req.method}} {{req.url.replace(/token=[-\\w.~]*(&*)/, "token=$1")}} - {{res.statusCode}} {{res.responseTime}}ms' + msg: '{{req.method}} {{req.url.replace(/token=[-\\w.~]*(&*)/, "token=$1")}} - {{res.statusCode}} {{res.responseTime}}ms', }) ); diff --git a/src/metadata.ts b/src/metadata.ts index 8f2ea3e..3cba605 100644 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -76,7 +76,7 @@ class Metadata { getGradientStyle(): GradientStyle { return { stage1: this.config.stage1, - stage2: this.config.stage2 + stage2: this.config.stage2, }; } @@ -90,7 +90,7 @@ class Metadata { .findOne({ organization, name: repository, - ["branches." + branch]: { $exists: true, $ne: null } + ["branches." + branch]: { $exists: true, $ne: null }, }); if (result !== null && Object.keys(result.branches).includes(branch)) { @@ -133,7 +133,7 @@ class Metadata { const repo: Repository = { organization, name, - branches: { [branch]: { head } } + branches: { [branch]: { head } }, }; const result = await this.database diff --git a/src/routes.test.ts b/src/routes.test.ts index dc2b6a6..1381abb 100644 --- a/src/routes.test.ts +++ b/src/routes.test.ts @@ -31,18 +31,21 @@ let output = ""; jest.mock("./util/logger", () => { const stream = new Writable(); stream._write = (chunk, _encoding, next) => { - output = output += chunk.toString(); - next(); + output = output += chunk.toString(); + next(); }; const streamTransport = new winston.transports.Stream({ stream }); return { __esModule: true, default: () => ({ - format: winston.format.combine(winston.format.splat(), winston.format.simple()), - transports: [streamTransport] - }) - } + format: winston.format.combine( + winston.format.splat(), + winston.format.simple() + ), + transports: [streamTransport], + }), + }; }); import { configOrError, persistTemplate } from "./util/config"; @@ -73,14 +76,14 @@ const config = { hostDir: configOrError("HOST_DIR"), publicDir: path.join(__dirname, "..", "public"), stage1: 95, - stage2: 80 + stage2: 80, }; const mock = ( headCommit: jest.Mock = jest.fn( () => - new Promise(solv => solv({ commit: "testcommit", format: "tarpaulin" })) + new Promise((solv) => solv({ commit: "testcommit", format: "tarpaulin" })) ), - updateBranch: jest.Mock = jest.fn(() => new Promise(solv => solv(true))) + updateBranch: jest.Mock = jest.fn(() => new Promise((solv) => solv(true))) ): MetadataMockType => ({ database: {} as Db, config: config, @@ -90,11 +93,11 @@ const mock = ( getPublicDir: jest.fn(() => config.publicDir), getGradientStyle: jest.fn(() => ({ stage1: config.stage1, - stage2: config.stage2 + stage2: config.stage2, })), getHeadCommit: headCommit, updateBranch: updateBranch, - createRepository: jest.fn() + createRepository: jest.fn(), }); const request = async ( @@ -121,7 +124,7 @@ describe("templates", () => { "sh.template" ), outputFile: path.join(HOST_DIR, "sh"), - context: { TARGET_URL } + context: { TARGET_URL }, } as Template); const res = await (await request()).get("/sh").expect(200); @@ -142,7 +145,7 @@ describe("templates", () => { "index.html.template" ), outputFile: path.join(HOST_DIR, "index.html"), - context: { TARGET_URL, CURL_HTTPS: "--https " } + context: { TARGET_URL, CURL_HTTPS: "--https " }, } as Template); const res = await (await request()) @@ -150,9 +153,7 @@ describe("templates", () => { .expect("Content-Type", /html/) .expect(200); expect(exit).not.toHaveBeenCalled(); - expect(res.text).toMatch( - `curl --https -sSf ${TARGET_URL}/sh | sh` - ); + expect(res.text).toMatch(`curl --https -sSf ${TARGET_URL}/sh | sh`); }); }); }); @@ -214,7 +215,7 @@ describe("Badges and reports", () => { const fakeBadge = badgen({ label: "coverage", status: "120%", - color: "#E1C" + color: "#E1C", }); beforeAll(async () => { @@ -283,7 +284,7 @@ describe("Badges and reports", () => { it("should retrieve the marked format as stored in metadata", async () => { const head = jest.fn( () => - new Promise(solv => + new Promise((solv) => solv({ commit: "testcommit", format: "cobertura" }) ) ); @@ -305,7 +306,7 @@ describe("Badges and reports", () => { it("should return 404 if head commit not found", async () => { const head = jest.fn( - () => new Promise(solv => solv(new BranchNotFoundError())) + () => new Promise((solv) => solv(new BranchNotFoundError())) ); await (await request(mock(head))) .get("/v1/testorg/testrepo/testbranch.html") @@ -324,7 +325,7 @@ describe("Badges and reports", () => { it("should retrieve the stored report file with the associated head commit", async () => { const head = jest.fn( () => - new Promise(solv => + new Promise((solv) => solv({ commit: "testcommit", format: "cobertura" }) ) ); @@ -342,7 +343,7 @@ describe("Badges and reports", () => { it("should retrieve the marked format as stored in metadata", async () => { const head = jest.fn( () => - new Promise(solv => + new Promise((solv) => solv({ commit: "testcommit", format: "tarpaulin" }) ) ); @@ -364,7 +365,7 @@ describe("Badges and reports", () => { it("should return 404 if head commit not found", async () => { const head = jest.fn( - () => new Promise(solv => solv(new BranchNotFoundError())) + () => new Promise((solv) => solv(new BranchNotFoundError())) ); await (await request(mock(head))) .get("/v1/testorg/testrepo/testbranch.xml") @@ -414,7 +415,7 @@ describe("Badges and reports", () => { it("should return 404 if head commit not found", async () => { const head = jest.fn( - () => new Promise(solv => solv(new BranchNotFoundError())) + () => new Promise((solv) => solv(new BranchNotFoundError())) ); await (await request(mock(head))) .get("/v1/testorg/testrepo/testbranch.svg") @@ -454,7 +455,9 @@ describe("Uploads", () => { it("should upload the report and generate a badge", async () => { const mockMeta = mock(); - await (await request(mockMeta)) + await ( + await request(mockMeta) + ) .post( `/v1/testorg/testrepo/newthis/newthat.html?token=${config.token}&format=tarpaulin` ) @@ -465,7 +468,7 @@ describe("Uploads", () => { organization: "testorg", repository: "testrepo", branch: "newthis", - head: { commit: "newthat", format: "tarpaulin" } + head: { commit: "newthat", format: "tarpaulin" }, }); expect(mockMeta.updateBranch).toHaveBeenCalledTimes(1); await fs.promises.access( @@ -479,7 +482,9 @@ describe("Uploads", () => { }); it("should return 401 when token is not correct", async () => { - await (await request()) + await ( + await request() + ) .post( `/v1/testorg/testrepo/newthis/newthat.html?token=wrong&format=tarpaulin` ) @@ -488,7 +493,9 @@ describe("Uploads", () => { }); it("should return 406 with an invalid format", async () => { - await (await request()) + await ( + await request() + ) .post( `/v1/testorg/testrepo/newthis/newthat.html?token=${config.token}&format=pepperoni` ) @@ -520,8 +527,10 @@ describe("Uploads", () => { }); it("should return 500 when Metadata does not create branch", async () => { - const update = jest.fn(() => new Promise(solv => solv(false))); - await (await request(mock(jest.fn(), update))) + const update = jest.fn(() => new Promise((solv) => solv(false))); + await ( + await request(mock(jest.fn(), update)) + ) .post( `/v1/testorg/testrepo/newthis/newthat.html?token=${config.token}&format=tarpaulin` ) @@ -531,7 +540,9 @@ describe("Uploads", () => { it("should return 500 when promise chain is rejected", async () => { const update = jest.fn(() => new Promise((_, rej) => rej("fooey 2"))); - await (await request(mock(jest.fn(), update))) + await ( + await request(mock(jest.fn(), update)) + ) .post( `/v1/testorg/testrepo/newthis/newthat.html?token=${config.token}&format=tarpaulin` ) @@ -547,7 +558,9 @@ describe("Uploads", () => { it("should upload the report and generate a badge", async () => { const mockMeta = mock(); - await (await request(mockMeta)) + await ( + await request(mockMeta) + ) .post( `/v1/testorg/testrepo/newthis/newthat.xml?token=${config.token}&format=cobertura` ) @@ -558,7 +571,7 @@ describe("Uploads", () => { organization: "testorg", repository: "testrepo", branch: "newthis", - head: { commit: "newthat", format: "cobertura" } + head: { commit: "newthat", format: "cobertura" }, }); expect(mockMeta.updateBranch).toHaveBeenCalledTimes(1); await fs.promises.access( @@ -572,7 +585,9 @@ describe("Uploads", () => { }); it("should return 401 when token is not correct", async () => { - await (await request()) + await ( + await request() + ) .post( `/v1/testorg/testrepo/newthis/newthat.xml?token=wrong&format=cobertura` ) @@ -581,7 +596,9 @@ describe("Uploads", () => { }); it("should return 406 with an invalid format", async () => { - await (await request()) + await ( + await request() + ) .post( `/v1/testorg/testrepo/newthis/newthat.xml?token=${config.token}&format=pepperoni` ) @@ -613,8 +630,10 @@ describe("Uploads", () => { }); it("should return 500 when Metadata does not create branch", async () => { - const update = jest.fn(() => new Promise(solv => solv(false))); - await (await request(mock(jest.fn(), update))) + const update = jest.fn(() => new Promise((solv) => solv(false))); + await ( + await request(mock(jest.fn(), update)) + ) .post( `/v1/testorg/testrepo/newthis/newthat.xml?token=${config.token}&format=cobertura` ) @@ -624,7 +643,9 @@ describe("Uploads", () => { it("should return 500 when promise chain is rejected", async () => { const update = jest.fn(() => new Promise((_, rej) => rej("fooey 2"))); - await (await request(mock(jest.fn(), update))) + await ( + await request(mock(jest.fn(), update)) + ) .post( `/v1/testorg/testrepo/newthis/newthat.xml?token=${config.token}&format=cobertura` ) diff --git a/src/routes.ts b/src/routes.ts index e25918c..7383c5d 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -39,7 +39,7 @@ export default (metadata: Metadata): Router => { const badge = badgen({ label: "coverage", status: Math.floor(coverage).toString() + "%", - color: formatter.matchColor(coverage, style) + color: formatter.matchColor(coverage, style), }); // Write report and badge to directory @@ -62,7 +62,7 @@ export default (metadata: Metadata): Router => { router.use( "/:shell(bash|sh)", express.static(path.join(metadata.getHostDir(), "sh"), { - setHeaders: res => res.contentType("text/plain") + setHeaders: (res) => res.contentType("text/plain"), }) ); @@ -95,7 +95,7 @@ export default (metadata: Metadata): Router => { } let contents = ""; - req.on("data", raw => { + req.on("data", (raw) => { if (contents.length <= limit) { contents += raw; } @@ -111,7 +111,7 @@ export default (metadata: Metadata): Router => { organization: org, repository: repo, branch, - head: { commit, format } + head: { commit, format }, }; try { @@ -153,7 +153,7 @@ export default (metadata: Metadata): Router => { head.commit, file ); - fs.access(pathname, fs.constants.R_OK, err => + fs.access(pathname, fs.constants.R_OK, (err) => err === null ? res.sendFile(pathname) : res.status(404).send(Messages.FileNotFound) @@ -164,20 +164,20 @@ export default (metadata: Metadata): Router => { const { org, repo, branch } = req.params; metadata.getHeadCommit(org, repo, branch).then( - result => { + (result) => { if (!isError(result)) { const identity = { organization: org, repository: repo, branch, - head: result + head: result, }; retrieveFile(res, identity, "badge.svg"); } else { res.status(404).send(result.message); } }, - err => { + (err) => { logger.error( err ?? "Error occurred while fetching commit for GET request" ); @@ -190,13 +190,13 @@ export default (metadata: Metadata): Router => { const { org, repo, branch } = req.params; metadata.getHeadCommit(org, repo, branch).then( - result => { + (result) => { if (!isError(result)) { const identity = { organization: org, repository: repo, branch, - head: result + head: result, }; const { fileName } = formats.getFormat(result.format); retrieveFile(res, identity, fileName); @@ -204,7 +204,7 @@ export default (metadata: Metadata): Router => { res.status(404).send(result.message); } }, - err => { + (err) => { logger.error( err ?? "Error occurred while fetching commit for GET request" ); @@ -220,7 +220,7 @@ export default (metadata: Metadata): Router => { organization: org, repository: repo, branch, - head: { commit, format: "_" } + head: { commit, format: "_" }, }; retrieveFile(res, identity, "badge.svg"); }); @@ -233,7 +233,7 @@ export default (metadata: Metadata): Router => { organization: org, repository: repo, branch, - head: { commit, format: "tarpaulin" } + head: { commit, format: "tarpaulin" }, }; retrieveFile(res, identity, format.fileName); }); @@ -245,7 +245,7 @@ export default (metadata: Metadata): Router => { organization: org, repository: repo, branch, - head: { commit, format: "cobertura" } + head: { commit, format: "cobertura" }, }; retrieveFile(res, identity, format.fileName); }); diff --git a/src/templates.test.ts b/src/templates.test.ts index 1fb88b7..e434ce4 100644 --- a/src/templates.test.ts +++ b/src/templates.test.ts @@ -11,7 +11,7 @@ const genTemplate = (filename: string): Template => "build", filename.replace(/template/, "txt") ), - context: { that: "this", potential: "resolved" } + context: { that: "this", potential: "resolved" }, } as Template); describe("processTemplate", () => { diff --git a/src/templates.ts b/src/templates.ts index 5458a36..648bb56 100644 --- a/src/templates.ts +++ b/src/templates.ts @@ -4,23 +4,20 @@ import fs from "fs"; export interface Template { inputFile: string; outputFile: string; - context: object; - data: string | undefined; + context: Record; + data?: string; } -export default (_template: Template): Promise