Add [Jenkins] Jacoco coverage badge ☘ (#1593)

* Add Jenkins Jacoco coverage badge

* [Jenkins] add service test for jacoco coverage

* Added Jenkins Coverage (Jacoco) in all-badge-examples page

* Defined variables using let/const instead of var

* Used template string for the uri

* Used checkErrorResponse helper function for the error check

* Used NaN method for not a number test

* Prefixed the original Jenkin coverage test with "cobertura:"

* Moved the happy test case at front

* Merge the business logic between jacoco and cobertura

* Fixed lint issue

* Trigger notification
This commit is contained in:
Stanley Ng
2018-07-09 23:12:26 -07:00
committed by Danial
parent 036b191996
commit 85dd5f0809
3 changed files with 72 additions and 25 deletions

View File

@@ -215,13 +215,17 @@ const allBadgeExamples = [
previewUri: '/jenkins/s/https/jenkins.qa.ubuntu.com/view/Precise/view/All%20Precise/job/precise-desktop-amd64_default.svg'
},
{
title: 'Jenkins tests',
title: 'Jenkins Tests',
previewUri: '/jenkins/t/https/jenkins.qa.ubuntu.com/view/Precise/view/All%20Precise/job/precise-desktop-amd64_default.svg'
},
{
title: 'Jenkins coverage',
title: 'Jenkins Coverage (Cobertura)',
previewUri: '/jenkins/c/https/jenkins.qa.ubuntu.com/view/Utopic/view/All/job/address-book-service-utopic-i386-ci.svg'
},
{
title: 'Jenkins Coverage (Jacoco)',
previewUri: '/jenkins/j/https/jenkins.qa.ubuntu.com/view/Utopic/view/All/job/address-book-service-utopic-i386-ci.svg'
},
{
title: 'Bitbucket Pipelines',
previewUri: '/bitbucket/pipelines/atlassian/adf-builder-javascript.svg'

View File

@@ -4587,21 +4587,30 @@ cache(function(data, match, sendBadge, request) {
});
}));
// Jenkins coverage integration
camp.route(/^\/jenkins(?:-ci)?\/c\/(http(?:s)?)\/([^/]+)\/(.+)\.(svg|png|gif|jpg|json)$/,
// Jenkins coverage integration (cobertura + jacoco)
camp.route(/^\/jenkins(?:-ci)?\/(c|j)\/(http(?:s)?)\/([^/]+)\/(.+)\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {
var scheme = match[1]; // http(s)
var host = match[2]; // example.org:8080
var job = match[3]; // folder/job
var format = match[4];
var options = {
const type = match[1]; // c - cobertura | j - jacoco
const scheme = match[2]; // http(s)
const host = match[3]; // example.org:8080
const job = match[4]; // folder/job
const format = match[5];
const options = {
json: true,
uri: scheme + '://' + host + '/job/' + job
+ '/lastBuild/cobertura/api/json?tree=results[elements[name,denominator,numerator,ratio]]'
uri: `${scheme}://${host}/job/${job}/`
};
if (job.indexOf('/') > -1 ) {
options.uri = scheme + '://' + host + '/' + job
+ '/lastBuild/cobertura/api/json?tree=results[elements[name,denominator,numerator,ratio]]';
options.uri = `${scheme}://${host}/${job}/`;
}
switch (type) {
case 'c':
options.uri += 'lastBuild/cobertura/api/json?tree=results[elements[name,denominator,numerator,ratio]]';
break;
case 'j':
options.uri += 'lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]';
break;
}
if (serverSecrets && serverSecrets.jenkins_user) {
@@ -4611,25 +4620,22 @@ cache(function(data, match, sendBadge, request) {
};
}
var badgeData = getBadgeData('coverage', data);
const badgeData = getBadgeData('coverage', data);
request(options, function(err, res, json) {
if (err !== null) {
badgeData.text[1] = 'inaccessible';
if (checkErrorResponse(badgeData, err, res)) {
sendBadge(format, badgeData);
return;
}
try {
var coverageObject = json.results.elements.filter(function (obj) {
return obj.name === 'Lines';
})[0];
const coverageObject = json.instructionCoverage;
if (coverageObject === undefined) {
badgeData.text[1] = 'inaccessible';
sendBadge(format, badgeData);
return;
}
var coverage = coverageObject.ratio;
if (+coverage !== +coverage) {
const coverage = coverageObject.percentage;
if (isNaN(coverage)) {
badgeData.text[1] = 'unknown';
sendBadge(format, badgeData);
return;

View File

@@ -6,7 +6,7 @@ const ServiceTester = require('../service-tester');
const t = new ServiceTester({ id: 'jenkins', title: 'Jenkins' });
module.exports = t;
t.create('latest version')
t.create('cobertura: latest version')
.get('/plugin/v/blueocean.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/current/update-center.actual.json')
@@ -17,7 +17,7 @@ t.create('latest version')
value: Joi.string().regex(/^v(.*)$/)
}));
t.create('version 0')
t.create('cobertura: version 0')
.get('/plugin/v/blueocean.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/current/update-center.actual.json')
@@ -28,7 +28,7 @@ t.create('version 0')
value: Joi.string().regex(/^v0$/)
}));
t.create('inexistent artifact')
t.create('cobertura: inexistent artifact')
.get('/plugin/v/inexistent-artifact-id.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/current/update-center.actual.json')
@@ -36,7 +36,44 @@ t.create('inexistent artifact')
)
.expectJSON({ name: 'plugin', value: 'not found' });
t.create('connection error')
t.create('cobertura: connection error')
.get('/plugin/v/blueocean.json')
.networkOff()
.expectJSON({ name: 'plugin', value: 'inaccessible' });
t.create('jacoco: 81% | valid coverage')
.get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
.reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: 81, percentageFloat: 80.5983, total: 49006 } })
)
.expectJSONTypes({ name: 'coverage', value: '81%' });
t.create('jacoco: inaccessible | request error')
.get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
.networkOff()
.expectJSONTypes({ name: 'coverage', value: 'inaccessible' });
t.create('jacoco: inaccessible | invalid coverage object')
.get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
.reply(200, { invalidCoverageObject: { covered: 39498, missed: 9508, percentage: 81, percentageFloat: 80.5983, total: 49006 } })
)
.expectJSONTypes({ name: 'coverage', value: 'inaccessible' });
t.create('jacoco: unknown | invalid coverage (non-numeric)')
.get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
.reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: 'non-numeric', percentageFloat: 80.5983, total: 49006 } })
)
.expectJSONTypes({ name: 'coverage', value: 'unknown' });
t.create('jacoco: unknown | exception handling')
.get('/j/https/updates.jenkins-ci.org/job/hello-project/job/master.json')
.intercept(nock => nock('https://updates.jenkins-ci.org')
.get('/job/hello-project/job/master/lastBuild/jacoco/api/json?tree=instructionCoverage[covered,missed,percentage,total]')
.reply(200, { instructionCoverage: { covered: 39498, missed: 9508, percentage: '81.x', percentageFloat: 80.5983, total: 49006 } })
)
.expectJSONTypes({ name: 'coverage', value: 'unknown' });