aboutsummaryrefslogtreecommitdiff
path: root/src/routes.ts
blob: 1dbc94fdcab61c51e8071d9934854b77960b81da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import express from "express";
import { JSDOM } from "jsdom";
import { badgen } from "badgen";
import path from "path";
import fs from "fs";

import formats, { Format } from "./formats";
import Metadata from "./metadata";
import { config_or_error } from "./util/config";

const TOKEN = process.env.TOKEN || "";
const UPLOAD_LIMIT = Number(process.env.UPLOAD_LIMIT || 4194304);
const HOST_DIR = config_or_error("HOST_DIR");

export default (metadata: Metadata) => {
  const router = express.Router();

  // Upload HTML file
  router.post("/v1/:org/:repo/:branch/:commit.html", (req, res) => {
    const { org, repo, branch, commit } = req.params;

    const { token, format } = req.query;
    //TODO @Metadata token should come from metadata
    if (token != TOKEN) {
      return res.status(401).send("Invalid token");
    }

    if (!formats.list_formats().includes(format)) {
      return res.status(406).send("Report format unknown");
    }

    var contents = "";
    req.on("data", raw => {
      if (contents.length + raw.length > UPLOAD_LIMIT) {
        res.status(413).send("Uploaded file is too large");
      } else {
        contents += raw;
      }
    });
    req.on("end", () => {
      let formatter: Format, coverage: number;
      try {
        const doc = new JSDOM(contents).window.document;
        formatter = formats.get_format(format);
        coverage = formatter.parse_coverage(doc);
      } catch {
        return res.status(400).send("Invalid report document");
      }

      const badge = badgen({
        label: "coverage",
        status: Math.floor(coverage).toString() + "%",
        //TODO @Metadata stage values should come from metadata
        color: formatter.match_color(coverage, 95, 80)
      });

      const report_path = path.join(HOST_DIR, org, repo, branch, commit);

      fs.promises
        .mkdir(report_path, { recursive: true })
        .then(() =>
          fs.promises.writeFile(path.join(report_path, "badge.svg"), badge)
        )
        .then(() =>
          fs.promises.writeFile(path.join(report_path, "index.html"), contents)
        )
        .then(() =>
          metadata.updateBranch({ org, repo, name: branch, head: commit })
        )
        .then(result =>
          result
            ? res.status(200).send()
            : res.status(500).send("Unknown error occurred")
        );
    });
  });

  router.get("/v1/:org/:repo/:branch.svg", (req, res) => {
    const { org, repo, branch } = req.params;

    metadata.getHeadCommit(org, repo, branch).then(
      commit => {
        res.sendFile(
          path.join(HOST_DIR, org, repo, branch, commit, "badge.svg")
        );
      },
      () => {
        res.status(500).send("Unknown error occurred");
      }
    );
  });

  router.get("/v1/:org/:repo/:branch.html", (req, res) => {
    const { org, repo, branch } = req.params;

    metadata.getHeadCommit(org, repo, branch).then(
      commit => {
        res.sendFile(
          path.join(HOST_DIR, org, repo, branch, commit, "index.html")
        );
      },
      () => {
        res.status(500).send("Unknown error occurred");
      }
    );
  });

  // provide hard link for commit
  router.get("/v1/:org/:repo/:branch/:commit.svg", (req, res) => {
    const { org, repo, branch, commit } = req.params;

    res.sendFile(path.join(HOST_DIR, org, repo, branch, commit, "badge.svg"));
  });

  // provide hard link for commit
  router.get("/v1/:org/:repo/:branch/:commit.html", (req, res) => {
    const { org, repo, branch, commit } = req.params;

    res.sendFile(path.join(HOST_DIR, org, repo, branch, commit, "index.html"));
  });

  return router;
};