@@ -13,7 +13,7 @@ import {
13
13
RequestClientError ,
14
14
RequestNotFoundError ,
15
15
} from '../../../../errors' ;
16
- import type { IssueOrPullRequest } from '../../../../git/models/issueOrPullRequest' ;
16
+ import type { IssueOrPullRequest , IssueOrPullRequestType } from '../../../../git/models/issueOrPullRequest' ;
17
17
import type { PullRequest } from '../../../../git/models/pullRequest' ;
18
18
import type { Provider } from '../../../../git/models/remoteProvider' ;
19
19
import { showIntegrationRequestFailed500WarningMessage } from '../../../../messages' ;
@@ -23,8 +23,8 @@ import { Logger } from '../../../../system/logger';
23
23
import type { LogScope } from '../../../../system/logger.scope' ;
24
24
import { getLogScope } from '../../../../system/logger.scope' ;
25
25
import { maybeStopWatch } from '../../../../system/stopwatch' ;
26
- import type { BitbucketPullRequest } from './models' ;
27
- import { fromBitbucketPullRequest } from './models' ;
26
+ import type { BitbucketIssue , BitbucketPullRequest } from './models' ;
27
+ import { bitbucketIssueStateToState , fromBitbucketPullRequest } from './models' ;
28
28
29
29
export class BitbucketApi implements Disposable {
30
30
private readonly _disposable : Disposable ;
@@ -102,25 +102,69 @@ export class BitbucketApi implements Disposable {
102
102
id : string ,
103
103
options : {
104
104
baseUrl : string ;
105
+ type ?: IssueOrPullRequestType ;
105
106
} ,
106
107
) : Promise < IssueOrPullRequest | undefined > {
107
108
const scope = getLogScope ( ) ;
108
109
109
- const response = await this . request < BitbucketPullRequest > (
110
- provider ,
111
- token ,
112
- options . baseUrl ,
113
- `repositories/${ owner } /${ repo } /pullrequests/${ id } ?fields=*` ,
114
- {
115
- method : 'GET' ,
116
- } ,
117
- scope ,
118
- ) ;
110
+ if ( options ?. type !== 'issue' ) {
111
+ try {
112
+ const prResponse = await this . request < BitbucketPullRequest > (
113
+ provider ,
114
+ token ,
115
+ options . baseUrl ,
116
+ `repositories/${ owner } /${ repo } /pullrequests/${ id } ?fields=%2Bvalues.reviewers,%2Bvalues.participants` ,
117
+ {
118
+ method : 'GET' ,
119
+ } ,
120
+ scope ,
121
+ ) ;
119
122
120
- if ( ! response ) {
121
- return undefined ;
123
+ if ( prResponse ) {
124
+ return fromBitbucketPullRequest ( prResponse , provider ) ;
125
+ }
126
+ } catch ( ex ) {
127
+ if ( ex . original ?. status !== 404 ) {
128
+ Logger . error ( ex , scope ) ;
129
+ return undefined ;
130
+ }
131
+ }
122
132
}
123
- return fromBitbucketPullRequest ( response , provider ) ;
133
+
134
+ if ( options ?. type !== 'pullrequest' ) {
135
+ try {
136
+ const issueResponse = await this . request < BitbucketIssue > (
137
+ provider ,
138
+ token ,
139
+ options . baseUrl ,
140
+ `repositories/${ owner } /${ repo } /issues/${ id } ` ,
141
+ {
142
+ method : 'GET' ,
143
+ } ,
144
+ scope ,
145
+ ) ;
146
+
147
+ if ( issueResponse ) {
148
+ return {
149
+ id : issueResponse . id . toString ( ) ,
150
+ type : 'issue' ,
151
+ nodeId : issueResponse . id . toString ( ) ,
152
+ provider : provider ,
153
+ createdDate : new Date ( issueResponse . created_on ) ,
154
+ updatedDate : new Date ( issueResponse . updated_on ) ,
155
+ state : bitbucketIssueStateToState ( issueResponse . state ) ,
156
+ closed : issueResponse . state === 'closed' ,
157
+ title : issueResponse . title ,
158
+ url : issueResponse . links . html . href ,
159
+ } ;
160
+ }
161
+ } catch ( ex ) {
162
+ Logger . error ( ex , scope ) ;
163
+ return undefined ;
164
+ }
165
+ }
166
+
167
+ return undefined ;
124
168
}
125
169
126
170
private async request < T > (
@@ -192,22 +236,22 @@ export class BitbucketApi implements Disposable {
192
236
throw new RequestNotFoundError ( ex ) ;
193
237
case 401 : // Unauthorized
194
238
throw new AuthenticationError ( 'bitbucket' , AuthenticationErrorReason . Unauthorized , ex ) ;
195
- // TODO: Learn the Bitbucket API docs and put it in order:
196
- // case 403: // Forbidden
197
- // if (ex.message.includes('rate limit')) {
198
- // let resetAt: number | undefined;
199
-
200
- // const reset = ex.response?.headers?.get('x-ratelimit-reset');
201
- // if (reset != null) {
202
- // resetAt = parseInt(reset, 10);
203
- // if (Number.isNaN(resetAt)) {
204
- // resetAt = undefined;
205
- // }
206
- // }
207
-
208
- // throw new RequestRateLimitError(ex, token, resetAt);
209
- // }
210
- // throw new AuthenticationError('bitbucket', AuthenticationErrorReason.Forbidden, ex);
239
+ case 403 : // Forbidden
240
+ // TODO: Learn the Bitbucket API docs and put it in order:
241
+ // if (ex.message.includes('rate limit')) {
242
+ // let resetAt: number | undefined;
243
+
244
+ // const reset = ex.response?.headers?.get('x-ratelimit-reset');
245
+ // if (reset != null) {
246
+ // resetAt = parseInt(reset, 10);
247
+ // if (Number.isNaN(resetAt)) {
248
+ // resetAt = undefined;
249
+ // }
250
+ // }
251
+
252
+ // throw new RequestRateLimitError(ex, token, resetAt);
253
+ // }
254
+ throw new AuthenticationError ( 'bitbucket' , AuthenticationErrorReason . Forbidden , ex ) ;
211
255
case 500 : // Internal Server Error
212
256
Logger . error ( ex , scope ) ;
213
257
if ( ex . response != null ) {
0 commit comments