1+ import { RepositoryAccessLevel } from '../../../../git/models/issue' ;
12import type { IssueOrPullRequestState } from '../../../../git/models/issueOrPullRequest' ;
2- import { PullRequest } from '../../../../git/models/pullRequest' ;
3+ import type { PullRequestMember , PullRequestReviewer } from '../../../../git/models/pullRequest' ;
4+ import {
5+ PullRequest ,
6+ PullRequestMergeableState ,
7+ PullRequestReviewDecision ,
8+ PullRequestReviewState ,
9+ } from '../../../../git/models/pullRequest' ;
310import type { Provider } from '../../../../git/models/remoteProvider' ;
411
512export type AzureWorkItemStateCategory = 'Proposed' | 'InProgress' | 'Resolved' | 'Completed' | 'Removed' ;
@@ -36,15 +43,24 @@ export interface AzureUser {
3643 id : string ;
3744 uniqueName : string ;
3845 imageUrl : string ;
39- descriptor : string ;
46+ descriptor ? : string ;
4047}
4148
4249export interface AzureUserWithVote extends AzureUser {
43- isFlagged : boolean ;
44- isReapprove : boolean ;
45- isRequired : boolean ;
50+ isFlagged ?: boolean ;
51+ hasDeclined ?: boolean ;
52+ isReapprove ?: boolean ;
53+ isRequired ?: boolean ;
54+ vote ?: AzurePullRequestVote ;
4655}
4756
57+ export type AzurePullRequestVote =
58+ | 10 // approved
59+ | 5 // approved with suggestions
60+ | 0 // no vote
61+ | - 5 // waiting for author
62+ | - 10 ; // rejected
63+
4864export interface AzureWorkItemCommentVersionRef {
4965 commentId : number ;
5066 createdInRevision : number ;
@@ -133,19 +149,6 @@ export interface AzureProject {
133149 lastUpdateTime : string ;
134150}
135151
136- export type AzureProjectState = 'createPending' | 'deleted' | 'deleting' | 'new' | 'unchanged' | 'wellFormed' ;
137- export type AzureProjectVisibility = 'private' | 'public' ;
138-
139- export interface AzureProject {
140- id : string ;
141- name : string ;
142- url : string ;
143- state : AzureProjectState ;
144- revision : number ;
145- visibility : AzureProjectVisibility ;
146- lastUpdateTime : string ;
147- }
148-
149152export interface AzureRepository {
150153 id : string ;
151154 name : string ;
@@ -238,10 +241,13 @@ export interface AzurePullRequest {
238241 closedBy ?: AzureUser ; // Can be missed even if closedDate is presented.
239242 title : string ;
240243 description : string ;
244+ forkSource ?: AzureGitForkRef ;
241245 sourceRefName : string ;
242246 targetRefName : string ;
243247 isDraft : boolean ;
244248 mergeId : string ;
249+ mergeStatus ?: AzurePullRequestAsyncStatus ;
250+ lastMergeCommit ?: AzureGitCommitRef ;
245251 lastMergeSourceCommit : AzureGitCommitRef ;
246252 lastMergeTargetCommit : AzureGitCommitRef ;
247253 reviewers : AzureUserWithVote [ ] ;
@@ -267,14 +273,11 @@ export interface AzurePullRequestWithLinks extends AzurePullRequest {
267273 commits ?: AzureGitCommitRef [ ] ;
268274 completionOptions ?: AzurePullRequestCompletionOptions ;
269275 completionQueueTime ?: string ;
270- forkSource ?: AzureGitForkRef ;
271276 hasMultipleMergeBases ?: boolean ;
272277 labels ?: AzureWebApiTagDefinition [ ] ;
273- lastMergeCommit ?: AzureGitCommitRef ;
274278 mergeFailureMessage ?: string ;
275279 mergeFailureType ?: 'caseSensitive' | 'none' | 'objectTooLarge' | 'unknown' ;
276280 mergeOptions ?: AzureGitPullRequestMergeOptions ;
277- mergeStatus ?: AzurePullRequestAsyncStatus ;
278281 remoteUrl ?: string ;
279282 workItemRefs ?: AzureResourceRef [ ] ;
280283}
@@ -306,7 +309,91 @@ export function getAzurePullRequestWebUrl(pr: AzurePullRequest): string {
306309 return `${ baseUrl } /${ owner } /${ repoPath } /pullrequest/${ pr . pullRequestId } ` ;
307310}
308311
309- export function fromAzurePullRequest ( pr : AzurePullRequest , provider : Provider ) : PullRequest {
312+ export function fromAzurePullRequestMergeStatusToMergeableState (
313+ mergeStatus : AzurePullRequestAsyncStatus ,
314+ ) : PullRequestMergeableState {
315+ switch ( mergeStatus ) {
316+ case 'conflicts' :
317+ return PullRequestMergeableState . Conflicting ;
318+ case 'failure' :
319+ return PullRequestMergeableState . FailingChecks ;
320+ case 'rejectedByPolicy' :
321+ return PullRequestMergeableState . BlockedByPolicy ;
322+ case 'succeeded' :
323+ return PullRequestMergeableState . Mergeable ;
324+ case 'notSet' :
325+ case 'queued' :
326+ default :
327+ return PullRequestMergeableState . Unknown ;
328+ }
329+ }
330+
331+ export function fromAzurePullRequestVoteToReviewState ( vote : AzurePullRequestVote ) : PullRequestReviewState {
332+ switch ( vote ) {
333+ case 10 :
334+ case 5 :
335+ return PullRequestReviewState . Approved ;
336+ case 0 :
337+ return PullRequestReviewState . ReviewRequested ;
338+ case - 5 :
339+ case - 10 :
340+ return PullRequestReviewState . ChangesRequested ;
341+ default :
342+ return PullRequestReviewState . ReviewRequested ;
343+ }
344+ }
345+
346+ export function fromAzureUserWithVoteToReviewer ( reviewer : AzureUserWithVote ) : PullRequestReviewer {
347+ return {
348+ isCodeOwner : undefined ,
349+ reviewer : {
350+ avatarUrl : reviewer . imageUrl ,
351+ id : reviewer . id ,
352+ name : reviewer . displayName ,
353+ url : reviewer . url ,
354+ } ,
355+ state : fromAzurePullRequestVoteToReviewState ( reviewer . vote ?? 0 ) ,
356+ } ;
357+ }
358+
359+ export function getAzurePullRequestReviewDecision (
360+ votes : AzurePullRequestVote [ ] ,
361+ ) : PullRequestReviewDecision | undefined {
362+ const reviewStates = votes . map ( vote => fromAzurePullRequestVoteToReviewState ( vote ) ) ;
363+ if ( reviewStates . includes ( PullRequestReviewState . ChangesRequested ) ) {
364+ return PullRequestReviewDecision . ChangesRequested ;
365+ }
366+
367+ if ( reviewStates . includes ( PullRequestReviewState . ReviewRequested ) ) {
368+ return PullRequestReviewDecision . ReviewRequired ;
369+ }
370+
371+ if ( reviewStates . includes ( PullRequestReviewState . Approved ) ) {
372+ return PullRequestReviewDecision . Approved ;
373+ }
374+
375+ return undefined ;
376+ }
377+
378+ export function fromAzureReviewerToPullRequestMember ( reviewer : AzureUser ) : PullRequestMember {
379+ return {
380+ avatarUrl : reviewer . imageUrl ,
381+ id : reviewer . id ,
382+ name : reviewer . displayName ,
383+ url : reviewer . url ,
384+ } ;
385+ }
386+
387+ function normalizeAzureBranchName ( branchName : string ) : string {
388+ return branchName . startsWith ( 'refs/heads/' ) ? branchName . replace ( 'refs/heads/' , '' ) : branchName ;
389+ }
390+
391+ export function fromAzurePullRequest (
392+ pr : AzurePullRequest ,
393+ provider : Provider ,
394+ orgName : string ,
395+ projectName : string ,
396+ ) : PullRequest {
310397 const url = new URL ( pr . url ) ;
311398 return new PullRequest (
312399 provider ,
@@ -322,10 +409,52 @@ export function fromAzurePullRequest(pr: AzurePullRequest, provider: Provider):
322409 getAzurePullRequestWebUrl ( pr ) ,
323410 {
324411 owner : getAzureOwner ( url ) ,
325- repo : getAzureRepo ( pr ) ,
412+ repo : pr . repository . name ,
413+ id : pr . repository . id ,
414+ // TODO: Remove this assumption once actual access level is available
415+ accessLevel : RepositoryAccessLevel . Write ,
326416 } ,
327417 azurePullRequestStatusToState ( pr . status ) ,
328418 new Date ( pr . creationDate ) ,
329- new Date ( pr . creationDate ) ,
419+ new Date ( pr . closedDate || pr . creationDate ) ,
420+ pr . closedDate ? new Date ( pr . closedDate ) : undefined ,
421+ pr . closedDate && pr . status === 'completed' ? new Date ( pr . closedDate ) : undefined ,
422+ fromAzurePullRequestMergeStatusToMergeableState ( pr . mergeStatus ?? 'notSet' ) ,
423+ undefined ,
424+ {
425+ base : {
426+ branch : pr . targetRefName ? normalizeAzureBranchName ( pr . targetRefName ) : '' ,
427+ sha : pr . lastMergeTargetCommit ?. commitId ?? '' ,
428+ repo : pr . repository . name ,
429+ owner : getAzureOwner ( url ) ,
430+ exists : pr . targetRefName != null ,
431+ url : pr . repository . webUrl ,
432+ } ,
433+ head : {
434+ branch : pr . sourceRefName ? normalizeAzureBranchName ( pr . sourceRefName ) : '' ,
435+ sha : pr . lastMergeSourceCommit ?. commitId ?? '' ,
436+ repo : pr . forkSource ?. repository != null ? pr . forkSource . repository . name : pr . repository . name ,
437+ owner : getAzureOwner ( url ) ,
438+ exists : pr . sourceRefName != null ,
439+ url : pr . forkSource ?. repository != null ? pr . forkSource . repository . webUrl : pr . repository . webUrl ,
440+ } ,
441+ isCrossRepository : pr . forkSource != null ,
442+ } ,
443+ pr . isDraft ,
444+ undefined ,
445+ undefined ,
446+ undefined ,
447+ undefined ,
448+ getAzurePullRequestReviewDecision ( pr . reviewers ?. filter ( r => r . isRequired ) . map ( r => r . vote ?? 0 ) ?? [ ] ) ,
449+ pr . reviewers . filter ( r => r . vote == null || r . vote === 0 ) . map ( r => fromAzureUserWithVoteToReviewer ( r ) ) ,
450+ pr . reviewers . filter ( r => r . vote != null && r . vote !== 0 ) . map ( r => fromAzureUserWithVoteToReviewer ( r ) ) ,
451+ pr . reviewers . map ( r => fromAzureReviewerToPullRequestMember ( r ) ) ,
452+ undefined ,
453+ {
454+ id : pr . repository ?. project ?. id ,
455+ name : projectName ,
456+ resourceId : '' , // TODO: This is a workaround until we can get the org id here.
457+ resourceName : orgName ,
458+ } ,
330459 ) ;
331460}
0 commit comments