[Bitbucket] #1509 - Add Bitbucket Pipelines service (#1510)

* [Bitbucket] #1509 - Add Bitbucket Pipelines service

* Use ES6 const and error helper
This commit is contained in:
Patrick Streule
2018-02-20 07:33:09 +11:00
committed by Danial
parent 75503ec514
commit 57c7279540
3 changed files with 187 additions and 2 deletions

View File

@@ -212,6 +212,14 @@ const allBadgeExamples = [
title: 'Jenkins coverage',
previewUri: '/jenkins/c/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'
},
{
title: 'Bitbucket Pipelines branch',
previewUri: '/bitbucket/pipelines/atlassian/adf-builder-javascript/task/SECO-2168.svg'
},
{
title: 'Coveralls github',
previewUri: '/coveralls/github/jekyll/jekyll.svg'

View File

@@ -4458,6 +4458,67 @@ cache(function(data, match, sendBadge, request) {
});
}));
// Bitbucket Pipelines integration.
camp.route(/^\/bitbucket\/pipelines\/([^/]+)\/([^/]+)(?:\/(.+))?\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {
const user = match[1]; // eg, atlassian
const repo = match[2]; // eg, adf-builder-javascript
const branch = match[3] || 'master'; // eg, development
const format = match[4];
const apiUrl = 'https://api.bitbucket.org/2.0/repositories/'
+ encodeURIComponent(user) + '/' + encodeURIComponent(repo)
+ '/pipelines/?fields=values.state&page=1&pagelen=2&sort=-created_on'
+ '&target.ref_type=BRANCH&target.ref_name=' + encodeURIComponent(branch);
const badgeData = getBadgeData('build', data);
request(apiUrl, function(err, res, buffer) {
if (checkErrorResponse(badgeData, err, res)) {
sendBadge(format, badgeData);
return;
}
try {
const data = JSON.parse(buffer);
if (!data.values) {
throw Error('Unexpected response');
}
const values = data.values.filter(value => value.state && value.state.name === 'COMPLETED');
if (values.length > 0) {
switch (values[0].state.result.name) {
case 'SUCCESSFUL':
badgeData.text[1] = 'passing';
badgeData.colorscheme = 'brightgreen';
break;
case 'FAILED':
badgeData.text[1] = 'failing';
badgeData.colorscheme = 'red';
break;
case 'ERROR':
badgeData.text[1] = 'error';
badgeData.colorscheme = 'red';
break;
case 'STOPPED':
badgeData.text[1] = 'stopped';
badgeData.colorscheme = 'yellow';
break;
case 'EXPIRED':
badgeData.text[1] = 'expired';
badgeData.colorscheme = 'yellow';
break;
default:
badgeData.text[1] = 'unknown';
}
} else {
badgeData.text[1] = 'never built';
}
sendBadge(format, badgeData);
} catch(e) {
badgeData.text[1] = 'invalid';
sendBadge(format, badgeData);
}
});
}));
// Chef cookbook integration.
camp.route(/^\/cookbook\/v\/(.*)\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {

View File

@@ -6,8 +6,9 @@ const {
isMetric,
isMetricOpenIssues
} = require('./helpers/validators.js');
const { invalidJSON } = require('./helpers/response-fixtures');
const t = new ServiceTester({ id: 'bitbucket', title: 'BitBucket badges' });
const t = new ServiceTester({ id: 'bitbucket', title: 'Bitbucket badges' });
module.exports = t;
@@ -76,7 +77,7 @@ t.create('pr-raw (connection error)')
.networkOff()
.expectJSON({ name: 'pull requests', value: 'inaccessible' });
t.create('pr (valid)')
t.create('pr (valid)')
.get('/pr/atlassian/python-bitbucket.json')
.expectJSONTypes(Joi.object().keys({
name: 'pull requests',
@@ -95,3 +96,118 @@ t.create('pr (connection error)')
.get('/pr/atlassian/python-bitbucket.json')
.networkOff()
.expectJSON({ name: 'pull requests', value: 'inaccessible' });
// tests for Bitbucket Pipelines
function bitbucketApiResponse(status) {
return JSON.stringify({
"values": [
{
"state": {
"type": "pipeline_state_completed",
"name": "COMPLETED",
"result": {
"type": "pipeline_state_completed_xyz",
"name": status
}
}
}
]
});
}
t.create('master build result (valid)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.expectJSONTypes(Joi.object().keys({
name: 'build',
value: Joi.equal('failing', 'passing', 'error', 'stopped', 'expired')
}));
t.create('master build result (not found)')
.get('/pipelines/atlassian/not-a-repo.json')
.expectJSON({ name: 'build', value: 'not found' })
t.create('branch build result (valid)')
.get('/pipelines/atlassian/adf-builder-javascript/shields-test-dont-remove.json')
.expectJSONTypes(Joi.object().keys({
name: 'build',
value: Joi.equal('failing', 'passing', 'error', 'stopped', 'expired')
}));
t.create('branch build result (not found)')
.get('/pipelines/atlassian/not-a-repo/some-branch.json')
.expectJSON({ name: 'build', value: 'not found' })
t.create('branch build result (never built)')
.get('/pipelines/atlassian/adf-builder-javascript/some/new/branch.json')
.expectJSON({ name: 'build', value: 'never built' })
t.create('build result (passing)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('SUCCESSFUL'))
)
.expectJSON({ name: 'build', value: 'passing' })
t.create('build result (failing)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('FAILED'))
)
.expectJSON({ name: 'build', value: 'failing' })
t.create('build result (error)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('ERROR'))
)
.expectJSON({ name: 'build', value: 'error' })
t.create('build result (stopped)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('STOPPED'))
)
.expectJSON({ name: 'build', value: 'stopped' })
t.create('build result (expired)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('EXPIRED'))
)
.expectJSON({ name: 'build', value: 'expired' })
t.create('build result (unknown)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, bitbucketApiResponse('NEW_AND_UNEXPECTED'))
)
.expectJSON({ name: 'build', value: 'unknown' })
t.create('build result (empty json)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(200, '{}')
)
.expectJSON({ name: 'build', value: 'invalid' })
t.create('build result (invalid json)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.intercept(nock => nock('https://api.bitbucket.org')
.get(/^\/2.0\/.*/)
.reply(invalidJSON)
)
.expectJSON({ name: 'build', value: 'invalid' })
t.create('build result (network error)')
.get('/pipelines/atlassian/adf-builder-javascript.json')
.networkOff()
.expectJSON({ name: 'build', value: 'inaccessible' });