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(0))
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
33 var weighedCoverage = lodash.reduce(fileReports, function(accom, elem) {
34 return accom + (elem.total * Object.keys(elem.coverage).length);
35 }, 0);
36
37 var coveredLines = lodash.reduce(fileReports, function(accom, elem) {
38 return accom + Object.keys(elem.coverage).length;
39 }, 0);
40
41 var finalCoverage = weighedCoverage / coveredLines;
42
43 var dataPerLanguage = lodash.clone(data);
44 dataPerLanguage.fileReports = fileReports;
45 dataPerLanguage.total = Math.floor(finalCoverage);
46
47 return sendLanguage(endpoint, commitId, language, token, dataPerLanguage);
48 });
49
50 return Promise.all(languageResponses)
51 .then(function(errs) {
52 errs = lodash.filter(errs, function(e) {
53 return !lodash.isUndefined(e)
54 });
55
56 if (errs.length) {
57 return Promise.reject(errs[0]);
58 }
59
60 logger.trace('All languages sent successfully');
61 return Promise.resolve();
62 }, function(err) {
63 logger.trace('Failed to send some languages');
64 return Promise.reject(err);
65 });
66 }
67
68 function sendForLanguage(endpoint, commitId, language, token, data) {
69 return sendLanguage(endpoint, commitId, language, token, data)
70 .then(function(err) {
71 if (err) {
72 return Promise.reject(err);
73 }
74 return Promise.resolve();
75 }, function(err) {
76 return Promise.reject(err);
77 });
78 }
79
80 function sendLanguage(endpoint, commitId, language, token, data) {
81 var url = endpoint.replace(':commitId', commitId).replace(':language', language);
82 logger.trace(util.format('Sending POST to %s', url));
83 return request({
84 url: url,
85 method: 'POST',
86 json: data,
87 headers: {
88 // jscs:disable
89 project_token: token
90 // jscs:enable
91 },
92 resolveWithFullResponse: true
93 }).then(function(res) {
94 if (res.statusCode !== 200) {
95 var err = new Error(util.format('Expected Status Code of 200, but got [%s]', res.statusCode));
96 logger.error(util.format('Status Code [%s] - Error [%j]', res.statusCode, res.error));
97 return Promise.reject(err);
98 }
99 logger.debug('Successfully sent coverage data');
100 return Promise.resolve();
101 }, function(res) {
102 var err = new Error(util.format('Expected Successful Status Code, but got [%s]', res.statusCode));
103 logger.error(util.format('Status Code [%s] - Error [%j]', res.statusCode, res.error));
104 return Promise.reject(err);
105 });
106 }
107
108 module.exports = function(options) {
109 logger.trace(util.format('Creating reporter for %j', options));
110 var optionsValid = Joi.validate(options, optionsValidation, {
111 stripUnknown: true
112 });
113
114 if (optionsValid.error) {
115 logger.error(optionsValid.error);
116 throw optionsValid.error;
117 }
118
119 var endpoint = (options.endpoint || 'https://api.codacy.com') + '/2.0/coverage/:commitId/:language';
120 logger.debug('Setting up reporter communicating to: ' + endpoint);
121
122 return {
123 sendCoverage: function sendCoverage(token, commitId, language, data) {
124 logger.trace(util.format('Sending Coverage for token [%s] and commitId [%s]', token, commitId));
125 var tokenValid = Joi.validate(token, tokenValidation);
126 var commitIdValid = Joi.validate(commitId, commitIdValidation);
127 var dataValid = Joi.validate(data, coverageDataValidation, {
128 stripUnknown: true
129 });
130 var validationErr = tokenValid.error || commitIdValid.error || dataValid.error;
131
132 if (validationErr) {
133 logger.error(validationErr);
134 return Promise.reject(validationErr);
135 }
136
137 if (language) {
138 return sendForLanguage(endpoint, commitId, language, token, data);
139 }
140
141 return sendByLanguage(endpoint, commitId, token, data);
142 }
143 };
144 };
145}(require('request-promise'), require('joi'), require('bluebird'), require('util'), require('lodash'), require('./logger')()));