-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutomatedCodeReview.cs
More file actions
136 lines (113 loc) · 6.5 KB
/
Copy pathAutomatedCodeReview.cs
File metadata and controls
136 lines (113 loc) · 6.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Controls;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.VersionControl.Controls.Extensibility;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace AutomatedCodeReview
{
[TeamExplorerSection(SectionId, TeamExplorerPageIds.PendingChanges, 2)]
public class AutomatedCodeReview : TeamExplorerSection
{
private const string SectionId = "EFD86431-C734-4956-9E46-1DFff4506778";
public AutomatedCodeReview()
{
Title = @"Generate Code Review Requests At Checkin";
IsVisible = true;
IsExpanded = true;
SectionContent = new AutomatedCodeReviewView();
}
public override void Loaded(object sender, SectionLoadedEventArgs e)
{
TfsTeamProjectCollection teamProjectCollection = CurrentContext.TeamProjectCollection;
VersionControlServer versionControl = teamProjectCollection?.GetService<VersionControlServer>();
if (versionControl == null)
{
return;
}
versionControl.BeforeCheckinPendingChange += OnChekinPendingChanges;
}
private void OnChekinPendingChanges(object sender, ProcessingChangeEventArgs processingChangeEvent)
{
AutomatedCodeReviewView view = SectionContent as AutomatedCodeReviewView;
if (view == null || !view.IsChecked)
{
return;
}
Workspace workspace = processingChangeEvent.Workspace;
VersionControlServer control = workspace.VersionControlServer;
ITeamFoundationContext currentContext = CurrentContext;
if (control == null || currentContext == null)
{
return;
}
IPendingChangesExt pendingChangesExtService = GetService<IPendingChangesExt>();
//Create the code review request once, as the event is fired for every objects to be checked in.
PendingChange[] pendingChanges = pendingChangesExtService?.IncludedChanges;
PendingChange pendingChange = pendingChanges?[0];
if (pendingChange?.ItemId != processingChangeEvent.PendingChange.ItemId)
{
return;
}
WorkItemStore workitemStore = currentContext.TeamProjectCollection.GetService<WorkItemStore>();
Project project = workitemStore.Projects[currentContext.TeamProjectName];
//Create the shelve set
DateTime dateTimeNow = DateTime.UtcNow;
Shelveset shelveSet = new Shelveset(control,
$@"Code Review_{dateTimeNow.Year}-{dateTimeNow.Month}-{dateTimeNow.Day}_{dateTimeNow.Hour}.{dateTimeNow.Minute}.{dateTimeNow.Second}.{dateTimeNow.Millisecond}",
workspace.OwnerName);
shelveSet.WorkItemInfo = pendingChangesExtService.WorkItems;
workspace.Shelve(shelveSet, pendingChanges, ShelvingOptions.None);
//Create the review request
WorkItemType type = project.WorkItemTypes["Code Review Request"];
WorkItem workItem = new WorkItem(type) { Title = workspace.Comment };
workItem.Fields["System.AssignedTo"].Value = control.AuthenticatedUser;
workItem.Fields["Microsoft.VSTS.CodeReview.Context"].Value = shelveSet.Name;
workItem.Fields["System.AreaPath"].Value = currentContext.TeamProjectName;
workItem.Fields["System.IterationPath"].Value = project.Name;
workItem.Fields["System.State"].Value = "Requested";
workItem.Fields["System.Reason"].Value = "New";
workItem.Fields["System.Description"].Value = $"Code Review Request from {control.AuthenticatedUser}";
workItem.Fields["System.Title"].Value = pendingChangesExtService.CheckinComment;
//Get the list of recent reviewers
string workItemQuery =
$@"SELECT * FROM WorkItems WHERE [System.TeamProject] = '{project.Name}' AND [Work Item Type] = 'Code Review Request' AND [Area Path] = '{project.Name}' AND [Created By] = '{control.AuthenticatedUser}' AND [System.State] <> 'Closed' ORDER BY [System.CreatedDate]";
WorkItemCollection allReviewItems = workitemStore.Query(workItemQuery);
WorkItem lastItem = allReviewItems.OfType<WorkItem>().LastOrDefault();
IEnumerable<int> recentReviewers = lastItem?.Links.OfType<RelatedLink>().Select(x => x.RelatedWorkItemId);
if (recentReviewers != null)
{
foreach (int recentReviewer in recentReviewers)
{
//Create Code Review Response for each reviewer
WorkItem oldCodeReviewResponse = workitemStore.GetWorkItem(recentReviewer);
WorkItemType codeReviewResponseType = project.WorkItemTypes["Code Review Response"];
WorkItem codeReviewResponseItem = new WorkItem(codeReviewResponseType) {Title = @"Code Review Response"};
object reviewerName = oldCodeReviewResponse.Fields["System.State"].Value.ToString() == @"Requested"
? oldCodeReviewResponse.Fields["System.AssignedTo"].Value
: oldCodeReviewResponse.Fields["Closed By"].Value;
codeReviewResponseItem.Fields["System.AssignedTo"].Value = reviewerName;
codeReviewResponseItem.Fields["Reviewed By"].Value = reviewerName;
ArrayList result = codeReviewResponseItem.Validate();
if (result.Count != 0)
{
continue;
}
codeReviewResponseItem.Save();
int responseId = codeReviewResponseItem.Id;
WorkItemLinkTypeEnd linkTypeEnd = workitemStore.WorkItemLinkTypes.LinkTypeEnds["Child"];
workItem.Links.Add(new RelatedLink(linkTypeEnd, responseId));
}
}
ArrayList codeReviewRequestResult = workItem.Validate();
if (codeReviewRequestResult.Count != 0)
{
return;
}
workItem.Save();
}
}
}