public async Task DoNotFetchMorePullRequestsIfCreatedAfterIsSet() { var page1 = new[] { CreatePR("PR 1", daysAgo: 1), CreatePR("PR 2 skip", daysAgo: 1) }; var page2 = new[] { CreatePR("PR 3 skip", daysAgo: 3), CreatePR("PR 4", daysAgo: 5) }; var page3 = new[] { CreatePR("PR 5", daysAgo: 6) }; SetupPagedGetCollectionOf <PullRequest>() .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page1 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page2 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page3 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = Enumerable.Empty <PullRequest>() }); var query = new PullRequestQuery { CreatedAfter = DateTime.UtcNow.AddDays(-4) }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); result.Should().HaveCount(3); _httpClientMock.Verify(c => c.ExecuteGet <CollectionResponse <PullRequest> >(It.IsAny <string>(), _cancellationToken), Times.Exactly(2)); }
public async Task StopRequestingIfFoundOlderPRsThanRequested() { var page1 = new[] { CreatePR(daysAgo: 1), CreatePR(daysAgo: 2) }; var page2 = new[] { CreatePR(daysAgo: 3), CreatePR(daysAgo: 5) }; var page3 = new[] { CreatePR(daysAgo: 6) }; SetupPagedGetCollectionOf <PullRequest>() .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page1 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page2 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page3 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = Enumerable.Empty <PullRequest>() }); var query = new PullRequestQuery { CreatedAfter = DateTime.UtcNow.AddDays(-4) }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); VerifyPagedRequests <PullRequest>(Times.Exactly(2)); result.Should().HaveCount(3); result.Should().BeEquivalentTo(page1.Union(page2.Take(1))); }
private void FetchPullrequestsForRepository(List <PullRequest> resultingPrs, string repositoryName, string projectName) { var sw = Stopwatch.StartNew(); var totalTime = TimeSpan.FromMilliseconds(0); Parallel.ForEach(Input.Members, member => { _progressReporter.Report($"Looking for {member.DisplayName} pull requests in {projectName}/{repositoryName}"); var pullRequestsQuery = PullRequestQuery.New(Input.Query.StartDate) .WithFilter(IsPullRequestMatch) .WithParameter("creatorId", member.Id.ToString()) .WithParameter("status", "all"); var pullRequests = _vstsRepository.GetPullRequests(projectName, repositoryName, pullRequestsQuery) .GetAwaiter() .GetResult(); _logger.LogInformation("Fetched pull requests for '{Member}'. Time: {OperationTime}", member.Email, sw.Elapsed); totalTime += sw.Elapsed; sw.Restart(); _progressReporter.Report($"Found {pullRequests.Count()} pull requests from {member.DisplayName} in {projectName}/{repositoryName}.", GetProgressStep()); lock (_locker) { resultingPrs.AddRange(pullRequests); } }); sw.Stop(); _logger.LogInformation("Finished fetching pull requests for '{Repository}'. Time: {OperationTime}", repositoryName, totalTime); }
public async Task CorrectlySetSkipCountWithQuery() { var page1 = new[] { CreatePR("PR 1"), CreatePR("PR 2 skip") }; var page2 = new[] { CreatePR("PR 3 skip"), CreatePR("PR 4") }; var page3 = new[] { CreatePR("PR 5") }; int skipTotal = 0; SetupPagedGetCollectionOf <PullRequest>(u => ValidateUrlWithPaging(u, ref skipTotal)) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page1 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page2 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = page3 }) .ReturnsAsync(new CollectionResponse <PullRequest> { Value = Enumerable.Empty <PullRequest>() }); var query = new PullRequestQuery { CustomFilter = p => !p.Title.Contains("skip") }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); result.Should().HaveCount(3); skipTotal.Should().Be(11); }
private async Task <IEnumerable <PullRequest> > GetPullRequests(VSTSRepository repositoryInfo, VSTSProject project) { var query = PullRequestQuery.New(Input.Query.StartDate) .WithFilter(p => p.CreationDate >= Input.Query.StartDate && p.CreationDate <= Input.Query.EndDate) .WithParameter("status", "all"); return(await _vstsRepository.GetPullRequests(project.Name, repositoryInfo.Name, query)); }
private bool ValidateUrlWithQuery(string url, PullRequestQuery query) { var uri = new Uri(url); var queryString = uri.Query; return(queryString.Contains($"searchCriteria.status={query.Status}") && queryString.Contains($"searchCriteria.reviewerId={query.ReviewerId}") && queryString.Contains($"searchCriteria.creatorId={query.CreatorId}")); }
public async Task ShouldNotThrowIfErrorRetrievingPullRequests() { _clientMock.Setup(c => c.ExecuteGet <PullRequestsResponse>(It.IsAny <string>())) .Returns(Task.FromResult((PullRequestsResponse)null)); var result = await _repository.GetPullRequests("Foo", "Bar", PullRequestQuery.New(DateTime.UtcNow)); result.Should().NotBeNull(); result.Should().BeEmpty(); }
private void FetchPullrequests() { var isDisabled = _repository.GetFieldValue <Settings, bool>(_ => true, s => s.PullRequestsSettings.DisablePullRequestsJob); if (isDisabled) { _logger.LogWarning("Pull requests job is disabled in settings."); return; } var teamMembers = GetTeamMembers(); var profiles = _repository.GetAll <Profile>(); var repositories = _repository.GetAll <VSTSRepository>(); var projects = _repository.GetAll <VSTSProject>(); foreach (var teamMember in teamMembers) { var memberRepositoriesAndProjects = profiles.Where(p => p.Members.Contains(teamMember.Id)) .SelectMany(p => p.Repositories) .Select(r => { var repository = repositories.Single(ar => ar.Id == r); var project = projects.Single(p => p.Id == repository.Project); return(repository, project); }); var retrievedPullRequests = new List <PullRequest>(); foreach (var repositoryAndProject in memberRepositoriesAndProjects) { var query = PullRequestQuery.New(teamMember.LastPullRequestsFetchDate) .WithFilter(IsPullRequestMatch) .WithParameter("creatorId", teamMember.Id.ToString()) .WithParameter("status", "all"); var pullRequests = _vstsClient.GetPullRequests(repositoryAndProject.project.Name, repositoryAndProject.repository.Name, query) .GetAwaiter() .GetResult(); retrievedPullRequests.AddRange(pullRequests); } if (teamMember.PullRequests == null) { teamMember.PullRequests = Enumerable.Empty <PullRequest>(); } var newPullrequests = retrievedPullRequests.Except(teamMember.PullRequests); _logger.LogInformation("Found {newPullRequestsNumber} pullrequests for '{TeamMember}'", newPullrequests.Count(), teamMember.Email); teamMember.PullRequests = teamMember.PullRequests.Union(newPullrequests); teamMember.LastPullRequestsFetchDate = DateTime.UtcNow; _repository.CreateOrUpdateAsync(teamMember) .GetAwaiter() .GetResult(); } }
public async Task <BacklogResponse <PullRequest[]> > GetPullRequestsAsync(PullRequestQuery query = null) { query = query ?? new PullRequestQuery(); var client = Project.Client; var response = await client.GetAsync($"/api/v2/projects/{Project.Id}/git/repositories/{Id}/pullRequests", query.Build()).ConfigureAwait(false); return(await client.CreateResponseAsync <PullRequest[], List <_PullRequest> >( response, HttpStatusCode.OK, data => data.Select(x => new PullRequest(x, this)).ToArray()).ConfigureAwait(false)); }
public async Task <BacklogResponse <int> > GetPullRequestCountAsync(PullRequestQuery query = null) { query = query ?? new PullRequestQuery(); var client = Project.Client; var response = await client.GetAsync($"/api/v2/projects/{Project.Id}/git/repositories/{Id}/pullRequests/count", query.Build()).ConfigureAwait(false); return(await client.CreateResponseAsync <int, _Count>( response, HttpStatusCode.OK, data => data.count).ConfigureAwait(false)); }
public async Task FilterByDate() { var pullRequests = new[] { CreatePR(daysAgo: 5), CreatePR(daysAgo: 3), CreatePR(daysAgo: 2) }; SetupOnePageOf(pullRequests); var query = new PullRequestQuery { CreatedAfter = DateTime.UtcNow.AddDays(-4) }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); result.Should().HaveCount(2); result.Should().BeEquivalentTo(pullRequests.Skip(1)); }
public async Task CustomFilter() { var pullRequests = new[] { CreatePR("Bug 1"), CreatePR("Task 1"), CreatePR("Bug 2") }; SetupOnePageOf(pullRequests); var query = new PullRequestQuery { CustomFilter = p => p.Title.StartsWith("Bug") }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); result.Should().HaveCount(2); result.Should().OnlyContain(p => query.CustomFilter(p)); }
public async Task CustomFilterWithDateFilter() { var pullRequests = new[] { CreatePR("Bug 1", daysAgo: 2), CreatePR("Task 1", daysAgo: 2), CreatePR("Bug 2", daysAgo: 4) }; SetupOnePageOf(pullRequests); var query = new PullRequestQuery { CustomFilter = p => p.Title.StartsWith("Bug"), CreatedAfter = DateTime.UtcNow.AddDays(-3) }; var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); result.Should().HaveCount(1); result.Should().BeEquivalentTo(pullRequests.Take(1)); }
public async Task IncludesQueryParametersInUrl() { var query = new PullRequestQuery { CreatorId = Guid.NewGuid(), ReviewerId = Guid.NewGuid(), Status = "Active", CreatedAfter = DateTime.UtcNow.AddDays(-3) }; var pullRequests = new[] { CreatePR(daysAgo: 2), CreatePR(daysAgo: 1) }; SetupOnePageOf(pullRequests, s => ValidateUrlWithQuery(s, query)); var result = await _client.GetPullRequestsAsync(ProjectName, RepositoryName, query, _cancellationToken); _httpClientMock.VerifyAll(); result.Should().NotBeNull(); result.Should().NotBeEmpty(); result.Should().BeEquivalentTo(pullRequests); }
/// <inheritdoc /> public async Task <IEnumerable <PullRequest> > GetPullRequestsAsync(string project, string repository, PullRequestQuery query, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfArgumentNullOrEmpty(project, nameof(project)); ThrowIfArgumentNullOrEmpty(repository, nameof(repository)); if (query == null) { query = PullRequestQuery.None; } var haveMorePullRequests = true; var skip = 0; var allPullRequests = new List <PullRequest>(); while (haveMorePullRequests) { var url = VstsUrlBuilder.Create(_instanceName) .ForPullRequests(project, repository) .WithQueryParameterIfNotEmpty("searchCriteria.status", query.Status) .WithQueryParameterIfNotEmpty("searchCriteria.reviewerId", query.ReviewerId) .WithQueryParameterIfNotEmpty("searchCriteria.creatorId", query.CreatorId) .WithQueryParameter("$skip", skip) .Build(); var pullRequestsResponse = await _httpClient.ExecuteGet <CollectionResponse <PullRequest> >(url, cancellationToken); var pullRequests = pullRequestsResponse?.Value ?? Enumerable.Empty <PullRequest>(); haveMorePullRequests = pullRequests.Any() && (!query.CreatedAfter.HasValue || pullRequests.Min(p => p.CreationDate) >= query.CreatedAfter); if (query.CreatedAfter.HasValue) { pullRequests = pullRequests.Where(p => p.CreationDate >= query.CreatedAfter); } if (query.CustomFilter != null) { pullRequests = pullRequests.Where(query.CustomFilter); } allPullRequests.AddRange(pullRequests); skip = allPullRequests.Count; } return(allPullRequests); }
private async Task FetchPullRequests(string repositoryName, string projectName, List <PullRequest> pullrequests, PullRequestQuery query, int startFrom = 0) { var sw = Stopwatch.StartNew(); var pullRequestsUrlBuilder = VSTSApiUrl.Create(_configuration.Value.InstanceName) .ForPullRequests(projectName, repositoryName); foreach (var parameter in query.Parameters) { pullRequestsUrlBuilder.WithQueryParameter(parameter.Key, parameter.Value); } pullRequestsUrlBuilder.WithQueryParameter("$skip", startFrom.ToString()); var pullRequestsUrl = pullRequestsUrlBuilder.Build(ApiVersion); _logger.LogInformation($"Attempting to retrieve pull requests from {pullRequestsUrl}"); var prsResponse = await _client.ExecuteGet <PullRequestsResponse>(pullRequestsUrl); if (prsResponse == null) { _logger.LogWarning("Couldn't fetch pull requests from the server. Url: {APIUrl}", pullRequestsUrl); return; } _logger.LogInformation($"Retrieved {prsResponse.Value.Count()} PRs from '{repositoryName}' repository. Start position {startFrom}. Operation took: {sw.Elapsed}"); sw.Restart(); var prs = prsResponse.Value .Where(query.Filter) .ToList(); sw.Stop(); _logger.LogInformation($"Filtering PRs by range took {sw.Elapsed}. Count {prs.Count}"); pullrequests.AddRange(prs); if (prs.Any() && prs.Min(p => p.CreationDate) > query.FromDate) { await FetchPullRequests(repositoryName, projectName, pullrequests, query, startFrom + prs.Count); } }
public async Task <IEnumerable <PullRequest> > GetPullRequests(string project, string repository, PullRequestQuery query) { var pullrequests = new List <PullRequest>(); await FetchPullRequests(repository, project, pullrequests, query); return(pullrequests); }
private bool VerifyPullRequestQuery(PullRequestQuery query, IList <TeamMemberViewModel> members) { return(members.Any(m => m.Id == query.CreatorId) && string.Equals(query.Status, "all")); }