private async Task <bool> CreateNewPullRequest(string dummyBranchName, CancellationToken token) { token.ThrowIfCancellationRequested(); var pullRequest = new GitPullRequest() { Title = $"AutoMerge PR from {SourceName} to {DestName}", SourceRefName = SourceBranch, TargetRefName = dummyBranchName, }; try { var response = await GitHttpClient.CreatePullRequestAsync(pullRequest, RepositoryId); Logger.Info($"Pull Request ID: {response.PullRequestId}, URL: {response.Url}"); AutoPullRequestId = response.PullRequestId; return(true); } catch (OperationCanceledException) { Logger.Error($"Time out occurs when try to create PR from {SourceBranch} to {dummyBranchName}"); throw; } catch (Exception e) { Logger.Error($"Exception occurs when try to create PR from {SourceBranch} to {dummyBranchName}, message: {e.Message}"); throw; } }
public PullRequestVM(Uri baseUri, GitPullRequest pr, IAvatarProvider avatarProvider, IWindow window) { this.baseUri = baseUri; this.pr = pr; this.avatarProvider = avatarProvider; this.window = window; }
public List <GitPullRequestStatus> GetPullRequestIterationStatuses() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); Console.WriteLine($"project {project.Name}, repo {repo.Name}, pullRequestId {pullRequest.PullRequestId}"); List <GitPullRequestStatus> iterationStatuses = gitClient.GetPullRequestIterationStatusesAsync(repo.Id, pullRequest.PullRequestId, 1).Result; Console.WriteLine($"{iterationStatuses.Count} statuses found for pull request {pullRequest.PullRequestId} iteration {1}"); foreach (var status in iterationStatuses) { Console.WriteLine($"{status.Description}({status.Context.Genre}/{status.Context.Name}) with id {status.Id}"); } GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); return(iterationStatuses); }
/// <summary> /// Creates a pull request, and then adds a reviewer to it. /// </summary> /// <param name="gitHttpClient"> GitHttpClient that is created for accessing vsts</param> /// <param name="gitPullRequest"> the pull request to be created</param> /// <param name="repositoryId"> the unique identifier of the repository</param> /// <param name="reviewerAlias"> reviewer's alias in vsts</param> /// <param name="vstsAccountUrl">vsts account's url</param> /// <param name="personalToken"> personal access token to access the vsts account. </param> public static async void CreatePullRequestAndAddReviewer( GitHttpClient gitHttpClient, GitPullRequest gitPullRequest, string repositoryId, string reviewerAlias, Uri vstsAccountUrl, string personalToken) { // 1- Create the pull request. GitPullRequest pullRequest = gitHttpClient.CreatePullRequestAsync(gitPullRequest, repositoryId, cancellationToken: CancellationToken.None).Result; // 2- Create an Identity Client to get the reviewer's vsts id IdentityHttpClient identityHttpClient = CreateIdentityClient(vstsAccountUrl, personalToken); // 3- Find the reviewer's vsts identity. Identity identity = SearchForReviewerVstsIdentity(identityHttpClient, reviewerAlias).Result; // 4- Create a IdentityRefWithVote for the reviewer IdentityRefWithVote identityRefWithVote = new IdentityRefWithVote { Id = identity.Id.ToString(), IsRequired = true // false otherwise. }; // 5- Finally add the reviewer to the pull request. await AddReviewerToPullRequest(gitHttpClient, pullRequest, identityRefWithVote); }
public PropertiesCollection GetPullRequestProperties() { VssConnection connection = Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); using (new ClientSampleHttpLoggerOutputSuppression()) { JsonPatchDocument patch = new JsonPatchDocument(); patch.Add(new JsonPatchOperation() { Operation = Operation.Add, Path = "/sampleId", Value = 8 }); patch.Add(new JsonPatchOperation() { Operation = Operation.Add, Path = "/startedDateTime", Value = DateTime.UtcNow }); gitClient.UpdatePullRequestPropertiesAsync(patch, repo.Id, pullRequest.PullRequestId).SyncResult(); } Console.WriteLine("project {0}, repo {1}, pullRequestId {2}", project.Name, repo.Name, pullRequest.PullRequestId); PropertiesCollection properties = gitClient.GetPullRequestPropertiesAsync(repo.Id, pullRequest.PullRequestId).SyncResult(); Console.WriteLine($"Pull request {pullRequest.PullRequestId} has {properties.Count} properties"); GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); return(properties); }
public async Task FetchIterationsAsync( string project, string repositoryId, GitPullRequest pullRequest) { var pullRequestId = pullRequest.PullRequestId; var outputFile = $"{pullRequestId.ToString()}-iterations.json"; if (outputFileStore.Contains(outputFile)) { info.Trace($"{outputFile} already exists. Skipping call to the API."); } else { info.Trace($"Fetching iterations for pull request {pullRequestId.ToString()} ..."); var iterations = await gitClient.GetPullRequestIterationsAsync( project, repositoryId, pullRequestId); info.Trace($"Writing output to {outputFile} ..."); await outputFileStore.WriteFileAsync( filename : outputFile, content : JsonConvert.SerializeObject(iterations, Formatting.Indented)); } }
public async Task FetchPullRequestChangesAsync( string project, string repositoryId, GitPullRequest pullRequest) { var pullRequestId = pullRequest.PullRequestId; var outputFile = $"{pullRequestId.ToString()}-changes.json"; var mergeCommitId = pullRequest.LastMergeCommit?.CommitId; if (mergeCommitId == null) { // A completed PR won't merge if the commit is already in the target branch info.Trace($"{pullRequestId} has no merge commit."); } else if (outputFileStore.Contains(outputFile)) { info.Trace($"{outputFile} already exists. Skipping call to the API."); } else { info.Trace($"Fetching changes for commit {mergeCommitId.ToString()} ..."); var changes = await gitClient.GetChangesAsync( project, commitId : mergeCommitId, repositoryId : repositoryId); info.Trace($"Writing output to {outputFile} ..."); await outputFileStore.WriteFileAsync( filename : outputFile, content : JsonConvert.SerializeObject(changes, Formatting.Indented)); } }
/// <summary> /// Build a Url to the web view of the pull request. /// </summary> /// <remarks> /// Example Url: https://team.visualstudio.com/_git/myrepo/pullRequest/10571 /// </remarks> private string ConstructUri(GitPullRequest pr) { string repo = Uri.EscapeDataString(pr.Repository.Name); string proj = Uri.EscapeDataString(m_config.Project !); return($"{m_config.OrganizationUrl}/{proj}/_git/{repo}/pullrequest/{pr.PullRequestId}"); }
public void UpdatePullRequestIterationStatuses() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); GitPullRequestStatus status1 = GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); GitPullRequestStatus status2 = GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); Console.WriteLine($"project {project.Name}, repo {repo.Name}, pullRequestId {pullRequest.PullRequestId}"); var patch = new JsonPatchDocument(); patch.Add(new JsonPatchOperation() { Operation = VisualStudio.Services.WebApi.Patch.Operation.Remove, Path = $"/{status1.Id}" }); patch.Add(new JsonPatchOperation() { Operation = VisualStudio.Services.WebApi.Patch.Operation.Remove, Path = $"/{status2.Id}" }); gitClient.UpdatePullRequestIterationStatusesAsync(patch, repo.Id, pullRequest.PullRequestId, 1).SyncResult(); Console.WriteLine($"Statuses {status1.Id}, and {status2.Id} deleted from the pull request {pullRequest.PullRequestId}, iteration {1}"); GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); }
/// <summary> /// Create new Pull Request /// </summary> /// <param name="TeamProjectName"></param> /// <param name="RepoName"></param> /// <param name="SourceRef"></param> /// <param name="TargetRef"></param> /// <param name="WorkItems"></param> /// <returns></returns> static int CreatePullRequest(string TeamProjectName, string RepoName, string SourceRef, string TargetRef, int [] WorkItems) { GitPullRequest pr = new GitPullRequest(); pr.Title = pr.Description = String.Format("PR from {0} into {1} ", SourceRef, TargetRef); pr.SourceRefName = SourceRef; pr.TargetRefName = TargetRef; if (WorkItems != null && WorkItems.Length > 0) { List <ResourceRef> wiRefs = new List <ResourceRef>(); foreach (int wiId in WorkItems) { WorkItem workItem = WitClient.GetWorkItemAsync(wiId).Result; wiRefs.Add(new ResourceRef { Id = workItem.Id.ToString(), Url = workItem.Url }); } pr.WorkItemRefs = wiRefs.ToArray(); } var newPr = GitClient.CreatePullRequestAsync(pr, TeamProjectName, RepoName).Result; Console.WriteLine("PR was created: " + newPr.PullRequestId); return(newPr.PullRequestId); }
/// <summary> /// Close all active comments and complete PR /// </summary> /// <param name="TeamProjectName"></param> /// <param name="RepoName"></param> /// <param name="PrId"></param> static void CompletePR(string TeamProjectName, string RepoName, int PrId) { GitPullRequest pr = GitClient.GetPullRequestAsync(TeamProjectName, RepoName, PrId).Result; if (pr.MergeStatus != PullRequestAsyncStatus.Succeeded) { CreateNewCommentThread(TeamProjectName, RepoName, PrId, "You need to resolve conflicts"); return; } List <GitPullRequestCommentThread> threads = GitClient.GetThreadsAsync(TeamProjectName, RepoName, PrId).Result; foreach (var thread in threads) { if (thread.Status == CommentThreadStatus.Active) { GitPullRequestCommentThread updatedThread = new GitPullRequestCommentThread(); updatedThread.Status = CommentThreadStatus.Fixed; Microsoft.TeamFoundation.SourceControl.WebApi.Comment[] comments = { new Microsoft.TeamFoundation.SourceControl.WebApi.Comment { Content = "Task is completed." } }; updatedThread.Comments = comments; updatedThread = GitClient.UpdateThreadAsync(updatedThread, TeamProjectName, RepoName, PrId, thread.Id).Result; } } GitPullRequest prUdated = new GitPullRequest(); prUdated.Status = PullRequestStatus.Completed; prUdated.LastMergeSourceCommit = pr.LastMergeSourceCommit; prUdated = GitClient.UpdatePullRequestAsync(prUdated, TeamProjectName, RepoName, PrId).Result; }
private PullRequestsDetailViewModel CreateSutWithData( long id, GitPullRequest pullRequest, ConnectionData connectionData ) { IEnumerable <GitCommit> commits = new List <GitCommit>() { new GitCommit() }; IEnumerable <GitComment> comments = new List <GitComment>() { new GitComment() }; IEnumerable <FileDiff> filesDiff = new List <FileDiff>() { new FileDiff() }; _userInfoService.Stub(x => x.ConnectionData).Return(connectionData); _userInfoService.Stub(x => x.CurrentTheme).Return(Theme.Light); _gitClientService.Expect(x => x.GetPullRequest(id)).Return(pullRequest.FromTaskAsync()); _gitClientService.Expect(x => x.GetPullRequestComments(id)).Return(comments.FromTaskAsync()); _gitClientService.Expect(x => x.GetPullRequestCommits(id)).Return(commits.FromTaskAsync()); _gitClientService.Expect(x => x.GetPullRequestDiff(id)).Return(filesDiff.FromTaskAsync()); _pullRequestDiffViewModel.Expect(x => x.AddFileDiffs(filesDiff)); _pullRequestDiffViewModel.Expect(x => x.UpdateComments(id)).Return(comments.FromTaskAsync()); return(CreateSut()); }
public async Task EvaluateAsync_UnfinishedTaskListInDescription_ShouldSetStatusToFailed() { var pullRequest = new GitPullRequest(); pullRequest.Description = "[ ] Task 1 [x] Task 2"; await EvaluateAsync(pullRequest, GitStatusState.Failed); }
public async Task EvaluateAsync_NoTaskListInDescription_ShouldSetStatusToSuceeded() { var pullRequest = new GitPullRequest(); pullRequest.Description = "Task 1 Task 2"; await EvaluateAsync(pullRequest, GitStatusState.Succeeded); }
public async Task EvaluateAsync_WorkInProgressInTitle_ShouldSetStatusToFailed() { var pullRequest = new GitPullRequest(); pullRequest.Title = "[WIP] New super awesome feature pull request #123"; await EvaluateAsync(pullRequest, GitStatusState.Failed); }
public async Task EvaluateAsync_WorkInProgressNotInTitle_ShouldSetStatusToSuceeded() { var pullRequest = new GitPullRequest(); pullRequest.Title = "Wipe all data"; await EvaluateAsync(pullRequest, GitStatusState.Succeeded); }
public TfsPullRequests(GitPullRequest native, TfsUrlBuilder urlBuilder) : base(native.PullRequestId, urlBuilder) { Description = native.Description; SourceBranch = native.SourceRefName; TargetBranch = native.TargetRefName; Id = native.PullRequestId.ToString(CultureInfo.InvariantCulture); }
public static string ChangeSize(this GitPullRequest pr) { if (pr == null) { throw new ArgumentNullException(nameof(pr)); } if (pr.Commits == null) { return(string.Empty); } int added = 0; int edits = 0; int delete = 0; foreach (var change in pr.Commits) { foreach (var count in change.ChangeCounts) { switch (count.Key) { case VersionControlChangeType.Add: added += count.Value; break; case VersionControlChangeType.Edit: edits += count.Value; break; case VersionControlChangeType.Delete: delete += count.Value; break; } } } StringBuilder builder = new StringBuilder(); if (added > 0) { builder.Append($"++{added} "); } if (delete > 0) { builder.Append($"--{delete} "); } if (edits > 0) { builder.Append($"--{edits}"); } return(builder.ToString()); }
public async Task CreatePullRequest(string repositoryId) { var gitClient = _connection.GetClient <GitHttpClient>(); var pullRequestToCreate = new GitPullRequest { }; var vstsPullRequest = await gitClient.CreatePullRequestAsync(pullRequestToCreate, repositoryId); }
/// <summary> /// Abandon a pull request /// </summary> /// <param name="TeamProjectName"></param> /// <param name="RepoName"></param> /// <param name="PrId"></param> static void AbandonPR(string TeamProjectName, string RepoName, int PrId) { CreateNewCommentThread(TeamProjectName, RepoName, PrId, "Reject this PR"); GitPullRequest prUdated = new GitPullRequest(); prUdated.Status = PullRequestStatus.Abandoned; prUdated = GitClient.UpdatePullRequestAsync(prUdated, TeamProjectName, RepoName, PrId).Result; }
public void TestIsApproved_WhenThereIsOneReviewerVotingMoreThanZero_ReturnsTrue(short vote) { var pullRequest = new GitPullRequest { Reviewers = new[] { new IdentityRefWithVote { Vote = vote } } }; var systemUnderTest = new PullRequest(pullRequest, "server-uri", _repo); Assert.That(systemUnderTest.IsApproved, Is.True); }
/// <summary> /// Build a protocol handler specific compatible Url. /// </summary> /// <remarks> /// Example Url: /// protocol://open/?server=https%3A%2F%2Fteam.visualstudio.com%2F&project=myprojectl&repo=myrepo&pullRequest=10571&alert=true /// </remarks> private string ConstructUri(GitPullRequest pr) { string?proj = m_config.Project; string?repo = pr.Repository.Name; string url = $"{m_config.OrganizationUrl}&project={proj}&repo={repo}&pullRequest={pr.PullRequestId}&alert=true"; string escapedUrl = Uri.EscapeUriString(url); return($"{m_protocolPrefix}://open/?server={escapedUrl}"); }
/// <summary> /// Build a protocol handler specific compatible Url. /// </summary> /// <remarks> /// Example Url: /// protocol://open/?server=https%3A%2F%2Fteam.visualstudio.com%2F&project=myprojectl&repo=myrepo&pullRequest=10571&alert=true /// </remarks> private string ConstructUri(GitPullRequest pr) { string proj = m_config.Project; string url = $"{m_config.OrganizationUrl}&project={proj}&repo={proj}&pullRequest={pr.PullRequestId}&alert=true"; // Some app Urll decoders don't seem to support full url de-encoding... so just encode "enough". // url = url.Replace("/", "%2F", StringComparison.InvariantCultureIgnoreCase); url = url.Replace(":", "%3A", StringComparison.InvariantCultureIgnoreCase); return($"{m_protocolPrefix}://open/?server={url}"); }
private static async Task TryQueueBuildPolicy(GitPullRequest pullRequest, string buildPolicy, string insertionBranchName) { try { await QueueBuildPolicy(pullRequest, buildPolicy); } catch (Exception ex) { LogWarning($"Unable to start {buildPolicy} for '{insertionBranchName}'"); LogWarning(ex); } }
private static void SendMail(GitPullRequest pullRequest, List <string> newPackageFiles, bool isInsertionCancelled = false, bool noProgressOnFailedBuilds = false) { Log.Factory.Flush(); using (var mailClient = new SmtpClient(Options.EmailServerName)) { mailClient.UseDefaultCredentials = true; var from = new MailAddress(Options.Username); var to = new MailAddress(Options.MailRecipient); using (var mailMessage = new MailMessage(from, to)) { if (pullRequest != null) { mailMessage.Subject = $"{Options.InsertionName} insertion from {Options.BuildQueueName}/{Options.BranchName}/{Options.BuildConfig} into {Options.VisualStudioBranchName} SUCCEEDED"; mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.IsBodyHtml = true; mailMessage.Body = GetHTMLSuccessMessage(pullRequest, newPackageFiles); mailMessage.BodyEncoding = Encoding.UTF8; } else { string insertionStatus; if (noProgressOnFailedBuilds || !isInsertionCancelled) { insertionStatus = "FAILED"; } else { insertionStatus = "CANCELLED"; } string body = $"Review attached log for details"; if (noProgressOnFailedBuilds) { body = $"Latest successful build has already been inserted, but there are newer unsuccessful builds."; } mailMessage.Subject = $"{Options.InsertionName} insertion from {Options.BuildQueueName}/{Options.BranchName}/{Options.BuildConfig} into {Options.VisualStudioBranchName} {insertionStatus}"; mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.Body = body; } if (File.Exists(Options.LogFileLocation)) { mailMessage.Attachments.Add(new System.Net.Mail.Attachment(Options.LogFileLocation)); } mailClient.Send(mailMessage); } } }
/// <summary> /// Returns the vote ratio string for the pull request. /// </summary> /// <param name="pr">The pull request to process.</param> /// <exception cref="ArgumentNullException">identityRef</exception> public static string VoteRatio(this GitPullRequest pr) { if (pr == null) { throw new ArgumentNullException(nameof(pr)); } int reviewers = pr.Reviewers.Length; int signedOff = pr.Reviewers.Count(r => r.IsSignedOff()); return($"{signedOff} / {reviewers}"); }
public virtual async Task EvaluateAsync(GitPullRequest pullRequest) { PullRequest = pullRequest; try { await EvaluateInternalAsync(pullRequest); } catch { await UpdateStatusAsync(GitStatusState.Error, GetName() + " run into an error"); } }
public override IEnumerable <IRow> Extract(IUnstructuredReader input, IUpdatableRow output) { string line = string.Empty; foreach (Stream current in input.Split(_rowDelim)) { using (StreamReader streamReader = new StreamReader(current, _encoding)) { line = streamReader.ReadToEnd().Trim(); if (!string.IsNullOrEmpty(line)) { GitPullRequest pr = JsonConvert.DeserializeObject <GitPullRequest>(line); output.Set("assignee", pr.Assignee == null?(int?)null:pr.Assignee.Id); output.Set("assignees", pr.Assignees == null?null:JsonConvert.SerializeObject(pr.Assignees)); output.Set("milestone", pr.Milestone == null ? null : JsonConvert.SerializeObject(pr.Milestone)); output.Set("merged", pr.Merged); output.Set("mergeable", pr.Mergeable); output.Set("mergeableState", pr.MergeableState == null?null:pr.MergeableState.StringValue); output.Set("mergeCommitSHA", pr.MergeCommitSha); output.Set("userId", pr.User == null?(int?)null : pr.User.Id); output.Set("comments", pr.Comments); output.Set("commits", pr.Commits); output.Set("additions", pr.Additions); output.Set("deletions", pr.Deletions); output.Set("changedFiles", pr.ChangedFiles); output.Set("mergedBy", pr.MergedBy == null?(int?)null:pr.MergedBy.Id); output.Set("base", pr.Base == null?null:JsonConvert.SerializeObject(pr.Base)); output.Set("mergedAt", pr.MergedAt == null?(DateTime?)null:pr.MergedAt.Value.UtcDateTime); output.Set("locked", pr.Locked); output.Set("id", pr.Id); output.Set("url", pr.Url); output.Set("htmlUrl", pr.HtmlUrl); output.Set("diffUrl", pr.DiffUrl); output.Set("patchUrl", pr.PatchUrl); output.Set("issueUrl", pr.IssueUrl); output.Set("head", pr.Head == null ? null : JsonConvert.SerializeObject(pr.Head)); output.Set("statusesUrl", pr.StatusesUrl); output.Set("state", pr.State.StringValue); output.Set("title", pr.Title); output.Set("body", pr.Body); output.Set("createdAt", pr.CreatedAt.UtcDateTime); output.Set("updatedAt", pr.UpdatedAt.UtcDateTime); output.Set("closedAt", pr.ClosedAt == null?(DateTime?)null:pr.ClosedAt.Value.UtcDateTime); output.Set("number", pr.Number); output.Set("requestedReviewers", pr.RequestedReviewers == null ? null : JsonConvert.SerializeObject(pr.RequestedReviewers)); } } yield return(output.AsReadOnly()); } }
/// <summary> /// Tries to get the current users reviewer object from a pull request. /// </summary> /// <param name="pullRequest">The pull request we want to look our selves up in.</param> /// <param name="currentUserId">The <see cref="Guid"/> of our current user.</param> /// <param name="reviewer">Output parameter that points to our own reviewer object.</param> /// <returns></returns> private static bool TryGetReviewer(GitPullRequest pullRequest, Guid currentUserId, out IdentityRefWithVote reviewer) { foreach (IdentityRefWithVote r in pullRequest.Reviewers) { if (currentUserId.Equals(Guid.Parse(r.Id))) { reviewer = r; return(true); } } reviewer = null; return(false); }
public void Initialize_CorrectDataReturned_ShouldInitialize() { long id = 123; var pqAuthor = "Author"; var pullRequest = new GitPullRequest("Title", "Description", new GitBranch() { Name = "SourceBranch" }, new GitBranch() { Name = "DestinationBranch" }) { Reviewers = new Dictionary <GitUser, bool>() { [new GitUser() { Username = "******" }] = true, [new GitUser() { Username = "******" }] = false, }, Author = new GitUser() { Username = pqAuthor } }; var connectionData = new ConnectionData() { UserName = pqAuthor, }; var sut = CreateSutWithData(id, pullRequest, connectionData); sut.Initialize(id); Assert.AreEqual(pullRequest, sut.PullRequest); Assert.IsNotEmpty(sut.PullRequestDiffModel.CommentTree); Assert.IsNotEmpty(sut.PullRequestDiffModel.Comments); Assert.IsNotEmpty(sut.PullRequestDiffModel.Commits); Assert.IsNotEmpty(sut.PullRequestDiffModel.FileDiffs); Assert.IsNotEmpty(sut.PullRequestDiffModel.FilesTree); Assert.IsTrue(sut.ActionCommands.Any(sutActionCommand => sutActionCommand.Label.Contains("Merge"))); Assert.IsTrue(sut.ActionCommands.Any(sutActionCommand => sutActionCommand.Label.Contains("Decline"))); }