From 25952ef7a95d357ae50d7b02500b24e780834688 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 25 Oct 2018 06:41:15 -0400 Subject: [PATCH 01/25] Adding a second line to Checks in the PullRequestCheckView --- .../GitHubPane/PullRequestCheckViewModel.cs | 19 ++++++++++++++++++- src/GitHub.Exports/Models/CheckRunModel.cs | 9 +++++++-- .../Services/PullRequestSessionService.cs | 4 +++- .../GitHubPane/PullRequestCheckView.xaml | 5 +++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs index f95bd95fd1..c2178f3876 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using System.Reactive; using System.Reactive.Linq; +using System.Text; using System.Windows.Media.Imaging; using GitHub.Extensions; using GitHub.Factories; @@ -92,7 +93,23 @@ public static IEnumerable Build(IViewViewModelFactor var pullRequestCheckViewModel = (PullRequestCheckViewModel)viewViewModelFactory.CreateViewModel(); pullRequestCheckViewModel.CheckType = PullRequestCheckType.ChecksApi; pullRequestCheckViewModel.Title = model.Name; - pullRequestCheckViewModel.Description = model.Summary; + + var description = new StringBuilder(model.Conclusion.ToString()); + + if (model.StartedAt.HasValue && model.CompletedAt.HasValue) + { + description.Append(" in "); + var timeSpan = model.CompletedAt.Value - model.StartedAt.Value; + description.Append(timeSpan.ToString()); + } + + if (!string.IsNullOrEmpty(model.Title)) + { + description.Append(" - "); + description.Append(model.Title); + } + + pullRequestCheckViewModel.Description = description.ToString(); pullRequestCheckViewModel.Status = checkStatus; pullRequestCheckViewModel.DetailsUrl = new Uri(model.DetailsUrl); diff --git a/src/GitHub.Exports/Models/CheckRunModel.cs b/src/GitHub.Exports/Models/CheckRunModel.cs index a25335c8bb..c0c89cb62a 100644 --- a/src/GitHub.Exports/Models/CheckRunModel.cs +++ b/src/GitHub.Exports/Models/CheckRunModel.cs @@ -16,6 +16,11 @@ public class CheckRunModel /// public CheckStatusState Status { get; set; } + /// + /// Identifies the date and time when the check run was started. + /// + public DateTimeOffset? StartedAt { get; set; } + /// /// Identifies the date and time when the check run was completed. /// @@ -30,8 +35,8 @@ public class CheckRunModel public string DetailsUrl { get; set; } /// - /// The summary of a Check Run. + /// The title of a Check Run. /// - public string Summary { get; set; } + public string Title { get; set; } } } \ No newline at end of file diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index 56f8570903..b571328b9c 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -774,7 +774,9 @@ async Task GetPullRequestLastCommitAdapter(HostAddress addres Status = run.Status.FromGraphQl(), Name = run.Name, DetailsUrl = run.Permalink, - Summary = run.Summary, + Title = run.Title, + StartedAt = run.StartedAt, + CompletedAt = run.CompletedAt }).ToList() }).ToList(), Statuses = commit.Commit.Status diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index d04daeeda1..15d51f3f51 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -22,6 +22,7 @@ + @@ -50,5 +51,9 @@ Details + + + From 6c2e1c8ebc8d975de96edffa7c0408df31941c09 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 25 Oct 2018 14:14:49 -0700 Subject: [PATCH 02/25] Update checks list layout --- .../GitHubPane/PullRequestCheckView.xaml | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 15d51f3f51..1a1612d85c 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -22,11 +22,9 @@ - - @@ -34,26 +32,22 @@ + - - - + + + - - - - From 2a8b50f052d8bf559252e5fb34e2ffb3cb7a38a4 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 25 Oct 2018 14:25:02 -0700 Subject: [PATCH 03/25] Little bit of spacing and some text color formatting --- .../Views/GitHubPane/PullRequestCheckView.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 1a1612d85c..9d5ed67b2a 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -22,7 +22,7 @@ - + @@ -42,7 +42,7 @@ --> - + Details From 632c9fb6ce5c6e0abae055bcbab01e6f727d9bef Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Tue, 30 Oct 2018 14:19:56 -0400 Subject: [PATCH 04/25] Making duration status a tooltip --- .../PullRequestCheckViewModelDesigner.cs | 2 + .../GitHubPane/PullRequestCheckViewModel.cs | 26 +-- .../GitHubPane/IPullRequestCheckViewModel.cs | 14 +- .../Extensions/TimeSpanExtensions.cs | 89 ++++++++++ src/GitHub.Exports/GitHub.Exports.csproj | 1 + src/GitHub.Resources/Resources.Designer.cs | 156 +++++++++++++++--- src/GitHub.Resources/Resources.resx | 60 +++++-- src/GitHub.Resources/Resources.zh-CN.resx | 60 +++++-- .../Converters/DurationToStringConverter.cs | 26 +-- .../GitHubPane/PullRequestCheckView.xaml | 2 +- 10 files changed, 346 insertions(+), 90 deletions(-) create mode 100644 src/GitHub.Exports/Extensions/TimeSpanExtensions.cs diff --git a/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs index 3011e581c1..2236bff114 100644 --- a/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs @@ -13,6 +13,8 @@ public sealed class PullRequestCheckViewModelDesigner : ViewModelBase, IPullRequ public string Description { get; set; } = "AppVeyor build failed"; + public string DurationStatus { get; set; } + public PullRequestCheckStatus Status { get; set; } = PullRequestCheckStatus.Failure; public Uri DetailsUrl { get; set; } = new Uri("http://github.com"); diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs index c2178f3876..d343bee471 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reactive; @@ -11,10 +12,12 @@ using GitHub.Factories; using GitHub.Models; using GitHub.Services; +using GitHub.UI.Converters; using ReactiveUI; namespace GitHub.ViewModels.GitHubPane { + /// [Export(typeof(IPullRequestCheckViewModel))] [PartCreationPolicy(CreationPolicy.NonShared)] public class PullRequestCheckViewModel: ViewModelBase, IPullRequestCheckViewModel @@ -94,22 +97,13 @@ public static IEnumerable Build(IViewViewModelFactor pullRequestCheckViewModel.CheckType = PullRequestCheckType.ChecksApi; pullRequestCheckViewModel.Title = model.Name; - var description = new StringBuilder(model.Conclusion.ToString()); - if (model.StartedAt.HasValue && model.CompletedAt.HasValue) { - description.Append(" in "); - var timeSpan = model.CompletedAt.Value - model.StartedAt.Value; - description.Append(timeSpan.ToString()); + var timeSpanString = TimeSpanExtensions.Humanize(model.CompletedAt.Value - model.StartedAt.Value, CultureInfo.CurrentCulture, TimeSpanExtensions.OutputTense.Completed); + pullRequestCheckViewModel.DurationStatus = $"{checkStatus} - {timeSpanString}"; } - if (!string.IsNullOrEmpty(model.Title)) - { - description.Append(" - "); - description.Append(model.Title); - } - - pullRequestCheckViewModel.Description = description.ToString(); + pullRequestCheckViewModel.Description = model.Title; pullRequestCheckViewModel.Status = checkStatus; pullRequestCheckViewModel.DetailsUrl = new Uri(model.DetailsUrl); @@ -141,16 +135,24 @@ private void DoOpenDetailsUrl() usageTracker.IncrementCounter(expression).Forget(); } + /// public string Title { get; private set; } + /// + public string DurationStatus { get; private set; } + + /// public string Description { get; private set; } public PullRequestCheckType CheckType { get; private set; } + /// public PullRequestCheckStatus Status{ get; private set; } + /// public Uri DetailsUrl { get; private set; } + /// public ReactiveCommand OpenDetailsUrl { get; } } } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs index 1a9d658a39..a6528e98d3 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs @@ -12,29 +12,33 @@ namespace GitHub.ViewModels.GitHubPane public interface IPullRequestCheckViewModel: IViewModel { /// - /// The title of the Status/Check + /// The title of the Status/Check. /// string Title { get; } /// - /// The description of the Status/Check + /// The description of the Status/Check. /// string Description { get; } /// - /// The status of the Status/Check + /// The status of the Status/Check. /// PullRequestCheckStatus Status { get; } /// - /// The url where more information about the Status/Check can be found + /// The url where more information about the Status/Check can be found. /// Uri DetailsUrl { get; } /// - /// A command that opens the DetailsUrl in a browser + /// The amount of time this Status/Check took to run. /// + string DurationStatus { get; } + /// + /// A command that opens the DetailsUrl in a browser + /// ReactiveCommand OpenDetailsUrl { get; } } diff --git a/src/GitHub.Exports/Extensions/TimeSpanExtensions.cs b/src/GitHub.Exports/Extensions/TimeSpanExtensions.cs new file mode 100644 index 0000000000..7f1fbb09e5 --- /dev/null +++ b/src/GitHub.Exports/Extensions/TimeSpanExtensions.cs @@ -0,0 +1,89 @@ +using System; +using System.Globalization; + +namespace GitHub.UI.Converters +{ + public static class TimeSpanExtensions + { + public static string Humanize(TimeSpan duration, CultureInfo culture, OutputTense outputTense = OutputTense.Past) + { + if (duration.Ticks <= 0) + { + return Resources.JustNow; + } + + const int year = 365; + const int month = 30; + const int day = 24; + const int hour = 60; + const int minute = 60; + + if (duration.TotalDays >= year) + { + return GetFormattedValue(culture, (int) (duration.TotalDays / year), + outputTense, + Resources.YearsAgo, Resources.Years, + Resources.YearAgo, Resources.Year); + } + + if (duration.TotalDays >= 360) + { + return string.Format(culture, outputTense == OutputTense.Past ? Resources.MonthsAgo : Resources.Month, 11); + } + + if (duration.TotalDays >= month) + { + return GetFormattedValue(culture, (int)(duration.TotalDays / month), + outputTense, + Resources.MonthsAgo, Resources.Months, + Resources.MonthAgo, Resources.Month); + } + + if (duration.TotalHours >= day) + { + return GetFormattedValue(culture, (int)(duration.TotalHours / day), + outputTense, + Resources.DaysAgo, Resources.Days, + Resources.DayAgo, Resources.Day); + } + + if (duration.TotalMinutes >= hour) + { + return GetFormattedValue(culture, (int)(duration.TotalMinutes / hour), + outputTense, + Resources.HoursAgo, Resources.Hours, + Resources.HourAgo, Resources.Hour); + } + + if (duration.TotalSeconds >= minute) + { + return GetFormattedValue(culture, (int)(duration.TotalSeconds / minute), + outputTense, + Resources.MinutesAgo, Resources.Minutes, + Resources.MinuteAgo, Resources.Minute); + } + + return GetFormattedValue(culture, (int) duration.TotalSeconds, + outputTense, + Resources.SecondsAgo, Resources.Seconds, + Resources.SecondAgo, Resources.Second); + } + + private static string GetFormattedValue(CultureInfo culture, int value, OutputTense outputTense, + string multiplePast, string multipleCompleted, + string singlePast, string singleCompleted) + { + var formatString = value > 1 + ? outputTense == OutputTense.Past ? multiplePast : multipleCompleted + : outputTense == OutputTense.Past ? singlePast : singleCompleted; + + return string.Format(culture, formatString, value); + } + + public enum OutputTense + { + Past, + Completed + } + } +} \ No newline at end of file diff --git a/src/GitHub.Exports/GitHub.Exports.csproj b/src/GitHub.Exports/GitHub.Exports.csproj index 5f2792e87c..0811f46551 100644 --- a/src/GitHub.Exports/GitHub.Exports.csproj +++ b/src/GitHub.Exports/GitHub.Exports.csproj @@ -20,6 +20,7 @@ + diff --git a/src/GitHub.Resources/Resources.Designer.cs b/src/GitHub.Resources/Resources.Designer.cs index ff8f5b2516..aae9932074 100644 --- a/src/GitHub.Resources/Resources.Designer.cs +++ b/src/GitHub.Resources/Resources.Designer.cs @@ -450,21 +450,39 @@ public static string CreateTitle { } } + /// + /// Looks up a localized string similar to {0:N0} day. + /// + public static string Day { + get { + return ResourceManager.GetString("Day", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0:N0} day ago. /// - public static string day { + public static string DayAgo { + get { + return ResourceManager.GetString("DayAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} days. + /// + public static string Days { get { - return ResourceManager.GetString("day", resourceCulture); + return ResourceManager.GetString("Days", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} days ago. /// - public static string days { + public static string DaysAgo { get { - return ResourceManager.GetString("days", resourceCulture); + return ResourceManager.GetString("DaysAgo", resourceCulture); } } @@ -756,21 +774,39 @@ public static string GraphsNavigationItemText { } } + /// + /// Looks up a localized string similar to {0:N0} hour. + /// + public static string Hour { + get { + return ResourceManager.GetString("Hour", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0:N0} hour ago. /// - public static string hour { + public static string HourAgo { get { - return ResourceManager.GetString("hour", resourceCulture); + return ResourceManager.GetString("HourAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} hours. + /// + public static string Hours { + get { + return ResourceManager.GetString("Hours", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} hours ago. /// - public static string hours { + public static string HoursAgo { get { - return ResourceManager.GetString("hours", resourceCulture); + return ResourceManager.GetString("HoursAgo", resourceCulture); } } @@ -972,39 +1008,75 @@ public static string makePrivateGist { } } + /// + /// Looks up a localized string similar to {0:N0} minute. + /// + public static string Minute { + get { + return ResourceManager.GetString("Minute", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0:N0} minute ago. /// - public static string minute { + public static string MinuteAgo { + get { + return ResourceManager.GetString("MinuteAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} minutes. + /// + public static string Minutes { get { - return ResourceManager.GetString("minute", resourceCulture); + return ResourceManager.GetString("Minutes", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} minutes ago. /// - public static string minutes { + public static string MinutesAgo { get { - return ResourceManager.GetString("minutes", resourceCulture); + return ResourceManager.GetString("MinutesAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} month. + /// + public static string Month { + get { + return ResourceManager.GetString("Month", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} month ago. /// - public static string month { + public static string MonthAgo { + get { + return ResourceManager.GetString("MonthAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} months. + /// + public static string Months { get { - return ResourceManager.GetString("month", resourceCulture); + return ResourceManager.GetString("Months", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} months ago. /// - public static string months { + public static string MonthsAgo { get { - return ResourceManager.GetString("months", resourceCulture); + return ResourceManager.GetString("MonthsAgo", resourceCulture); } } @@ -1773,21 +1845,39 @@ public static string SafeRepositoryNameWarning { } } + /// + /// Looks up a localized string similar to {0:N0} second. + /// + public static string Second { + get { + return ResourceManager.GetString("Second", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0:N0} second ago. /// - public static string second { + public static string SecondAgo { get { - return ResourceManager.GetString("second", resourceCulture); + return ResourceManager.GetString("SecondAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} seconds. + /// + public static string Seconds { + get { + return ResourceManager.GetString("Seconds", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} seconds ago. /// - public static string seconds { + public static string SecondsAgo { get { - return ResourceManager.GetString("seconds", resourceCulture); + return ResourceManager.GetString("SecondsAgo", resourceCulture); } } @@ -2162,21 +2252,39 @@ public static string Wrote { } } + /// + /// Looks up a localized string similar to {0:N0} year. + /// + public static string Year { + get { + return ResourceManager.GetString("Year", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0:N0} year ago. /// - public static string year { + public static string YearAgo { + get { + return ResourceManager.GetString("YearAgo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0:N0} years. + /// + public static string Years { get { - return ResourceManager.GetString("year", resourceCulture); + return ResourceManager.GetString("Years", resourceCulture); } } /// /// Looks up a localized string similar to {0:N0} years ago. /// - public static string years { + public static string YearsAgo { get { - return ResourceManager.GetString("years", resourceCulture); + return ResourceManager.GetString("YearsAgo", resourceCulture); } } diff --git a/src/GitHub.Resources/Resources.resx b/src/GitHub.Resources/Resources.resx index d8ff9d14ba..7c062ae0d6 100644 --- a/src/GitHub.Resources/Resources.resx +++ b/src/GitHub.Resources/Resources.resx @@ -336,45 +336,81 @@ https://git-scm.com/download/win Logout Required - + {0:N0} day ago - + {0:N0} days ago - + {0:N0} hour ago - + {0:N0} hours ago just now - + {0:N0} minute ago - + {0:N0} minutes ago - + {0:N0} month ago - + {0:N0} months ago - + {0:N0} second ago - + {0:N0} seconds ago - + {0:N0} year ago - + {0:N0} years ago + + {0:N0} day + + + {0:N0} days + + + {0:N0} hour + + + {0:N0} hours + + + {0:N0} minute + + + {0:N0} minutes + + + {0:N0} month + + + {0:N0} months + + + {0:N0} second + + + {0:N0} seconds + + + {0:N0} year + + + {0:N0} years + Invalid authentication code diff --git a/src/GitHub.Resources/Resources.zh-CN.resx b/src/GitHub.Resources/Resources.zh-CN.resx index f1a1758f8d..09dc82e3ed 100644 --- a/src/GitHub.Resources/Resources.zh-CN.resx +++ b/src/GitHub.Resources/Resources.zh-CN.resx @@ -335,45 +335,81 @@ 需要注销 - + {0:N0} 天前 - + {0:N0} 天前 - + {0:N0} 小时前 - + {0:N0} 小时前 就现在 - + {0:N0} 分钟前 - + {0:N0} 分钟前 - + {0:N0} 月前 - + {0:N0} 月前 - + {0:N0} 秒前 - + {0:N0} 秒前 - + {0:N0} 年前 - + {0:N0} 年前 + + {0:N0} day + + + {0:N0} days + + + {0:N0} hour + + + {0:N0} hours + + + {0:N0} minute + + + {0:N0} minutes + + + {0:N0} month + + + {0:N0} months + + + {0:N0} second + + + {0:N0} seconds + + + {0:N0} year + + + {0:N0} years + 无效的验证码 diff --git a/src/GitHub.UI/Converters/DurationToStringConverter.cs b/src/GitHub.UI/Converters/DurationToStringConverter.cs index dbebe9f3fa..cc88249f7d 100644 --- a/src/GitHub.UI/Converters/DurationToStringConverter.cs +++ b/src/GitHub.UI/Converters/DurationToStringConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using GitHub.UI.Converters; namespace GitHub.UI { @@ -17,30 +18,7 @@ public override object Convert(object value, Type targetType, object parameter, else return value; - if (duration.Ticks <= 0) - { - return Resources.JustNow; - } - - const int year = 365; - const int month = 30; - const int day = 24; - const int hour = 60; - const int minute = 60; - - if (duration.TotalDays >= year) - return string.Format(culture, (int)(duration.TotalDays / year) > 1 ? Resources.years : Resources.year, (int)(duration.TotalDays / year)); - else if (duration.TotalDays >= 360) - return string.Format(culture, Resources.months, 11); - else if (duration.TotalDays >= month) - return string.Format(culture, (int)(duration.TotalDays / (month)) > 1 ? Resources.months : Resources.month, (int)(duration.TotalDays / (month))); - else if (duration.TotalHours >= day) - return string.Format(culture, (int)(duration.TotalHours / day) > 1 ? Resources.days : Resources.day, (int)(duration.TotalHours / day)); - else if (duration.TotalMinutes >= hour) - return string.Format(culture, (int)(duration.TotalMinutes / hour) > 1 ? Resources.hours : Resources.hour, (int)(duration.TotalMinutes / hour)); - else if (duration.TotalSeconds >= minute) - return string.Format(culture, (int)(duration.TotalSeconds / minute) > 1 ? Resources.minutes : Resources.minute, (int)(duration.TotalSeconds / minute)); - return string.Format(culture, duration.TotalSeconds > 1 || duration.Ticks == 0 ? Resources.seconds : Resources.second, duration.TotalSeconds); + return TimeSpanExtensions.Humanize(duration, culture); } } } \ No newline at end of file diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 9d5ed67b2a..4cd2d242c4 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -42,7 +42,7 @@ --> - + Details From 406c5d41f0ad68c68768f52b781587606555d211 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 31 Oct 2018 09:07:02 -0400 Subject: [PATCH 05/25] Allow functionality to set ProtectedBranches --- src/GitHub.App/Services/PullRequestService.cs | 8 ++++ src/GitHub.App/Services/RepositoryService.cs | 40 +++++++++++++++++-- src/GitHub.Exports/Models/ProtectedBranch.cs | 8 ++++ .../Services/IRepositoryService.cs | 4 ++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/GitHub.Exports/Models/ProtectedBranch.cs diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index 9b8015cb43..697e87810f 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -55,6 +55,7 @@ public class PullRequestService : IPullRequestService readonly IGitService gitService; readonly IVSGitExt gitExt; readonly IGraphQLClientFactory graphqlFactory; + readonly IRepositoryService repositoryService; readonly IOperatingSystem os; readonly IUsageTracker usageTracker; @@ -64,6 +65,7 @@ public PullRequestService( IGitService gitService, IVSGitExt gitExt, IGraphQLClientFactory graphqlFactory, + IRepositoryService repositoryService, IOperatingSystem os, IUsageTracker usageTracker) { @@ -71,6 +73,7 @@ public PullRequestService( this.gitService = gitService; this.gitExt = gitExt; this.graphqlFactory = graphqlFactory; + this.repositoryService = repositoryService; this.os = os; this.usageTracker = usageTracker; } @@ -198,6 +201,11 @@ public async Task> ReadPullRequests( query = readPullRequestsEnterprise; } + var protectedBranches = await repositoryService.GetProtectedBranches(address, owner, name) + .ConfigureAwait(false); + + var protectedBranchDictionary = protectedBranches.ToDictionary(branch => branch.Name); + var graphql = await graphqlFactory.CreateConnection(address); var vars = new Dictionary { diff --git a/src/GitHub.App/Services/RepositoryService.cs b/src/GitHub.App/Services/RepositoryService.cs index 36b729fe3e..1c8bf2c7af 100644 --- a/src/GitHub.App/Services/RepositoryService.cs +++ b/src/GitHub.App/Services/RepositoryService.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.Linq; using System.Threading.Tasks; using GitHub.Api; using GitHub.Extensions; +using GitHub.Models; using GitHub.Primitives; using Octokit.GraphQL; using static Octokit.GraphQL.Variable; @@ -12,9 +14,10 @@ namespace GitHub.Services { [Export(typeof(IRepositoryService))] [PartCreationPolicy(CreationPolicy.Shared)] - public class RepositoryService : IRepositoryService + public class RepositoryService: IRepositoryService { static ICompiledQuery> readParentOwnerLogin; + static ICompiledQuery> queryProtectedBranches; readonly IGraphQLClientFactory graphqlFactory; [ImportingConstructor] @@ -45,9 +48,40 @@ public RepositoryService(IGraphQLClientFactory graphqlFactory) { nameof(name), name }, }; - var graphql = await graphqlFactory.CreateConnection(address); - var result = await graphql.Run(readParentOwnerLogin, vars); + var graphql = await graphqlFactory.CreateConnection(address).ConfigureAwait(false); + var result = await graphql.Run(readParentOwnerLogin, vars).ConfigureAwait(false); return result != null ? (result.Item1, result.Item2) : ((string, string)?)null; } + + public async Task> GetProtectedBranches(HostAddress address, string owner, string name) + { + Guard.ArgumentNotNull(address, nameof(address)); + Guard.ArgumentNotEmptyString(owner, nameof(owner)); + Guard.ArgumentNotEmptyString(name, nameof(name)); + + if (queryProtectedBranches == null) + { + queryProtectedBranches = new Query() + .Repository(Var(nameof(owner)), Var(nameof(name))) + .Select(r => + r.ProtectedBranches(null, null, null, null) + .AllPages() + .Select(branch => new ProtectedBranch + { + Name = branch.Name, + RequiredStatusCheckContexts = branch.RequiredStatusCheckContexts.ToArray() + }) + ).Compile(); + } + + var vars = new Dictionary + { + { nameof(owner), owner }, + { nameof(name), name }, + }; + + var graphql = await graphqlFactory.CreateConnection(address).ConfigureAwait(false); + return await graphql.Run(queryProtectedBranches, vars).ConfigureAwait(false); + } } } diff --git a/src/GitHub.Exports/Models/ProtectedBranch.cs b/src/GitHub.Exports/Models/ProtectedBranch.cs new file mode 100644 index 0000000000..019bc9ff2b --- /dev/null +++ b/src/GitHub.Exports/Models/ProtectedBranch.cs @@ -0,0 +1,8 @@ +namespace GitHub.Models +{ + public class ProtectedBranch + { + public string Name { get; set; } + public string[] RequiredStatusCheckContexts { get; set; } + } +} \ No newline at end of file diff --git a/src/GitHub.Exports/Services/IRepositoryService.cs b/src/GitHub.Exports/Services/IRepositoryService.cs index c71f492e29..88e720fb28 100644 --- a/src/GitHub.Exports/Services/IRepositoryService.cs +++ b/src/GitHub.Exports/Services/IRepositoryService.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; +using GitHub.Models; using GitHub.Primitives; namespace GitHub.Services @@ -17,5 +19,7 @@ public interface IRepositoryService /// otherwise null. /// Task<(string owner, string name)?> FindParent(HostAddress address, string owner, string name); + + Task> GetProtectedBranches(HostAddress address, string owner, string name); } } From 0b979b380095c16255abcc053ffe9c5794a07351 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Fri, 2 Nov 2018 08:51:11 -0400 Subject: [PATCH 06/25] GraphQL fix --- src/GitHub.App/Services/RepositoryService.cs | 8 ++++---- src/GitHub.Exports/Services/IRepositoryService.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/GitHub.App/Services/RepositoryService.cs b/src/GitHub.App/Services/RepositoryService.cs index 474e100af9..d4d183ea30 100644 --- a/src/GitHub.App/Services/RepositoryService.cs +++ b/src/GitHub.App/Services/RepositoryService.cs @@ -17,7 +17,7 @@ namespace GitHub.Services public class RepositoryService: IRepositoryService { static ICompiledQuery> readParentOwnerLogin; - static ICompiledQuery> queryProtectedBranches; + static ICompiledQuery> queryProtectedBranches; readonly IGraphQLClientFactory graphqlFactory; [ImportingConstructor] @@ -53,7 +53,7 @@ public RepositoryService(IGraphQLClientFactory graphqlFactory) return result != null ? (result.Item1, result.Item2) : ((string, string)?)null; } - public async Task> GetProtectedBranches(HostAddress address, string owner, string name) + public async Task> GetProtectedBranches(HostAddress address, string owner, string name) { Guard.ArgumentNotNull(address, nameof(address)); Guard.ArgumentNotEmptyString(owner, nameof(owner)); @@ -62,7 +62,7 @@ public async Task> GetProtectedBranches(HostAddress if (queryProtectedBranches == null) { queryProtectedBranches = new Query() - .Repository(Var(nameof(owner)), Var(nameof(name))) + .Repository(Var(nameof(name)), Var(nameof(owner))) .Select(r => r.ProtectedBranches(null, null, null, null) .AllPages() @@ -70,7 +70,7 @@ public async Task> GetProtectedBranches(HostAddress { Name = branch.Name, RequiredStatusCheckContexts = branch.RequiredStatusCheckContexts.ToArray() - }) + }).ToList() ).Compile(); } diff --git a/src/GitHub.Exports/Services/IRepositoryService.cs b/src/GitHub.Exports/Services/IRepositoryService.cs index 88e720fb28..975996bc69 100644 --- a/src/GitHub.Exports/Services/IRepositoryService.cs +++ b/src/GitHub.Exports/Services/IRepositoryService.cs @@ -20,6 +20,6 @@ public interface IRepositoryService /// Task<(string owner, string name)?> FindParent(HostAddress address, string owner, string name); - Task> GetProtectedBranches(HostAddress address, string owner, string name); + Task> GetProtectedBranches(HostAddress address, string owner, string name); } } From e17b44b350da6e52450b97931704f548ec5db326 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Fri, 2 Nov 2018 11:37:36 -0400 Subject: [PATCH 07/25] Adding a second check for differing non-required statuses --- .../PullRequestListItemViewModelDesigner.cs | 2 +- src/GitHub.App/Services/PullRequestService.cs | 199 ++++++++++++++---- .../PullRequestListItemViewModel.cs | 2 +- .../Collections/TrackingCollection.cs | 4 +- .../Services/IGitClient.cs | 6 +- .../Services/IPullRequestService.cs | 4 +- .../Services/IRepositoryCloneService.cs | 4 +- .../GitHubPane/IPullRequestDetailViewModel.cs | 2 +- .../IPullRequestListItemViewModel.cs | 2 +- .../Models/IPullRequestModel.cs | 10 + .../Models/PullRequestDetailModel.cs | 2 +- .../Models/PullRequestListItemModel.cs | 12 +- .../IEnterpriseCapabilitiesService.cs | 2 +- .../GitHubPane/PullRequestListItemView.xaml | 4 + .../Services/PullRequestServiceTests.cs | 6 + .../PullRequestCreationViewModelTests.cs | 8 +- 16 files changed, 205 insertions(+), 64 deletions(-) diff --git a/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs index 500089fb84..aba518d750 100644 --- a/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs @@ -17,6 +17,6 @@ public class PullRequestListItemViewModelDesigner : ViewModelBase, IPullRequestL public int Number { get; set; } public string Title { get; set; } public DateTimeOffset UpdatedAt { get; set; } - public PullRequestChecksState Checks { get; set; } + public PullRequestChecksSummaryState Checks { get; set; } } } diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index b460f7fca9..e7c8f6091f 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -26,6 +26,7 @@ using static Octokit.GraphQL.Variable; using CheckConclusionState = GitHub.Models.CheckConclusionState; using CheckStatusState = GitHub.Models.CheckStatusState; +using ProtectedBranch = GitHub.Models.ProtectedBranch; using StatusState = GitHub.Models.StatusState; namespace GitHub.Services @@ -107,12 +108,14 @@ public async Task> ReadPullRequests( Items = page.Nodes.Select(pr => new ListItemAdapter { Id = pr.Id.Value, + BaseRefName = pr.BaseRefName, LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit => new LastCommitSummaryAdapter { CheckSuites = commit.Commit.CheckSuites(null, null, null, null, null).AllPages(10) .Select(suite => new CheckSuiteSummaryModel { + ApplicationName = suite.App != null ? suite.App.Name : "Private Application", CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10) .Select(run => new CheckRunSummaryModel { @@ -124,6 +127,7 @@ public async Task> ReadPullRequests( .Select(context => context.Contexts.Select(statusContext => new StatusSummaryModel { + Context = statusContext.Context, State = statusContext.State.FromGraphQl(), }).ToList() ).SingleOrDefault() @@ -168,6 +172,7 @@ public async Task> ReadPullRequests( Items = page.Nodes.Select(pr => new ListItemAdapter { Id = pr.Id.Value, + BaseRefName = pr.BaseRefName, LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit => new LastCommitSummaryAdapter { @@ -204,7 +209,7 @@ public async Task> ReadPullRequests( var protectedBranches = await repositoryService.GetProtectedBranches(address, owner, name) .ConfigureAwait(false); - var protectedBranchDictionary = protectedBranches.ToDictionary(branch => branch.Name); + var protectedBranchesContextsDictionary = protectedBranches.ToDictionary(branch => branch.Name, branch => new HashSet(branch.RequiredStatusCheckContexts)); var graphql = await graphqlFactory.CreateConnection(address); var vars = new Dictionary @@ -219,74 +224,172 @@ public async Task> ReadPullRequests( foreach (var item in result.Items.Cast()) { + HashSet protectedBranchContexts; + protectedBranchesContextsDictionary.TryGetValue(item.BaseRefName, out protectedBranchContexts); + item.CommentCount += item.Reviews.Sum(x => x.Count); item.Reviews = null; - var checkRuns = item.LastCommit?.CheckSuites?.SelectMany(model => model.CheckRuns).ToArray(); + if (protectedBranchContexts != null) + { + var requiredCheckRuns = item.LastCommit?.CheckSuites? + .Where(model => protectedBranchContexts.Contains(model.ApplicationName)) + .SelectMany(checkSuite => checkSuite.CheckRuns) + .ToArray(); - var hasCheckRuns = checkRuns?.Any() ?? false; - var hasStatuses = item.LastCommit?.Statuses?.Any() ?? false; + var requiredStatues = item.LastCommit?.Statuses + .Where(model => protectedBranchContexts.Contains(model.Context)) + .ToArray(); - if (!hasCheckRuns && !hasStatuses) - { - item.Checks = PullRequestChecksState.None; + item.RequiredChecks = CalculatePullRequestCheckState(requiredCheckRuns, requiredStatues); } else { - var checksHasFailure = false; - var checksHasCompleteSuccess = true; - - if (hasCheckRuns) - { - checksHasFailure = checkRuns - .Any(model => model.Conclusion.HasValue - && (model.Conclusion.Value == CheckConclusionState.Failure - || model.Conclusion.Value == CheckConclusionState.ActionRequired)); + item.RequiredChecks = PullRequestChecksState.None; + } - if (!checksHasFailure) - { - checksHasCompleteSuccess = checkRuns - .All(model => model.Conclusion.HasValue - && (model.Conclusion.Value == CheckConclusionState.Success - || model.Conclusion.Value == CheckConclusionState.Neutral)); - } - } + var checkRuns = item.LastCommit?.CheckSuites? + .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.ApplicationName)) + .SelectMany(checkSuite => checkSuite.CheckRuns) + .ToArray(); - var statusHasFailure = false; - var statusHasCompleteSuccess = true; + var statuses = item.LastCommit?.Statuses + .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.Context)) + .ToArray(); - if (!checksHasFailure && hasStatuses) - { - statusHasFailure = item.LastCommit - .Statuses - .Any(status => status.State == StatusState.Failure - || status.State == StatusState.Error); + item.OtherChecks = CalculatePullRequestCheckState(checkRuns, statuses); - if (!statusHasFailure) - { - statusHasCompleteSuccess = - item.LastCommit.Statuses.All(status => status.State == StatusState.Success); - } - } + switch (item.RequiredChecks) + { + case PullRequestChecksState.None: + item.Checks = PullRequestChecksSummaryState.None; + break; + case PullRequestChecksState.Pending: + item.Checks = PullRequestChecksSummaryState.Pending; + break; + case PullRequestChecksState.Success: + item.Checks = PullRequestChecksSummaryState.Success; + break; + case PullRequestChecksState.Failure: + item.Checks = PullRequestChecksSummaryState.Failure; + break; + default: + throw new ArgumentOutOfRangeException(); + } - if (checksHasFailure || statusHasFailure) + if (item.RequiredChecks != item.OtherChecks) + { + switch (item.RequiredChecks) { - item.Checks = PullRequestChecksState.Failure; + case PullRequestChecksState.None: + switch (item.OtherChecks) + { + case PullRequestChecksState.None: + item.Checks = PullRequestChecksSummaryState.None; + break; + case PullRequestChecksState.Pending: + item.Checks = PullRequestChecksSummaryState.Pending; + break; + case PullRequestChecksState.Success: + item.Checks = PullRequestChecksSummaryState.Success; + break; + case PullRequestChecksState.Failure: + item.Checks = PullRequestChecksSummaryState.Failure; + break; + default: + throw new ArgumentOutOfRangeException(); + } + break; + case PullRequestChecksState.Pending: + item.Checks = PullRequestChecksSummaryState.Pending; + break; + case PullRequestChecksState.Success: + switch (item.OtherChecks) + { + case PullRequestChecksState.Pending: + item.Checks = PullRequestChecksSummaryState.SuccessWithPending; + break; + case PullRequestChecksState.Failure: + item.Checks = PullRequestChecksSummaryState.SuccessWithFailure; + break; + } + break; + case PullRequestChecksState.Failure: + item.Checks = PullRequestChecksSummaryState.Failure; + break; + default: + throw new ArgumentOutOfRangeException(); } - else if (statusHasCompleteSuccess && checksHasCompleteSuccess) + } + + item.LastCommit = null; + } + + return result; + } + + static PullRequestChecksState CalculatePullRequestCheckState(IList checkRuns, IList statusSummaryModels) + { + var hasCheckRuns = checkRuns?.Any() ?? false; + var hasStatuses = statusSummaryModels?.Any() ?? false; + + PullRequestChecksState resultState; + if (!hasCheckRuns && !hasStatuses) + { + resultState = PullRequestChecksState.None; + } + else + { + var checksHasFailure = false; + var checksHasCompleteSuccess = true; + + if (hasCheckRuns) + { + checksHasFailure = checkRuns + .Any(model => model.Conclusion.HasValue + && (model.Conclusion.Value == CheckConclusionState.Failure + || model.Conclusion.Value == CheckConclusionState.ActionRequired)); + + if (!checksHasFailure) { - item.Checks = PullRequestChecksState.Success; + checksHasCompleteSuccess = checkRuns + .All(model => model.Conclusion.HasValue + && (model.Conclusion.Value == CheckConclusionState.Success + || model.Conclusion.Value == CheckConclusionState.Neutral)); } - else + } + + var statusHasFailure = false; + var statusHasCompleteSuccess = true; + + if (!checksHasFailure && hasStatuses) + { + statusHasFailure = statusSummaryModels + .Any(status => status.State == StatusState.Failure + || status.State == StatusState.Error); + + if (!statusHasFailure) { - item.Checks = PullRequestChecksState.Pending; + statusHasCompleteSuccess = + statusSummaryModels.All(status => status.State == StatusState.Success); } } - item.LastCommit = null; + if (checksHasFailure || statusHasFailure) + { + resultState = PullRequestChecksState.Failure; + } + else if (statusHasCompleteSuccess && checksHasCompleteSuccess) + { + resultState = PullRequestChecksState.Success; + } + else + { + resultState = PullRequestChecksState.Pending; + } } - return result; + return resultState; } public async Task> ReadAssignableUsers( @@ -1017,6 +1120,8 @@ class ListItemAdapter : PullRequestListItemModel public IList Reviews { get; set; } public LastCommitSummaryAdapter LastCommit { get; set; } + + public string BaseRefName { get; set; } } class ReviewAdapter @@ -1036,6 +1141,7 @@ class LastCommitSummaryAdapter class CheckSuiteSummaryModel { public List CheckRuns { get; set; } + public string ApplicationName { get; set; } } class CheckRunSummaryModel @@ -1047,6 +1153,7 @@ class CheckRunSummaryModel class StatusSummaryModel { public StatusState State { get; set; } + public string Context { get; set; } } } } diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs index b60cf0e70b..f4f0a8693b 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs @@ -33,7 +33,7 @@ public PullRequestListItemViewModel(PullRequestListItemModel model) public IActorViewModel Author { get; } /// - public PullRequestChecksState Checks { get; } + public PullRequestChecksSummaryState Checks { get; } /// public int CommentCount { get; } diff --git a/src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs b/src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs index 0c724bf9f0..4e6350229d 100644 --- a/src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs +++ b/src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs @@ -700,7 +700,7 @@ ActionData FilteredInsert(ActionData data) } /// - /// Checks if the object being moved affects the filtered list in any way and update + /// OtherChecks if the object being moved affects the filtered list in any way and update /// the list accordingly /// /// @@ -756,7 +756,7 @@ ActionData FilteredMove(ActionData data) } /// - /// Checks if the object being moved affects the filtered list in any way and update + /// OtherChecks if the object being moved affects the filtered list in any way and update /// the list accordingly /// /// diff --git a/src/GitHub.Exports.Reactive/Services/IGitClient.cs b/src/GitHub.Exports.Reactive/Services/IGitClient.cs index 81fbbafebe..ef02f0c0cf 100644 --- a/src/GitHub.Exports.Reactive/Services/IGitClient.cs +++ b/src/GitHub.Exports.Reactive/Services/IGitClient.cs @@ -57,7 +57,7 @@ public interface IGitClient Task Fetch(IRepository repository, UriString remoteUri, params string[] refspecs); /// - /// Checks out a branch. + /// OtherChecks out a branch. /// /// The repository to carry out the checkout on /// The name of the branch @@ -178,7 +178,7 @@ public interface IGitClient Task ExtractFileBinary(IRepository repository, string commitSha, string fileName); /// - /// Checks whether the latest commit of a file in the repository has the specified file + /// OtherChecks whether the latest commit of a file in the repository has the specified file /// contents. /// /// The repository. @@ -203,7 +203,7 @@ public interface IGitClient Task GetPullRequestMergeBase(IRepository repo, UriString targetCloneUrl, string baseSha, string headSha, string baseRef, int pullNumber); /// - /// Checks whether the current head is pushed to its remote tracking branch. + /// OtherChecks whether the current head is pushed to its remote tracking branch. /// /// The repository. /// diff --git a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs index 48837ce2d6..54617c97cc 100644 --- a/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs +++ b/src/GitHub.Exports.Reactive/Services/IPullRequestService.cs @@ -47,7 +47,7 @@ IObservable CreatePullRequest(IModelService modelService, string title, string body); /// - /// Checks whether the working directory for the specified repository is in a clean state. + /// OtherChecks whether the working directory for the specified repository is in a clean state. /// /// The repository. /// @@ -61,7 +61,7 @@ IObservable CreatePullRequest(IModelService modelService, IObservable CountSubmodulesToSync(ILocalRepositoryModel repository); /// - /// Checks out a pull request to a local branch. + /// OtherChecks out a pull request to a local branch. /// /// The repository. /// The pull request details. diff --git a/src/GitHub.Exports.Reactive/Services/IRepositoryCloneService.cs b/src/GitHub.Exports.Reactive/Services/IRepositoryCloneService.cs index a4810bf742..a05e4c6005 100644 --- a/src/GitHub.Exports.Reactive/Services/IRepositoryCloneService.cs +++ b/src/GitHub.Exports.Reactive/Services/IRepositoryCloneService.cs @@ -48,7 +48,7 @@ Task CloneOrOpenRepository( object progress = null); /// - /// Checks whether the specified destination directory already exists. + /// OtherChecks whether the specified destination directory already exists. /// /// The destination path. /// @@ -57,7 +57,7 @@ Task CloneOrOpenRepository( bool DestinationDirectoryExists(string path); /// - /// Checks whether the specified destination file already exists. + /// OtherChecks whether the specified destination file already exists. /// /// The destination file. /// diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs index 37e87ed78b..4fe726aa16 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestDetailViewModel.cs @@ -176,7 +176,7 @@ public interface IPullRequestDetailViewModel : IPanePageViewModel, IOpenInBrowse ReactiveCommand ShowReview { get; } /// - /// Gets the latest pull request Checks & Statuses + /// Gets the latest pull request OtherChecks & Statuses /// IReadOnlyList Checks { get; } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs index f8fa89c351..0f135924b5 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs @@ -32,6 +32,6 @@ public interface IPullRequestListItemViewModel : IIssueListItemViewModelBase /// /// Gets the pull request checks and statuses summary /// - PullRequestChecksState Checks { get; } + PullRequestChecksSummaryState Checks { get; } } } diff --git a/src/GitHub.Exports/Models/IPullRequestModel.cs b/src/GitHub.Exports/Models/IPullRequestModel.cs index 4d78de08ab..ae8b8f148d 100644 --- a/src/GitHub.Exports/Models/IPullRequestModel.cs +++ b/src/GitHub.Exports/Models/IPullRequestModel.cs @@ -21,6 +21,16 @@ public enum PullRequestChecksState Failure } + public enum PullRequestChecksSummaryState + { + None, + Pending, + Success, + SuccessWithFailure, + SuccessWithPending, + Failure + } + public interface IPullRequestModel : ICopyable, IEquatable, IComparable { diff --git a/src/GitHub.Exports/Models/PullRequestDetailModel.cs b/src/GitHub.Exports/Models/PullRequestDetailModel.cs index 975c6511d2..6c765b01a1 100644 --- a/src/GitHub.Exports/Models/PullRequestDetailModel.cs +++ b/src/GitHub.Exports/Models/PullRequestDetailModel.cs @@ -93,7 +93,7 @@ public class PullRequestDetailModel public IReadOnlyList Threads { get; set; } /// - /// Gets or sets a collection of pull request Checks Suites + /// Gets or sets a collection of pull request OtherChecks Suites /// public IReadOnlyList CheckSuites { get; set; } diff --git a/src/GitHub.Exports/Models/PullRequestListItemModel.cs b/src/GitHub.Exports/Models/PullRequestListItemModel.cs index f6a9a7fe55..18a104899f 100644 --- a/src/GitHub.Exports/Models/PullRequestListItemModel.cs +++ b/src/GitHub.Exports/Models/PullRequestListItemModel.cs @@ -40,7 +40,17 @@ public class PullRequestListItemModel /// /// Gets the pull request checks and statuses summary /// - public PullRequestChecksState Checks { get; set; } + public PullRequestChecksState RequiredChecks { get; set; } + + /// + /// Gets the pull request checks and statuses summary + /// + public PullRequestChecksState OtherChecks { get; set; } + + /// + /// Gets the pull request checks and statuses summary + /// + public PullRequestChecksSummaryState Checks { get; set; } /// /// Gets or sets the date/time at which the pull request was last updated. diff --git a/src/GitHub.Exports/Services/IEnterpriseCapabilitiesService.cs b/src/GitHub.Exports/Services/IEnterpriseCapabilitiesService.cs index 875916c722..1e091977bf 100644 --- a/src/GitHub.Exports/Services/IEnterpriseCapabilitiesService.cs +++ b/src/GitHub.Exports/Services/IEnterpriseCapabilitiesService.cs @@ -33,7 +33,7 @@ public interface IEnterpriseCapabilitiesService Task Probe(Uri enterpriseBaseUrl); /// - /// Checks the login methods supported by an enterprise instance. + /// OtherChecks the login methods supported by an enterprise instance. /// /// The URL to test. /// The supported login methods. diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml index 4d7e261552..19120e288f 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml @@ -101,6 +101,10 @@ + + + + diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index c8e437cb8d..05c13e6424 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -576,6 +576,7 @@ static PullRequestService CreatePullRequestService(Repository repo) gitService, Substitute.For(), Substitute.For(), + Substitute.For(), serviceProvider.GetOperatingSystem(), Substitute.For()); return service; @@ -685,6 +686,7 @@ public void CreatePullRequestAllArgsMandatory() serviceProvider.GetGitService(), Substitute.For(), Substitute.For(), + Substitute.For(), serviceProvider.GetOperatingSystem(), Substitute.For()); @@ -894,6 +896,7 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameForPullRequestsWithNo MockGitService(), Substitute.For(), Substitute.For(), + Substitute.For(), Substitute.For(), Substitute.For()); @@ -1046,6 +1049,7 @@ static PullRequestService CreateTarget( IGitService gitService = null, IVSGitExt gitExt = null, IGraphQLClientFactory graphqlFactory = null, + IRepositoryService repositoryService = null, IOperatingSystem os = null, IUsageTracker usageTracker = null) { @@ -1055,12 +1059,14 @@ static PullRequestService CreateTarget( graphqlFactory = graphqlFactory ?? Substitute.For(); os = os ?? Substitute.For(); usageTracker = usageTracker ?? Substitute.For(); + repositoryService = repositoryService ?? Substitute.For(); return new PullRequestService( gitClient, gitService, gitExt, graphqlFactory, + repositoryService, os, usageTracker); } diff --git a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs index 5b21260e0a..cd7fa8b8ed 100644 --- a/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/GitHubPane/PullRequestCreationViewModelTests.cs @@ -128,7 +128,9 @@ static TestData PrepareTestData( public async Task TargetBranchDisplayNameIncludesRepoOwnerWhenForkAsync() { var data = PrepareTestData("octokit.net", "shana", "master", "octokit", "master", "origin", true, true); - var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), Substitute.For(), data.ServiceProvider.GetOperatingSystem(), Substitute.For()); + var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), + Substitute.For(), Substitute.For(), + data.ServiceProvider.GetOperatingSystem(), Substitute.For()); prservice.GetPullRequestTemplate(data.ActiveRepo).Returns(Observable.Empty()); var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, Substitute.For()); await vm.InitializeAsync(data.ActiveRepo, data.Connection); @@ -164,7 +166,9 @@ public async Task CreatingPRsAsync( var targetBranch = data.TargetBranch; var ms = data.ModelService; - var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), Substitute.For(), data.ServiceProvider.GetOperatingSystem(), Substitute.For()); + var prservice = new PullRequestService(data.GitClient, data.GitService, Substitute.For(), + Substitute.For(), Substitute.For(), + data.ServiceProvider.GetOperatingSystem(), Substitute.For()); var vm = new PullRequestCreationViewModel(data.GetModelServiceFactory(), prservice, data.NotificationService, Substitute.For()); await vm.InitializeAsync(data.ActiveRepo, data.Connection); From bc9284290a6bc59ecead7d550e38c3c4e8ce6740 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Fri, 2 Nov 2018 12:51:14 -0400 Subject: [PATCH 08/25] Adding a required tag to PullRequestCheckViewModel --- .../PullRequestCheckViewModelDesigner.cs | 2 ++ src/GitHub.App/Services/PullRequestService.cs | 8 ++--- src/GitHub.App/Services/RepositoryService.cs | 7 +++++ .../GitHubPane/PullRequestCheckViewModel.cs | 4 +++ .../GitHubPane/IPullRequestCheckViewModel.cs | 2 ++ src/GitHub.Exports/Models/CheckRunModel.cs | 2 ++ src/GitHub.Exports/Models/StatusModel.cs | 2 ++ .../Services/IRepositoryService.cs | 2 ++ .../Services/PullRequestSessionService.cs | 30 ++++++++++++++++--- .../GitHubPane/PullRequestCheckView.xaml | 12 +++++--- 10 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs index 3011e581c1..086e842644 100644 --- a/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestCheckViewModelDesigner.cs @@ -9,6 +9,8 @@ namespace GitHub.SampleData { public sealed class PullRequestCheckViewModelDesigner : ViewModelBase, IPullRequestCheckViewModel { + public bool IsRequired { get; } = true; + public string Title { get; set; } = "continuous-integration/appveyor/pr"; public string Description { get; set; } = "AppVeyor build failed"; diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index e7c8f6091f..240be1daf8 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -115,10 +115,10 @@ public async Task> ReadPullRequests( CheckSuites = commit.Commit.CheckSuites(null, null, null, null, null).AllPages(10) .Select(suite => new CheckSuiteSummaryModel { - ApplicationName = suite.App != null ? suite.App.Name : "Private Application", CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10) .Select(run => new CheckRunSummaryModel { + Name = run.Name, Conclusion = run.Conclusion.FromGraphQl(), Status = run.Status.FromGraphQl() }).ToList() @@ -233,8 +233,8 @@ public async Task> ReadPullRequests( if (protectedBranchContexts != null) { var requiredCheckRuns = item.LastCommit?.CheckSuites? - .Where(model => protectedBranchContexts.Contains(model.ApplicationName)) .SelectMany(checkSuite => checkSuite.CheckRuns) + .Where(model => protectedBranchContexts.Contains(model.Name)) .ToArray(); var requiredStatues = item.LastCommit?.Statuses @@ -249,8 +249,8 @@ public async Task> ReadPullRequests( } var checkRuns = item.LastCommit?.CheckSuites? - .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.ApplicationName)) .SelectMany(checkSuite => checkSuite.CheckRuns) + .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.Name)) .ToArray(); var statuses = item.LastCommit?.Statuses @@ -1141,11 +1141,11 @@ class LastCommitSummaryAdapter class CheckSuiteSummaryModel { public List CheckRuns { get; set; } - public string ApplicationName { get; set; } } class CheckRunSummaryModel { + public string Name { get; set; } public CheckConclusionState? Conclusion { get; set; } public CheckStatusState Status { get; set; } } diff --git a/src/GitHub.App/Services/RepositoryService.cs b/src/GitHub.App/Services/RepositoryService.cs index d4d183ea30..2212445de4 100644 --- a/src/GitHub.App/Services/RepositoryService.cs +++ b/src/GitHub.App/Services/RepositoryService.cs @@ -83,5 +83,12 @@ public async Task> GetProtectedBranches(HostAddress addre var graphql = await graphqlFactory.CreateConnection(address).ConfigureAwait(false); return await graphql.Run(queryProtectedBranches, vars).ConfigureAwait(false); } + + public async Task GetProtectedBranch(HostAddress address, string owner, string name, string branchName) + { + Guard.ArgumentNotNull(branchName, nameof(branchName)); + var protectedBranches = await GetProtectedBranches(address, owner, name).ConfigureAwait(false); + return protectedBranches.FirstOrDefault(branch => branch.Name.Equals(branchName, StringComparison.InvariantCultureIgnoreCase)); + } } } diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs index f95bd95fd1..75b162e626 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs @@ -45,6 +45,7 @@ public static IEnumerable Build(IViewViewModelFactor var pullRequestCheckViewModel = (PullRequestCheckViewModel) viewViewModelFactory.CreateViewModel(); pullRequestCheckViewModel.CheckType = PullRequestCheckType.StatusApi; + pullRequestCheckViewModel.IsRequired = model.IsRequired; pullRequestCheckViewModel.Title = model.Context; pullRequestCheckViewModel.Description = model.Description; pullRequestCheckViewModel.Status = checkStatus; @@ -91,6 +92,7 @@ public static IEnumerable Build(IViewViewModelFactor var pullRequestCheckViewModel = (PullRequestCheckViewModel)viewViewModelFactory.CreateViewModel(); pullRequestCheckViewModel.CheckType = PullRequestCheckType.ChecksApi; + pullRequestCheckViewModel.IsRequired = model.IsRequired; pullRequestCheckViewModel.Title = model.Name; pullRequestCheckViewModel.Description = model.Summary; pullRequestCheckViewModel.Status = checkStatus; @@ -124,6 +126,8 @@ private void DoOpenDetailsUrl() usageTracker.IncrementCounter(expression).Forget(); } + public bool IsRequired { get; private set; } + public string Title { get; private set; } public string Description { get; private set; } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs index 1a9d658a39..c54365c0a1 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestCheckViewModel.cs @@ -11,6 +11,8 @@ namespace GitHub.ViewModels.GitHubPane /// public interface IPullRequestCheckViewModel: IViewModel { + bool IsRequired { get; } + /// /// The title of the Status/Check /// diff --git a/src/GitHub.Exports/Models/CheckRunModel.cs b/src/GitHub.Exports/Models/CheckRunModel.cs index a25335c8bb..e1c78b0426 100644 --- a/src/GitHub.Exports/Models/CheckRunModel.cs +++ b/src/GitHub.Exports/Models/CheckRunModel.cs @@ -33,5 +33,7 @@ public class CheckRunModel /// The summary of a Check Run. /// public string Summary { get; set; } + + public bool IsRequired { get; set; } } } \ No newline at end of file diff --git a/src/GitHub.Exports/Models/StatusModel.cs b/src/GitHub.Exports/Models/StatusModel.cs index 3b0832caa0..a911bfa7e0 100644 --- a/src/GitHub.Exports/Models/StatusModel.cs +++ b/src/GitHub.Exports/Models/StatusModel.cs @@ -24,5 +24,7 @@ public class StatusModel /// The descritption for the Status /// public string Description { get; set; } + + public bool IsRequired { get; set; } } } \ No newline at end of file diff --git a/src/GitHub.Exports/Services/IRepositoryService.cs b/src/GitHub.Exports/Services/IRepositoryService.cs index 975996bc69..c0e8ea4fd7 100644 --- a/src/GitHub.Exports/Services/IRepositoryService.cs +++ b/src/GitHub.Exports/Services/IRepositoryService.cs @@ -21,5 +21,7 @@ public interface IRepositoryService Task<(string owner, string name)?> FindParent(HostAddress address, string owner, string name); Task> GetProtectedBranches(HostAddress address, string owner, string name); + + Task GetProtectedBranch(HostAddress address, string owner, string name, string branchName); } } diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index d7db28e6f5..8e41d6d57f 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -57,6 +57,7 @@ public class PullRequestSessionService : IPullRequestSessionService readonly IDiffService diffService; readonly IApiClientFactory apiClientFactory; readonly IGraphQLClientFactory graphqlFactory; + readonly IRepositoryService repositoryService; readonly IUsageTracker usageTracker; readonly IDictionary, string> mergeBaseCache; @@ -67,6 +68,7 @@ public PullRequestSessionService( IDiffService diffService, IApiClientFactory apiClientFactory, IGraphQLClientFactory graphqlFactory, + IRepositoryService repositoryService, IUsageTracker usageTracker) { this.gitService = gitService; @@ -74,6 +76,7 @@ public PullRequestSessionService( this.diffService = diffService; this.apiClientFactory = apiClientFactory; this.graphqlFactory = graphqlFactory; + this.repositoryService = repositoryService; this.usageTracker = usageTracker; mergeBaseCache = new Dictionary, string>(); @@ -351,9 +354,12 @@ public virtual async Task ReadPullRequestDetail(HostAddr var connection = await graphqlFactory.CreateConnection(address); var result = await connection.Run(readPullRequest, vars); + var protectedBranches = await repositoryService.GetProtectedBranch(address, owner, name, result.BaseRefName); + var protectedContexts = protectedBranches != null ? new HashSet(protectedBranches.RequiredStatusCheckContexts) : null; + var apiClient = await apiClientFactory.Create(address); var files = await apiClient.GetPullRequestFiles(owner, name, number).ToList(); - var lastCommitModel = await GetPullRequestLastCommitAdapter(address, owner, name, number); + var lastCommitModel = await GetPullRequestLastCommitAdapter(address, owner, name, number, protectedContexts); result.Statuses = lastCommitModel.Statuses; result.CheckSuites = lastCommitModel.CheckSuites; @@ -752,7 +758,8 @@ Task GetRepository(ILocalRepositoryModel repository) return Task.Factory.StartNew(() => gitService.GetRepository(repository.LocalPath)); } - async Task GetPullRequestLastCommitAdapter(HostAddress address, string owner, string name, int number) + async Task GetPullRequestLastCommitAdapter(HostAddress address, string owner, string name, + int number, HashSet protectedContexts) { ICompiledQuery> query; if (address.IsGitHubDotCom()) @@ -827,8 +834,23 @@ async Task GetPullRequestLastCommitAdapter(HostAddress addres }; var connection = await graphqlFactory.CreateConnection(address); - var result = await connection.Run(query, vars); - return result.First(); + var results = await connection.Run(query, vars); + var result = results.First(); + + foreach (var resultCheckSuite in result.CheckSuites) + { + foreach (var checkRunModel in resultCheckSuite.CheckRuns) + { + checkRunModel.IsRequired = protectedContexts?.Contains(checkRunModel.Name) ?? false; + } + } + + foreach (var resultStatus in result.Statuses) + { + resultStatus.IsRequired = protectedContexts?.Contains(resultStatus.Context) ?? false; + } + + return result; } static void BuildPullRequestThreads(PullRequestDetailModel model) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index d04daeeda1..89017fb747 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -45,10 +45,14 @@ - + + + + From 5d0c825659f2fd39a1419da8f26ae8b4033ff7fd Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Fri, 2 Nov 2018 15:05:06 -0400 Subject: [PATCH 09/25] Fix compilation error --- .../Services/PullRequestSessionServiceTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionServiceTests.cs b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionServiceTests.cs index 0ab2b674f1..51559f5f8f 100644 --- a/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionServiceTests.cs +++ b/test/GitHub.InlineReviews.UnitTests/Services/PullRequestSessionServiceTests.cs @@ -296,6 +296,7 @@ static PullRequestSessionService CreateTarget(IDiffService diffService) diffService, Substitute.For(), Substitute.For(), + Substitute.For(), Substitute.For()); } From 6e03523891013c066a83fc1d6445c66ac93c2db2 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Wed, 12 Dec 2018 17:06:36 -0500 Subject: [PATCH 10/25] Fixes needed for compilation --- .../GitHubPane/PullRequestCheckViewModel.cs | 5 +++-- .../Views/GitHubPane/PullRequestCheckView.xaml | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs index aeb4db8272..2a09fcad72 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs @@ -10,6 +10,7 @@ using GitHub.Models; using GitHub.Primitives; using GitHub.Services; +using GitHub.UI.Converters; using ReactiveUI; namespace GitHub.ViewModels.GitHubPane @@ -105,9 +106,9 @@ public static IEnumerable Build(IViewViewModelFactor pullRequestCheckViewModel.HasAnnotations = arg.checkRun.Annotations?.Any() ?? false; pullRequestCheckViewModel.Title = arg.checkRun.Name; - if (model.StartedAt.HasValue && model.CompletedAt.HasValue) + if (arg.checkRun.StartedAt.HasValue && arg.checkRun.CompletedAt.HasValue) { - var timeSpanString = TimeSpanExtensions.Humanize(model.CompletedAt.Value - model.StartedAt.Value, CultureInfo.CurrentCulture, TimeSpanExtensions.OutputTense.Completed); + var timeSpanString = TimeSpanExtensions.Humanize(arg.checkRun.CompletedAt.Value - arg.checkRun.StartedAt.Value, CultureInfo.CurrentCulture, TimeSpanExtensions.OutputTense.Completed); pullRequestCheckViewModel.DurationStatus = $"{checkStatus} - {timeSpanString}"; } diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 33b0087e64..6703fd1920 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -35,23 +35,23 @@ - - - + + + - From a489cbed354ea6886566522321a89e7ea5a8d318 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 13 Dec 2018 09:58:20 -0500 Subject: [PATCH 12/25] Fxing how the model is populated --- .../ViewModels/GitHubPane/PullRequestCheckViewModel.cs | 2 +- src/GitHub.Exports/Models/CheckRunModel.cs | 5 +++++ .../Services/PullRequestSessionService.cs | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs index 2a09fcad72..d3ceed939b 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestCheckViewModel.cs @@ -112,7 +112,7 @@ public static IEnumerable Build(IViewViewModelFactor pullRequestCheckViewModel.DurationStatus = $"{checkStatus} - {timeSpanString}"; } - pullRequestCheckViewModel.Description = arg.checkRun.Summary; + pullRequestCheckViewModel.Description = arg.checkRun.Title; pullRequestCheckViewModel.Status = checkStatus; pullRequestCheckViewModel.DetailsUrl = new Uri(arg.checkRun.DetailsUrl); return pullRequestCheckViewModel; diff --git a/src/GitHub.Exports/Models/CheckRunModel.cs b/src/GitHub.Exports/Models/CheckRunModel.cs index cc965c6062..2587ab2a03 100644 --- a/src/GitHub.Exports/Models/CheckRunModel.cs +++ b/src/GitHub.Exports/Models/CheckRunModel.cs @@ -48,6 +48,11 @@ public class CheckRunModel /// public string DetailsUrl { get; set; } + /// + /// The title of a Check Run. + /// + public string Title { get; set; } + /// /// The summary of a Check Run. /// diff --git a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs index 41157c9663..129b0a59db 100644 --- a/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs +++ b/src/GitHub.InlineReviews/Services/PullRequestSessionService.cs @@ -796,6 +796,8 @@ async Task GetPullRequestLastCommitAdapter(HostAddress addres Conclusion = run.Conclusion.FromGraphQl(), Status = run.Status.FromGraphQl(), Name = run.Name, + Title = run.Title, + Summary = run.Summary, DetailsUrl = run.Permalink, StartedAt = run.StartedAt, CompletedAt = run.CompletedAt, From f25c4881e33708d5af60c76dbcfb41d9dcfc866a Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 13 Dec 2018 10:54:45 -0500 Subject: [PATCH 13/25] Reverting functionality to process protected branches in the pull request list view --- .../PullRequestListItemViewModelDesigner.cs | 2 +- src/GitHub.App/Services/PullRequestService.cs | 205 ++++-------------- .../PullRequestListItemViewModel.cs | 2 +- .../IPullRequestListItemViewModel.cs | 2 +- .../Models/PullRequestListItemModel.cs | 12 +- .../GitHubPane/PullRequestListItemView.xaml | 4 - .../Services/PullRequestServiceTests.cs | 6 - 7 files changed, 49 insertions(+), 184 deletions(-) diff --git a/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs b/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs index aba518d750..500089fb84 100644 --- a/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs +++ b/src/GitHub.App/SampleData/PullRequestListItemViewModelDesigner.cs @@ -17,6 +17,6 @@ public class PullRequestListItemViewModelDesigner : ViewModelBase, IPullRequestL public int Number { get; set; } public string Title { get; set; } public DateTimeOffset UpdatedAt { get; set; } - public PullRequestChecksSummaryState Checks { get; set; } + public PullRequestChecksState Checks { get; set; } } } diff --git a/src/GitHub.App/Services/PullRequestService.cs b/src/GitHub.App/Services/PullRequestService.cs index 6b19ff81f5..abfc1feac1 100644 --- a/src/GitHub.App/Services/PullRequestService.cs +++ b/src/GitHub.App/Services/PullRequestService.cs @@ -26,7 +26,6 @@ using static Octokit.GraphQL.Variable; using CheckConclusionState = GitHub.Models.CheckConclusionState; using CheckStatusState = GitHub.Models.CheckStatusState; -using ProtectedBranch = GitHub.Models.ProtectedBranch; using StatusState = GitHub.Models.StatusState; namespace GitHub.Services @@ -56,7 +55,6 @@ public class PullRequestService : IPullRequestService readonly IGitService gitService; readonly IVSGitExt gitExt; readonly IGraphQLClientFactory graphqlFactory; - readonly IRepositoryService repositoryService; readonly IOperatingSystem os; readonly IUsageTracker usageTracker; @@ -66,7 +64,6 @@ public PullRequestService( IGitService gitService, IVSGitExt gitExt, IGraphQLClientFactory graphqlFactory, - IRepositoryService repositoryService, IOperatingSystem os, IUsageTracker usageTracker) { @@ -74,7 +71,6 @@ public PullRequestService( this.gitService = gitService; this.gitExt = gitExt; this.graphqlFactory = graphqlFactory; - this.repositoryService = repositoryService; this.os = os; this.usageTracker = usageTracker; } @@ -108,7 +104,6 @@ public async Task> ReadPullRequests( Items = page.Nodes.Select(pr => new ListItemAdapter { Id = pr.Id.Value, - BaseRefName = pr.BaseRefName, LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit => new LastCommitSummaryAdapter { @@ -118,7 +113,6 @@ public async Task> ReadPullRequests( CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10) .Select(run => new CheckRunSummaryModel { - Name = run.Name, Conclusion = run.Conclusion.FromGraphQl(), Status = run.Status.FromGraphQl() }).ToList(), @@ -127,7 +121,6 @@ public async Task> ReadPullRequests( .Select(context => context.Contexts.Select(statusContext => new StatusSummaryModel { - Context = statusContext.Context, State = statusContext.State.FromGraphQl(), }).ToList() ).SingleOrDefault() @@ -172,7 +165,6 @@ public async Task> ReadPullRequests( Items = page.Nodes.Select(pr => new ListItemAdapter { Id = pr.Id.Value, - BaseRefName = pr.BaseRefName, LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit => new LastCommitSummaryAdapter { @@ -208,11 +200,6 @@ public async Task> ReadPullRequests( query = readPullRequestsEnterprise; } - var protectedBranches = await repositoryService.GetProtectedBranches(address, owner, name) - .ConfigureAwait(false); - - var protectedBranchesContextsDictionary = protectedBranches.ToDictionary(branch => branch.Name, branch => new HashSet(branch.RequiredStatusCheckContexts)); - var graphql = await graphqlFactory.CreateConnection(address); var vars = new Dictionary { @@ -226,172 +213,74 @@ public async Task> ReadPullRequests( foreach (var item in result.Items.Cast()) { - HashSet protectedBranchContexts; - protectedBranchesContextsDictionary.TryGetValue(item.BaseRefName, out protectedBranchContexts); - item.CommentCount += item.Reviews.Sum(x => x.Count); item.Reviews = null; - if (protectedBranchContexts != null) - { - var requiredCheckRuns = item.LastCommit?.CheckSuites? - .SelectMany(checkSuite => checkSuite.CheckRuns) - .Where(model => protectedBranchContexts.Contains(model.Name)) - .ToArray(); + var checkRuns = item.LastCommit?.CheckSuites?.SelectMany(model => model.CheckRuns).ToArray(); - var requiredStatues = item.LastCommit?.Statuses - .Where(model => protectedBranchContexts.Contains(model.Context)) - .ToArray(); + var hasCheckRuns = checkRuns?.Any() ?? false; + var hasStatuses = item.LastCommit?.Statuses?.Any() ?? false; - item.RequiredChecks = CalculatePullRequestCheckState(requiredCheckRuns, requiredStatues); - } - else + if (!hasCheckRuns && !hasStatuses) { - item.RequiredChecks = PullRequestChecksState.None; + item.Checks = PullRequestChecksState.None; } - - var checkRuns = item.LastCommit?.CheckSuites? - .SelectMany(checkSuite => checkSuite.CheckRuns) - .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.Name)) - .ToArray(); - - var statuses = item.LastCommit?.Statuses - .Where(model => protectedBranchContexts == null || !protectedBranchContexts.Contains(model.Context)) - .ToArray(); - - item.OtherChecks = CalculatePullRequestCheckState(checkRuns, statuses); - - switch (item.RequiredChecks) + else { - case PullRequestChecksState.None: - item.Checks = PullRequestChecksSummaryState.None; - break; - case PullRequestChecksState.Pending: - item.Checks = PullRequestChecksSummaryState.Pending; - break; - case PullRequestChecksState.Success: - item.Checks = PullRequestChecksSummaryState.Success; - break; - case PullRequestChecksState.Failure: - item.Checks = PullRequestChecksSummaryState.Failure; - break; - default: - throw new ArgumentOutOfRangeException(); - } + var checksHasFailure = false; + var checksHasCompleteSuccess = true; - if (item.RequiredChecks != item.OtherChecks) - { - switch (item.RequiredChecks) + if (hasCheckRuns) { - case PullRequestChecksState.None: - switch (item.OtherChecks) - { - case PullRequestChecksState.None: - item.Checks = PullRequestChecksSummaryState.None; - break; - case PullRequestChecksState.Pending: - item.Checks = PullRequestChecksSummaryState.Pending; - break; - case PullRequestChecksState.Success: - item.Checks = PullRequestChecksSummaryState.Success; - break; - case PullRequestChecksState.Failure: - item.Checks = PullRequestChecksSummaryState.Failure; - break; - default: - throw new ArgumentOutOfRangeException(); - } - break; - case PullRequestChecksState.Pending: - item.Checks = PullRequestChecksSummaryState.Pending; - break; - case PullRequestChecksState.Success: - switch (item.OtherChecks) - { - case PullRequestChecksState.Pending: - item.Checks = PullRequestChecksSummaryState.SuccessWithPending; - break; - case PullRequestChecksState.Failure: - item.Checks = PullRequestChecksSummaryState.SuccessWithFailure; - break; - } - break; - case PullRequestChecksState.Failure: - item.Checks = PullRequestChecksSummaryState.Failure; - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - item.LastCommit = null; - } + checksHasFailure = checkRuns + .Any(model => model.Conclusion.HasValue + && (model.Conclusion.Value == CheckConclusionState.Failure + || model.Conclusion.Value == CheckConclusionState.ActionRequired)); - return result; - } + if (!checksHasFailure) + { + checksHasCompleteSuccess = checkRuns + .All(model => model.Conclusion.HasValue + && (model.Conclusion.Value == CheckConclusionState.Success + || model.Conclusion.Value == CheckConclusionState.Neutral)); + } + } - static PullRequestChecksState CalculatePullRequestCheckState(IList checkRuns, IList statusSummaryModels) - { - var hasCheckRuns = checkRuns?.Any() ?? false; - var hasStatuses = statusSummaryModels?.Any() ?? false; + var statusHasFailure = false; + var statusHasCompleteSuccess = true; - PullRequestChecksState resultState; - if (!hasCheckRuns && !hasStatuses) - { - resultState = PullRequestChecksState.None; - } - else - { - var checksHasFailure = false; - var checksHasCompleteSuccess = true; + if (!checksHasFailure && hasStatuses) + { + statusHasFailure = item.LastCommit + .Statuses + .Any(status => status.State == StatusState.Failure + || status.State == StatusState.Error); - if (hasCheckRuns) - { - checksHasFailure = checkRuns - .Any(model => model.Conclusion.HasValue - && (model.Conclusion.Value == CheckConclusionState.Failure - || model.Conclusion.Value == CheckConclusionState.ActionRequired)); + if (!statusHasFailure) + { + statusHasCompleteSuccess = + item.LastCommit.Statuses.All(status => status.State == StatusState.Success); + } + } - if (!checksHasFailure) + if (checksHasFailure || statusHasFailure) { - checksHasCompleteSuccess = checkRuns - .All(model => model.Conclusion.HasValue - && (model.Conclusion.Value == CheckConclusionState.Success - || model.Conclusion.Value == CheckConclusionState.Neutral)); + item.Checks = PullRequestChecksState.Failure; } - } - - var statusHasFailure = false; - var statusHasCompleteSuccess = true; - - if (!checksHasFailure && hasStatuses) - { - statusHasFailure = statusSummaryModels - .Any(status => status.State == StatusState.Failure - || status.State == StatusState.Error); - - if (!statusHasFailure) + else if (statusHasCompleteSuccess && checksHasCompleteSuccess) { - statusHasCompleteSuccess = - statusSummaryModels.All(status => status.State == StatusState.Success); + item.Checks = PullRequestChecksState.Success; + } + else + { + item.Checks = PullRequestChecksState.Pending; } } - if (checksHasFailure || statusHasFailure) - { - resultState = PullRequestChecksState.Failure; - } - else if (statusHasCompleteSuccess && checksHasCompleteSuccess) - { - resultState = PullRequestChecksState.Success; - } - else - { - resultState = PullRequestChecksState.Pending; - } + item.LastCommit = null; } - return resultState; + return result; } public async Task> ReadAssignableUsers( @@ -1122,8 +1011,6 @@ class ListItemAdapter : PullRequestListItemModel public IList Reviews { get; set; } public LastCommitSummaryAdapter LastCommit { get; set; } - - public string BaseRefName { get; set; } } class ReviewAdapter @@ -1147,7 +1034,6 @@ class CheckSuiteSummaryModel class CheckRunSummaryModel { - public string Name { get; set; } public CheckConclusionState? Conclusion { get; set; } public CheckStatusState Status { get; set; } } @@ -1155,7 +1041,6 @@ class CheckRunSummaryModel class StatusSummaryModel { public StatusState State { get; set; } - public string Context { get; set; } } } } diff --git a/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs b/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs index f4f0a8693b..b60cf0e70b 100644 --- a/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs +++ b/src/GitHub.App/ViewModels/GitHubPane/PullRequestListItemViewModel.cs @@ -33,7 +33,7 @@ public PullRequestListItemViewModel(PullRequestListItemModel model) public IActorViewModel Author { get; } /// - public PullRequestChecksSummaryState Checks { get; } + public PullRequestChecksState Checks { get; } /// public int CommentCount { get; } diff --git a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs index 0f135924b5..f8fa89c351 100644 --- a/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs +++ b/src/GitHub.Exports.Reactive/ViewModels/GitHubPane/IPullRequestListItemViewModel.cs @@ -32,6 +32,6 @@ public interface IPullRequestListItemViewModel : IIssueListItemViewModelBase /// /// Gets the pull request checks and statuses summary /// - PullRequestChecksSummaryState Checks { get; } + PullRequestChecksState Checks { get; } } } diff --git a/src/GitHub.Exports/Models/PullRequestListItemModel.cs b/src/GitHub.Exports/Models/PullRequestListItemModel.cs index 18a104899f..f6a9a7fe55 100644 --- a/src/GitHub.Exports/Models/PullRequestListItemModel.cs +++ b/src/GitHub.Exports/Models/PullRequestListItemModel.cs @@ -40,17 +40,7 @@ public class PullRequestListItemModel /// /// Gets the pull request checks and statuses summary /// - public PullRequestChecksState RequiredChecks { get; set; } - - /// - /// Gets the pull request checks and statuses summary - /// - public PullRequestChecksState OtherChecks { get; set; } - - /// - /// Gets the pull request checks and statuses summary - /// - public PullRequestChecksSummaryState Checks { get; set; } + public PullRequestChecksState Checks { get; set; } /// /// Gets or sets the date/time at which the pull request was last updated. diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml index 19120e288f..4d7e261552 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestListItemView.xaml @@ -101,10 +101,6 @@ - - - - diff --git a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs index 6bc72c00f3..6fedcf1526 100644 --- a/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/PullRequestServiceTests.cs @@ -576,7 +576,6 @@ static PullRequestService CreatePullRequestService(Repository repo) gitService, Substitute.For(), Substitute.For(), - Substitute.For(), serviceProvider.GetOperatingSystem(), Substitute.For()); return service; @@ -690,7 +689,6 @@ public void CreatePullRequestAllArgsMandatory() serviceProvider.GetGitService(), Substitute.For(), Substitute.For(), - Substitute.For(), serviceProvider.GetOperatingSystem(), Substitute.For()); @@ -904,7 +902,6 @@ public async Task ShouldReturnCorrectDefaultLocalBranchNameForPullRequestsWithNo MockGitService(), Substitute.For(), Substitute.For(), - Substitute.For(), Substitute.For(), Substitute.For()); @@ -1062,7 +1059,6 @@ static PullRequestService CreateTarget( IGitService gitService = null, IVSGitExt gitExt = null, IGraphQLClientFactory graphqlFactory = null, - IRepositoryService repositoryService = null, IOperatingSystem os = null, IUsageTracker usageTracker = null) { @@ -1072,14 +1068,12 @@ static PullRequestService CreateTarget( graphqlFactory = graphqlFactory ?? Substitute.For(); os = os ?? Substitute.For(); usageTracker = usageTracker ?? Substitute.For(); - repositoryService = repositoryService ?? Substitute.For(); return new PullRequestService( gitClient, gitService, gitExt, graphqlFactory, - repositoryService, os, usageTracker); } From 1cf3c800201ba4d7c273d8e9c51508629bc513a6 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 13 Dec 2018 10:59:46 -0500 Subject: [PATCH 14/25] Repositioning --- .../Views/GitHubPane/PullRequestCheckView.xaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 8e11b97711..caf2380d7f 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -28,7 +28,6 @@ - @@ -48,13 +47,13 @@ - + - public interface IPullRequestCheckViewModel: IViewModel { + /// + /// The flag to show this Status/Check is required. + /// bool IsRequired { get; } /// diff --git a/src/GitHub.Exports/Models/CheckRunModel.cs b/src/GitHub.Exports/Models/CheckRunModel.cs index ba98d86638..41c8e112bc 100644 --- a/src/GitHub.Exports/Models/CheckRunModel.cs +++ b/src/GitHub.Exports/Models/CheckRunModel.cs @@ -59,7 +59,7 @@ public class CheckRunModel public string Summary { get; set; } /// - /// The flag that denotes if this check is required for the pull request. + /// The flag to shows this Check Run is required. /// public bool IsRequired { get; set; } diff --git a/src/GitHub.Exports/Models/StatusModel.cs b/src/GitHub.Exports/Models/StatusModel.cs index a911bfa7e0..878e6e4183 100644 --- a/src/GitHub.Exports/Models/StatusModel.cs +++ b/src/GitHub.Exports/Models/StatusModel.cs @@ -25,6 +25,9 @@ public class StatusModel /// public string Description { get; set; } + /// + /// The flag to shows this Status is required. + /// public bool IsRequired { get; set; } } } \ No newline at end of file From b7d9d2e9b5f7bf78eba5ea396e0ae5d295117eae Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 13 Dec 2018 11:13:54 -0500 Subject: [PATCH 17/25] Removing unused enum --- src/GitHub.Exports/Models/IPullRequestModel.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/GitHub.Exports/Models/IPullRequestModel.cs b/src/GitHub.Exports/Models/IPullRequestModel.cs index ae8b8f148d..4d78de08ab 100644 --- a/src/GitHub.Exports/Models/IPullRequestModel.cs +++ b/src/GitHub.Exports/Models/IPullRequestModel.cs @@ -21,16 +21,6 @@ public enum PullRequestChecksState Failure } - public enum PullRequestChecksSummaryState - { - None, - Pending, - Success, - SuccessWithFailure, - SuccessWithPending, - Failure - } - public interface IPullRequestModel : ICopyable, IEquatable, IComparable { From 20690eaf0ccc3fb8c96b623de2e24fe8eca298ff Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Thu, 13 Dec 2018 11:16:28 -0500 Subject: [PATCH 18/25] More comments --- src/GitHub.App/Services/RepositoryService.cs | 3 +++ src/GitHub.Exports/Services/IRepositoryService.cs | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/GitHub.App/Services/RepositoryService.cs b/src/GitHub.App/Services/RepositoryService.cs index fb372e6b94..0d6e081342 100644 --- a/src/GitHub.App/Services/RepositoryService.cs +++ b/src/GitHub.App/Services/RepositoryService.cs @@ -28,6 +28,7 @@ public RepositoryService(IGraphQLClientFactory graphqlFactory) this.graphqlFactory = graphqlFactory; } + /// public async Task<(string owner, string name)?> FindParent(HostAddress address, string owner, string name) { Guard.ArgumentNotNull(address, nameof(address)); @@ -53,6 +54,7 @@ public RepositoryService(IGraphQLClientFactory graphqlFactory) return result != null ? (result.Item1, result.Item2) : ((string, string)?)null; } + /// public async Task> GetProtectedBranches(HostAddress address, string owner, string name) { Guard.ArgumentNotNull(address, nameof(address)); @@ -84,6 +86,7 @@ public async Task> GetProtectedBranches(HostAddress addre return await graphql.Run(queryProtectedBranches, vars).ConfigureAwait(false); } + /// public async Task GetProtectedBranch(HostAddress address, string owner, string name, string branchName) { Guard.ArgumentNotNull(branchName, nameof(branchName)); diff --git a/src/GitHub.Exports/Services/IRepositoryService.cs b/src/GitHub.Exports/Services/IRepositoryService.cs index c0e8ea4fd7..34bf4459cc 100644 --- a/src/GitHub.Exports/Services/IRepositoryService.cs +++ b/src/GitHub.Exports/Services/IRepositoryService.cs @@ -20,8 +20,23 @@ public interface IRepositoryService /// Task<(string owner, string name)?> FindParent(HostAddress address, string owner, string name); + /// + /// Gets the list of protected branches. + /// + /// The host address. + /// The repository owner. + /// The repository name. + /// Task> GetProtectedBranches(HostAddress address, string owner, string name); + /// + /// Gets the protected branch configuration of a particular branch, if any. + /// + /// The host address. + /// The repository owner. + /// The repository name. + /// + /// Task GetProtectedBranch(HostAddress address, string owner, string name, string branchName); } } From a3cb52fb98d67a3ba26f3608aef007f012dcade5 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 13 Dec 2018 14:08:52 -0800 Subject: [PATCH 19/25] Flailing a little --- .../Views/GitHubPane/PullRequestCheckView.xaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index caf2380d7f..f5ac48f1fb 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -22,7 +22,7 @@ - + @@ -31,8 +31,8 @@ - - + + @@ -53,7 +53,7 @@ - From 1a46be88f97c0b75ffcb0825990ac6861099166b Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 13 Dec 2018 16:09:59 -0800 Subject: [PATCH 20/25] Use a dock panel layout --- .../GitHubPane/PullRequestCheckView.xaml | 79 ++++++++++--------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index f5ac48f1fb..ff6584c190 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -22,48 +22,51 @@ - - - - - - - - - - - - + + + + + + + + + + - - - + + + + - + + + + + + + Required + + - + + + + Checks + + - - + + Details + + + + - - - - - + From 2a9402e4a0dee84c3cfa94fa6fcdb24790f3d8da Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 13 Dec 2018 16:53:59 -0800 Subject: [PATCH 21/25] Theming --- src/GitHub.VisualStudio.UI/Styles/ThemeBlue.xaml | 2 ++ src/GitHub.VisualStudio.UI/Styles/ThemeDark.xaml | 2 ++ src/GitHub.VisualStudio.UI/Styles/ThemeLight.xaml | 2 ++ .../Views/GitHubPane/PullRequestCheckView.xaml | 7 ++++--- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Styles/ThemeBlue.xaml b/src/GitHub.VisualStudio.UI/Styles/ThemeBlue.xaml index 02e1b632f4..87dace4014 100644 --- a/src/GitHub.VisualStudio.UI/Styles/ThemeBlue.xaml +++ b/src/GitHub.VisualStudio.UI/Styles/ThemeBlue.xaml @@ -66,4 +66,6 @@ + + \ No newline at end of file diff --git a/src/GitHub.VisualStudio.UI/Styles/ThemeDark.xaml b/src/GitHub.VisualStudio.UI/Styles/ThemeDark.xaml index b9994994e7..21e6c3e3d3 100644 --- a/src/GitHub.VisualStudio.UI/Styles/ThemeDark.xaml +++ b/src/GitHub.VisualStudio.UI/Styles/ThemeDark.xaml @@ -66,4 +66,6 @@ + + \ No newline at end of file diff --git a/src/GitHub.VisualStudio.UI/Styles/ThemeLight.xaml b/src/GitHub.VisualStudio.UI/Styles/ThemeLight.xaml index 85fcdf79b5..19271d1ca6 100644 --- a/src/GitHub.VisualStudio.UI/Styles/ThemeLight.xaml +++ b/src/GitHub.VisualStudio.UI/Styles/ThemeLight.xaml @@ -66,4 +66,6 @@ + + \ No newline at end of file diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index ff6584c190..2c30c8e390 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -41,9 +41,10 @@ - - + + From 6691ab7da059cdc6122f831ace8e2cda9cf1a113 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Thu, 13 Dec 2018 16:54:25 -0800 Subject: [PATCH 22/25] uncomment visibility condition --- .../Views/GitHubPane/PullRequestCheckView.xaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 2c30c8e390..5dfc5b92b9 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -44,10 +44,8 @@ - + FontSize="11"> Required From fa4add268d82cafa250fc89066ef866186147358 Mon Sep 17 00:00:00 2001 From: Stanley Goldman Date: Tue, 26 Feb 2019 13:46:55 -0500 Subject: [PATCH 23/25] Fixing view --- .../Views/GitHubPane/PullRequestCheckView.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index 5dfc5b92b9..dfa2f14726 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -42,9 +42,9 @@ - + Visibility="{Binding IsRequired, Converter={ghfvs:BooleanToVisibilityConverter}}" FontSize="11"> Required From f3b746c19b259d57af995e0d65c024208e303976 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Wed, 27 Feb 2019 13:45:10 -0800 Subject: [PATCH 24/25] Fix line spacing issues between check titles and descriptions --- .../GitHubPane/PullRequestCheckView.xaml | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index dfa2f14726..b004fe648f 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -29,26 +29,21 @@ - - - - - - - + + - + - Required - - + FontWeight="Medium" + FontSize="11"> + Required + + From 8bec5f0f34f650a29704dcbf4e8da2411fea3137 Mon Sep 17 00:00:00 2001 From: Don Okuda Date: Wed, 27 Feb 2019 13:45:32 -0800 Subject: [PATCH 25/25] Leave enough space for the Required Badge --- .../Views/GitHubPane/PullRequestCheckView.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml index b004fe648f..b1a150a750 100644 --- a/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml +++ b/src/GitHub.VisualStudio.UI/Views/GitHubPane/PullRequestCheckView.xaml @@ -33,7 +33,7 @@ - +