UNPKG

6.19 kBJavaScriptView Raw
1(function(request, Joi, Promise, util, lodash, logger) {
2 'use strict';
3
4 var optionsValidation = Joi.object({
5 endpoint: Joi.string().min(1).optional().example('https://api.codacy.com/2.0/coverage/:commitId/:language')
6 });
7 var tokenValidation = Joi.string().required().min(1).example('1234567890');//TODO: Revisit this validation to see if we can better validate the values
8 var commitIdValidation = Joi.string().required().min(1).example('1234567890'); //TODO: Revisit this validation to see if we can better validate the values
9 var coverageDataValidation = Joi.object({
10 total: Joi.number().integer().required().min(0).max(100),
11 fileReports: Joi.array().required().items(Joi.object({
12 filename: Joi.string().required().min(1),
13 total: Joi.number().integer().required().min(0).max(100),
14 coverage: Joi.object().pattern(/\d/, Joi.number().integer().min(1))
15 }).required())
16 }).example({total: 50, fileReports: [{filename: 'filename', total: 10, coverage: {1: 1, 2: 3}}]});
17
18 var languageMap = {
19 js: 'javascript',
20 jsx: 'javascript',
21 ts: 'typescript',
22 tsx: 'typescript',
23 coffee: 'coffeescript'
24 }
25
26 function sendByLanguage(endpoint, commitId, token, data) {
27 var reportsByLanguage = lodash.groupBy(data.fileReports, function(elem) {
28 return languageMap[lodash.head(lodash.takeRight(elem.filename.split('.'), 1))] || 'javascript';
29 });
30
31 var languageResponses = lodash.map(reportsByLanguage, function(fileReports, language) {
32 var weighedCoverage = lodash.reduce(fileReports, function(accom, elem) {
33 return accom + (elem.total * Object.keys(elem.coverage).length);
34 }, 0);
35
36 var coveredLines = lodash.reduce(fileReports, function(accom, elem) {
37 return accom + Object.keys(elem.coverage).length;
38 }, 0);
39
40 var finalCoverage = weighedCoverage / coveredLines;
41
42 var dataPerLanguage = lodash.clone(data);
43 dataPerLanguage.fileReports = fileReports;
44 dataPerLanguage.total = Math.floor(finalCoverage);
45
46 return sendLanguage(endpoint, commitId, language, token, dataPerLanguage);
47 });
48
49 return Promise.all(languageResponses)
50 .then(function(errs) {
51 errs = lodash.filter(errs, function(e) {
52 return !lodash.isUndefined(e)
53 });
54
55 if (errs.length) {
56 return Promise.reject(errs[0]);
57 }
58
59 logger.trace('All languages sent successfully');
60 return Promise.resolve();
61 }, function(err) {
62 logger.trace('Failed to send some languages');
63 return Promise.reject(err);
64 });
65 }
66
67 function sendForLanguage(endpoint, commitId, language, token, data) {
68 return sendLanguage(endpoint, commitId, language, token, data)
69 .then(function(err) {
70 if (err) {
71 return Promise.reject(err);
72 }
73 return Promise.resolve();
74 }, function(err) {
75 return Promise.reject(err);
76 });
77 }
78
79 function sendLanguage(endpoint, commitId, language, token, data) {
80 var url = endpoint.replace(':commitId', commitId).replace(':language', language);
81 logger.trace(util.format('Sending POST to %s', url));
82 return request({
83 url: url,
84 method: 'POST',
85 json: data,
86 headers: {
87 // jscs:disable
88 project_token: token
89 // jscs:enable
90 },
91 resolveWithFullResponse: true
92 }).then(function(res) {
93 if (res.statusCode !== 200) {
94 var err = new Error(util.format('Expected Status Code of 200, but got [%s]', res.statusCode));
95 logger.error(util.format('Status Code [%s] - Error [%j]', res.statusCode, res.error));
96 return Promise.reject(err);
97 }
98 logger.debug('Successfully sent coverage data');
99 return Promise.resolve();
100 }, function(res) {
101 var err = new Error(util.format('Expected Successful Status Code, but got [%s]', res.statusCode));
102 logger.error(util.format('Status Code [%s] - Error [%j]', res.statusCode, res.error));
103 return Promise.reject(err);
104 });
105 }
106
107 module.exports = function(options) {
108 logger.trace(util.format('Creating reporter for %j', options));
109 var optionsValid = Joi.validate(options, optionsValidation, {
110 stripUnknown: true
111 });
112
113 if (optionsValid.error) {
114 logger.error(optionsValid.error);
115 throw optionsValid.error;
116 }
117
118 var endpoint = (options.endpoint || 'https://api.codacy.com') + '/2.0/coverage/:commitId/:language';
119 logger.debug('Setting up reporter communicating to: ' + endpoint);
120
121 return {
122 sendCoverage: function sendCoverage(token, commitId, language, data) {
123 logger.trace(util.format('Sending Coverage for token [%s] and commitId [%s]', token, commitId));
124 var tokenValid = Joi.validate(token, tokenValidation);
125 var commitIdValid = Joi.validate(commitId, commitIdValidation);
126 var dataValid = Joi.validate(data, coverageDataValidation, {
127 stripUnknown: true
128 });
129 var validationErr = tokenValid.error || commitIdValid.error || dataValid.error;
130
131 if (validationErr) {
132 logger.error(validationErr);
133 return Promise.reject(validationErr);
134 }
135
136 if (language) {
137 return sendForLanguage(endpoint, commitId, language, token, data);
138 }
139
140 return sendByLanguage(endpoint, commitId, token, data);
141 }
142 };
143 };
144}(require('request-promise'), require('joi'), require('bluebird'), require('util'), require('lodash'), require('./logger')()));