22
33'use strict' ;
44
5- const Fusebox = require ( 'circuit-fuses' ) . breaker ;
5+ const Breaker = require ( 'circuit-fuses' ) . breaker ;
66const Scm = require ( 'screwdriver-scm-base' ) ;
77const hoek = require ( '@hapi/hoek' ) ;
88const joi = require ( 'joi' ) ;
99const Path = require ( 'path' ) ;
1010const Url = require ( 'url' ) ;
11- const request = require ( 'request' ) ;
11+ const request = require ( 'screwdriver- request' ) ;
1212const schema = require ( 'screwdriver-data-schema' ) ;
1313const API_URL_V2 = 'https://api.bitbucket.org/2.0' ;
1414const REPO_URL = `${ API_URL_V2 } /repositories` ;
@@ -28,37 +28,6 @@ const STATE_MAP = {
2828} ;
2929const WEBHOOK_PAGE_SIZE = 30 ;
3030
31- /**
32- * Check the status code of the server's response.
33- *
34- * If there was an error encountered with the request, this will format a human-readable
35- * error message.
36- * @method checkResponseError
37- * @param {HTTPResponse } response HTTP Response from `request` call
38- * @param {Number } response.statusCode HTTP status code of the HTTP request
39- * @param {String } [response.body.error.message] Error message from the server
40- * @param {String } [response.body.error.detail.required] Error resolution message
41- * @return {Promise } Resolves when no error encountered
42- * Rejects when status code is non-200
43- */
44- function checkResponseError ( response ) {
45- if ( response . statusCode >= 200 && response . statusCode < 300 ) {
46- return ;
47- }
48-
49- const errorMessage = hoek . reach ( response , 'body.error.message' , {
50- default : `SCM service unavailable (${ response . statusCode } ).`
51- } ) ;
52- const errorReason = hoek . reach ( response , 'body.error.detail' , {
53- default : JSON . stringify ( response . body )
54- } ) ;
55-
56- const error = new Error ( `${ errorMessage } Reason "${ errorReason } "` ) ;
57-
58- error . status = response . statusCode ;
59- throw error ;
60- }
61-
6231/**
6332 * Get repo information
6433 * @method getRepoInfo
@@ -101,6 +70,33 @@ function getScmUriParts(scmUri) {
10170}
10271
10372class BitbucketScm extends Scm {
73+ /**
74+ * Bitbucket command to run
75+ * @method _gitlabCommand
76+ * @param {Object } options An object that tells what command & params to run
77+ * @param {Object } [options.json] Body for request to make
78+ * @param {String } options.method Bitbucket method. For example: get
79+ * @param {String } options.route Route for gitlab.request()
80+ * @param {String } options.token Bitbucket token used for authentication of requests
81+ * @param {Function } callback Callback function from gitlab API
82+ */
83+ _bitbucketCommand ( options , callback ) {
84+ const config = options ;
85+
86+ // Everything else goes into context
87+ config . context = {
88+ token : options . token
89+ } ;
90+ delete config . token ;
91+
92+ request ( config )
93+ . then ( function cb ( ) {
94+ // Use "function" (not "arrow function") for getting "arguments"
95+ callback ( null , ...arguments ) ;
96+ } )
97+ . catch ( err => callback ( err ) ) ;
98+ }
99+
104100 /**
105101 * Constructor for Scm
106102 * @method constructor
@@ -155,7 +151,13 @@ class BitbucketScm extends Scm {
155151 'Invalid config for Bitbucket'
156152 ) ;
157153
158- this . breaker = new Fusebox ( request , this . config . fusebox ) ;
154+ // eslint-disable-next-line no-underscore-dangle
155+ this . breaker = new Breaker ( this . _bitbucketCommand . bind ( this ) , {
156+ // Do not retry when there is a 4XX error
157+ shouldRetry : err => err && err . status && ! ( err . status >= 400 && err . status < 500 ) ,
158+ retry : this . config . fusebox . retry ,
159+ breaker : this . config . fusebox . breaker
160+ } ) ;
159161
160162 // TODO: set fixed value temporarily.
161163 // need to change if the other bitbucket host is supported.
@@ -202,16 +204,11 @@ class BitbucketScm extends Scm {
202204 async _findWebhook ( { page, repoId, token : configToken , url } ) {
203205 const token = await this . _getToken ( ) ;
204206 const response = await this . breaker . runCommand ( {
205- json : true ,
206207 method : 'GET' ,
207- auth : {
208- bearer : token
209- } ,
210- url : `${ API_URL_V2 } /repositories/${ repoId } /hooks?pagelen=30&page=${ page } `
208+ token,
209+ url : `${ REPO_URL } /${ repoId } /hooks?pagelen=30&page=${ page } `
211210 } ) ;
212211
213- checkResponseError ( response ) ;
214-
215212 const hooks = response . body ;
216213 const result = hooks . values . find ( webhook => webhook . url === url ) ;
217214
@@ -244,7 +241,7 @@ class BitbucketScm extends Scm {
244241 */
245242 _createWebhook ( { hookInfo, repoId, token, url, actions } ) {
246243 const params = {
247- body : {
244+ json : {
248245 description : 'Screwdriver-CD build trigger' ,
249246 url,
250247 active : true ,
@@ -259,20 +256,17 @@ class BitbucketScm extends Scm {
259256 ]
260257 : actions
261258 } ,
262- json : true ,
263259 method : 'POST' ,
264- auth : {
265- bearer : token
266- } ,
267- url : `${ API_URL_V2 } /repositories/${ repoId } /hooks`
260+ token,
261+ url : `${ REPO_URL } /${ repoId } /hooks`
268262 } ;
269263
270264 if ( hookInfo ) {
271265 params . url = `${ params . url } /${ hookInfo . uuid } ` ;
272266 params . method = 'PUT' ;
273267 }
274268
275- return this . breaker . runCommand ( params ) . then ( checkResponseError ) ;
269+ return this . breaker . runCommand ( params ) ;
276270 }
277271
278272 /**
@@ -330,10 +324,7 @@ class BitbucketScm extends Scm {
330324 const options = {
331325 url : branchUrl ,
332326 method : 'GET' ,
333- json : true ,
334- auth : {
335- bearer : token
336- }
327+ token
337328 } ;
338329
339330 if ( hostname !== this . hostname ) {
@@ -429,10 +420,7 @@ class BitbucketScm extends Scm {
429420 const options = {
430421 url : `${ USER_URL } /${ encodeURIComponent ( username ) } ` ,
431422 method : 'GET' ,
432- json : true ,
433- auth : {
434- bearer : token
435- }
423+ token
436424 } ;
437425
438426 const response = await this . breaker . runCommand ( options ) ;
@@ -478,10 +466,7 @@ class BitbucketScm extends Scm {
478466 const options = {
479467 url : `${ REPO_URL } /${ repoId } ` ,
480468 method : 'GET' ,
481- json : true ,
482- auth : {
483- bearer : token
484- }
469+ token
485470 } ;
486471
487472 const response = await this . breaker . runCommand ( options ) ;
@@ -514,10 +499,7 @@ class BitbucketScm extends Scm {
514499 const options = {
515500 url : `${ REPO_URL } /${ scm . repoId } /commit/${ sha } ` ,
516501 method : 'GET' ,
517- json : true ,
518- auth : {
519- bearer : token
520- }
502+ token
521503 } ;
522504
523505 const response = await this . breaker . runCommand ( options ) ;
@@ -558,15 +540,14 @@ class BitbucketScm extends Scm {
558540 const options = {
559541 url : branchUrl ,
560542 method : 'GET' ,
561- json : true ,
562- auth : {
563- bearer : token
564- }
543+ token
565544 } ;
566545
567546 const response = await this . breaker . runCommand ( options ) ;
568547
569- checkResponseError ( response ) ;
548+ if ( response . statusCode !== 200 ) {
549+ throw new Error ( `STATUS CODE ${ response . statusCode } : ${ JSON . stringify ( response . body ) } ` ) ;
550+ }
570551
571552 return response . body . target . hash ;
572553 }
@@ -579,7 +560,7 @@ class BitbucketScm extends Scm {
579560 * @param {String } config.type Can be 'pr' or 'repo'
580561 * @param {Object } config.webhookPayload The webhook payload received from the
581562 * SCM service.
582- * @param {String } config.token Service token to authenticate with Github
563+ * @param {String } config.token Service token to authenticate with Bitbucket
583564 * @return {Promise } Resolves to the content of the file
584565 */
585566 _getChangedFiles ( ) {
@@ -600,15 +581,12 @@ class BitbucketScm extends Scm {
600581 const { branch : branchFromScmUri , repoId, rootDir } = getScmUriParts ( scmUri ) ;
601582 const branch = ref || branchFromScmUri ;
602583 const fullPath = rootDir ? Path . join ( rootDir , path ) : path ;
603- const fileUrl = `${ API_URL_V2 } /repositories /${ repoId } /src/${ branch } /${ fullPath } ` ;
584+ const fileUrl = `${ REPO_URL } /${ repoId } /src/${ branch } /${ fullPath } ` ;
604585 const token = await this . _getToken ( ) ;
605586 const options = {
606587 url : fileUrl ,
607588 method : 'GET' ,
608- json : true ,
609- auth : {
610- bearer : token
611- }
589+ token
612590 } ;
613591
614592 const response = await this . breaker . runCommand ( options ) ;
@@ -634,25 +612,17 @@ class BitbucketScm extends Scm {
634612 const token = await this . _getToken ( ) ;
635613
636614 // First, check to see if the repository exists
637- await this . breaker
638- . runCommand ( {
639- url : `${ API_URL_V2 } /repositories/${ owner } /${ uuid } ` ,
640- method : 'GET' ,
641- json : true ,
642- auth : {
643- bearer : token
644- }
645- } )
646- . then ( checkResponseError ) ;
615+ await this . breaker . runCommand ( {
616+ url : `${ REPO_URL } /${ owner } /${ uuid } ` ,
617+ method : 'GET' ,
618+ token
619+ } ) ;
647620
648621 const getPerm = async desiredAccess => {
649622 const options = {
650- url : `${ API_URL_V2 } /repositories /${ owner } ?q=uuid%3D%22${ uuid } %22` ,
623+ url : `${ REPO_URL } /${ owner } ?q=uuid%3D%22${ uuid } %22` ,
651624 method : 'GET' ,
652- json : true ,
653- auth : {
654- bearer : token
655- }
625+ token
656626 } ;
657627
658628 if ( desiredAccess === 'admin' ) {
@@ -705,16 +675,13 @@ class BitbucketScm extends Scm {
705675 const options = {
706676 url : `${ REPO_URL } /${ scm . repoId } /commit/${ sha } /statuses/build` ,
707677 method : 'POST' ,
708- json : true ,
709- body : {
678+ json : {
710679 url,
711680 state : STATE_MAP [ buildStatus ] ,
712681 key : sha ,
713682 description : context
714683 } ,
715- auth : {
716- bearer : decodeURIComponent ( token )
717- }
684+ token : decodeURIComponent ( token )
718685 } ;
719686
720687 return this . breaker . runCommand ( options ) . then ( response => {
@@ -891,16 +858,11 @@ class BitbucketScm extends Scm {
891858 const token = await this . _getToken ( ) ;
892859
893860 const response = await this . breaker . runCommand ( {
894- url : `${ API_URL_V2 } /repositories /${ repoId } /pullrequests` ,
861+ url : `${ REPO_URL } /${ repoId } /pullrequests` ,
895862 method : 'GET' ,
896- json : true ,
897- auth : {
898- bearer : token
899- }
863+ token
900864 } ) ;
901865
902- checkResponseError ( response ) ;
903-
904866 const prList = response . body . values ;
905867
906868 return prList . map ( pr => ( {
@@ -923,16 +885,11 @@ class BitbucketScm extends Scm {
923885 const token = await this . _getToken ( ) ;
924886
925887 const response = await this . breaker . runCommand ( {
926- url : `${ API_URL_V2 } /repositories /${ repoId } /pullrequests/${ prNum } ` ,
888+ url : `${ REPO_URL } /${ repoId } /pullrequests/${ prNum } ` ,
927889 method : 'GET' ,
928- json : true ,
929- auth : {
930- bearer : token
931- }
890+ token
932891 } ) ;
933892
934- checkResponseError ( response ) ;
935-
936893 const pr = response . body ;
937894
938895 return {
@@ -1001,14 +958,9 @@ class BitbucketScm extends Scm {
1001958 async _findBranches ( config ) {
1002959 const token = await this . _getToken ( ) ;
1003960 const response = await this . breaker . runCommand ( {
1004- json : true ,
1005961 method : 'GET' ,
1006- auth : {
1007- bearer : token
1008- } ,
1009- url :
1010- `${ API_URL_V2 } /repositories/${ config . repoId } ` +
1011- `/refs/branches?pagelen=${ BRANCH_PAGE_SIZE } &page=${ config . page } `
962+ token,
963+ url : `${ REPO_URL } /${ config . repoId } /refs/branches?pagelen=${ BRANCH_PAGE_SIZE } &page=${ config . page } `
1012964 } ) ;
1013965
1014966 let branches = hoek . reach ( response , 'body.values' ) ;
@@ -1024,11 +976,11 @@ class BitbucketScm extends Scm {
1024976 }
1025977
1026978 /**
1027- * Get branch list from the Github repository
979+ * Get branch list from the Bitbucket repository
1028980 * @async _getBranchList
1029981 * @param {Object } config
1030982 * @param {String } config.scmUri The SCM URI to get branch list
1031- * @param {String } config.token Service token to authenticate with Github
983+ * @param {String } config.token Service token to authenticate with Bitbucket
1032984 * @return {Promise } Resolves when complete
1033985 */
1034986 async _getBranchList ( { scmUri, token } ) {
@@ -1066,10 +1018,8 @@ class BitbucketScm extends Scm {
10661018 async _refreshToken ( ) {
10671019 const params = {
10681020 method : 'POST' ,
1069- auth : {
1070- user : this . config . oauthClientId ,
1071- pass : this . config . oauthClientSecret
1072- } ,
1021+ username : this . config . oauthClientId ,
1022+ password : this . config . oauthClientSecret ,
10731023 url : `https://${ this . hostname } /site/oauth2/access_token` ,
10741024 form : { }
10751025 } ;
0 commit comments