55using Microsoft . Build . Framework ;
66using Microsoft . DotNet . VersionTools . Automation ;
77using Microsoft . DotNet . VersionTools . Automation . GitHubApi ;
8+ using Microsoft . DotNet . VersionTools . Automation . VstsApi ;
9+ using System ;
810using System . Diagnostics ;
911using System . Linq ;
1012
@@ -13,12 +15,47 @@ namespace Microsoft.DotNet.Build.Tasks.VersionTools
1315 public class SubmitPullRequest : BuildTask
1416 {
1517 [ Required ]
16- public string GitHubAuthToken { get ; set ; }
18+ public string PullRequestServiceType { get ; set ; }
19+
20+ [ Required ]
21+ public string PullRequestAuthToken { get ; set ; }
22+
23+ /// <summary>
24+ /// The name of the user creating this PR. Used as the default for PullRequestAuthor.
25+ ///
26+ /// For GitHub, this locates the dev (origin) fork.
27+ ///
28+ /// For VSTS, this is only used as a default for PullRequestAuthor. (PullRequestAuthToken is
29+ /// used to fetch the calling user's GUID from VSTS. The GUID is used to search for existing
30+ /// PRs, like GitHub username is used to find GitHub PRs. However, VSTS user GUID isn't a
31+ /// good commit author, so the caller must provide a friendly name.)
32+ /// </summary>
1733 [ Required ]
18- public string GitHubUser { get ; set ; }
34+ public string PullRequestUser { get ; set ; }
35+
36+ /// <summary>
37+ /// Sets the Git author for the update commit. Defaults to PullRequestUser's value.
38+ /// </summary>
39+ public string PullRequestAuthor { get ; set ; }
40+
41+ /// <summary>
42+ /// Sets the Git author's email for the update commit.
43+ /// </summary>
1944 [ Required ]
20- public string GitHubEmail { get ; set ; }
45+ public string PullRequestEmail { get ; set ; }
46+
47+ /// <summary>
48+ /// Required for VSTS PullRequestServiceType. Used to find the VSTS repository.
49+ /// </summary>
50+ public string VstsInstanceName { get ; set ; }
2151
52+ public string VstsApiVersionOverride { get ; set ; }
53+
54+ /// <summary>
55+ /// For GitHub, the upstream repository owner. Defaults to 'dotnet'.
56+ ///
57+ /// For VSTS, the project containing the repo.
58+ /// </summary>
2259 public string ProjectRepoOwner { get ; set ; }
2360
2461 [ Required ]
@@ -34,17 +71,12 @@ public class SubmitPullRequest : BuildTask
3471 public string Title { get ; set ; }
3572
3673 /// <summary>
37- /// Body of the pull request. Optional.
74+ /// Body/description of the pull request. Optional.
3875 ///
39- /// Only used when submitting a new pull request or if TrackDiscardedCommits is false .
76+ /// This will overwrite the current PR body if updating a PR .
4077 /// </summary>
4178 public string Body { get ; set ; }
4279
43- /// <summary>
44- /// The git author of the update commit. Defaults to the same as GitHubUser.
45- /// </summary>
46- public string GitHubAuthor { get ; set ; }
47-
4880 public ITaskItem [ ] NotifyGitHubUsers { get ; set ; }
4981
5082 public bool AlwaysCreateNewPullRequest { get ; set ; }
@@ -61,12 +93,11 @@ public override bool Execute()
6193
6294 private void TraceListenedExecute ( )
6395 {
64- var auth = new GitHubAuth ( GitHubAuthToken , GitHubUser , GitHubEmail ) ;
96+ // GitHub and VSTS have different dev flow conventions.
97+ GitHubProject origin ;
6598
66- using ( GitHubClient client = new GitHubClient ( auth ) )
99+ using ( IGitHubClient client = CreateClient ( out origin ) )
67100 {
68- var origin = new GitHubProject ( ProjectRepoName , GitHubUser ) ;
69-
70101 var upstreamBranch = new GitHubBranch (
71102 ProjectRepoBranch ,
72103 new GitHubProject ( ProjectRepoName , ProjectRepoOwner ) ) ;
@@ -78,19 +109,61 @@ private void TraceListenedExecute()
78109 body += PullRequestCreator . NotificationString ( NotifyGitHubUsers . Select ( item => item . ItemSpec ) ) ;
79110 }
80111
81- var prCreator = new PullRequestCreator ( client . Auth , GitHubAuthor ) ;
112+ var options = new PullRequestOptions
113+ {
114+ ForceCreate = AlwaysCreateNewPullRequest ,
115+ MaintainersCanModify = MaintainersCanModifyPullRequest ,
116+ TrackDiscardedCommits = TrackDiscardedCommits
117+ } ;
118+
119+ var prCreator = new PullRequestCreator ( client . Auth , PullRequestAuthor ) ;
82120 prCreator . CreateOrUpdateAsync (
83121 CommitMessage ,
84122 CommitMessage + $ " ({ ProjectRepoBranch } )",
85123 body ,
86124 upstreamBranch ,
87125 origin ,
88- new PullRequestOptions
126+ options ,
127+ client ) . Wait ( ) ;
128+ }
129+ }
130+
131+ private IGitHubClient CreateClient ( out GitHubProject origin )
132+ {
133+ PullRequestServiceType type ;
134+ if ( ! Enum . TryParse ( PullRequestServiceType , true , out type ) )
135+ {
136+ string options = string . Join ( ", " , Enum . GetNames ( typeof ( PullRequestServiceType ) ) ) ;
137+ throw new ArgumentException (
138+ $ "{ nameof ( PullRequestServiceType ) } '{ PullRequestServiceType } ' is not valid. " +
139+ $ "Options are { options } ") ;
140+ }
141+
142+ var auth = new GitHubAuth (
143+ PullRequestAuthToken ,
144+ PullRequestUser ,
145+ PullRequestEmail ) ;
146+
147+ switch ( type )
148+ {
149+ case VersionTools . PullRequestServiceType . GitHub :
150+ origin = new GitHubProject ( ProjectRepoName , PullRequestUser ) ;
151+ return new GitHubClient ( auth ) ;
152+
153+ case VersionTools . PullRequestServiceType . Vsts :
154+ if ( string . IsNullOrEmpty ( VstsInstanceName ) )
89155 {
90- ForceCreate = AlwaysCreateNewPullRequest ,
91- MaintainersCanModify = MaintainersCanModifyPullRequest ,
92- TrackDiscardedCommits = TrackDiscardedCommits
93- } ) . Wait ( ) ;
156+ throw new ArgumentException ( $ "{ nameof ( VstsInstanceName ) } is required but not set.") ;
157+ }
158+
159+ origin = new GitHubProject ( ProjectRepoName , ProjectRepoOwner ) ;
160+ return new VstsAdapterClient ( auth , VstsInstanceName , VstsApiVersionOverride ) ;
161+
162+ default :
163+ throw new ArgumentOutOfRangeException (
164+ nameof ( PullRequestServiceType ) ,
165+ type ,
166+ "Enum value invalid." ) ;
94167 }
95168 }
96169 }
0 commit comments