public List <Issue> GetAllOpenIssues(string label) { var repoService = new RepositoryManagementService(); var allOpenIssues = repoService.GetAllCommunityIssues(false).Where(x => x.ClosedDateTime == null).ToList(); foreach (var issue in allOpenIssues) { var firstLabel = issue.Events.OrderBy(x => x.CreateDateTime).FirstOrDefault(x => x.Name == "labeled"); } foreach (var issue in allOpenIssues) { var firstComment = issue.Comments.OrderBy(x => x.CreateDateTime).FirstOrDefault(); } // Added label by HQ // -- Discussion / HQ Reply // -- Estimation // //foreach (var issue in labelIssues) //{ // foreach (var issueEvent in issue.Events) // { // if (issueEvent.Name == "labeled" && string.Equals(issueEvent.Label.Name, label, StringComparison.InvariantCultureIgnoreCase)) // { // issue.LabelAdded = issueEvent.CreateDateTime; // } // } //} return(allOpenIssues.ToList()); }
public async Task TestGet_NoWildcards_ReturnsOnlySpecifiedOrgs() { //arrange RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), TelemetryMock.InitializeMockTelemetryClient()); var parameters = new[] { new RepositoryQueryParameter(this.orgOne_RepoOne), new RepositoryQueryParameter(this.orgTwo_RepoOne), new RepositoryQueryParameter(this.orgThree_RepoOne), }; var repos = (await service.GetRepositories(parameters)).ToList(); //act ManifestQueryResult result = await service.GetCurrentProjects(repos, "FindMe", false); //assert Assert.AreEqual(3, result.Projects.Count); Assert.AreEqual(1, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgOne_RepoOne.Id)); Assert.AreEqual(0, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgOne_RepoTwo.Id)); Assert.AreEqual(1, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgTwo_RepoOne.Id)); Assert.AreEqual(0, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgTwo_RepoTwo.Id)); Assert.AreEqual(1, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgThree_RepoOne.Id)); Assert.AreEqual(0, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgThree_RepoTwo.Id)); Assert.AreEqual(0, result.Projects.Count(x => x.RepositoryInfo.Id == this.orgThree_RepoThree.Id)); }
public async Task DefaultRepoProjects_NotCleanedUp() { //arrange RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), TelemetryMock.InitializeMockTelemetryClient()); await SeedProjects(service, "Project1", this.defaultRepoOne, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); await SeedProjects(service, "Project2", this.defaultRepoOne, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); await SeedProjects(service, "Project3", this.defaultRepoOne, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); await SeedProjects(service, "Project4", this.defaultRepoOne, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); SnapshotRepoCleaner cleaner = new SnapshotRepoCleaner(database); //assuming... Check.That(database.GetAllProjects().Result.Count()).Equals(4); //act SnapshotRepoCleanupResult result = await cleaner.PerformCleanupAsync(new SnapshotRepoCleanupSettings() { }); //assert Check.That(result.RepositoryResults.Count).IsEqualTo(0); Check.That(database.GetAllProjects().Result.Count()).Equals(4); }
public async Task SnapshotRepoProjects_SettingsChange_AffectsTheNumberOfProjectsLeft() { //arrange RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), TelemetryMock.InitializeMockTelemetryClient()); await SeedProjects(service, "Project1", this.snapshotRepoOne, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); SnapshotRepoCleaner cleaner = new SnapshotRepoCleaner(database); //assuming... Check.That(database.GetAllProjects().Result.Count()).Equals(4); //act SnapshotRepoCleanupResult result = await cleaner.PerformCleanupAsync(new SnapshotRepoCleanupSettings() { NumberOfSnapshotsToKeep = 3 }); //assert Check.That(result.RepositoryResults.Single().Value).IsEqualTo(1); Check.That(database.GetAllProjects().Result.Count()).Equals(3); //now change settings and run again //act result = await cleaner.PerformCleanupAsync(new SnapshotRepoCleanupSettings() { NumberOfSnapshotsToKeep = 1 }); //assert Check.That(result.RepositoryResults.Single().Value).IsEqualTo(2); Check.That(database.GetAllProjects().Result.Count()).Equals(1); }
public List <Issue> GetAssignedIssues() { var repoService = new RepositoryManagementService(); var assignedIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.ClosedDateTime == null && x.Labels.Any(l => l.Name == "status/idea") == false && x.Assignees.Any()).ToList(); return(assignedIssues); }
private async Task <ProjectInfo> AddTwoProjectsWithSameRepoStamp(RepositoryManagementService service) { ManifestQueryResult allProjects; //add two projects with same repo stamp RepoCat.Transmission.Models.ProjectInfo prj = new RepoCat.Transmission.Models.ProjectInfo() { ProjectName = "Project1", ProjectUri = "SomeLocation", RepositoryInfo = new RepoCat.Transmission.Models.RepositoryInfo() { RepositoryName = this.testRepoOne.RepositoryName, OrganizationName = this.testRepoOne.OrganizationName, }, TargetExtension = "exe", RepositoryStamp = "1.0" }; await service.Upsert(prj).ConfigureAwait(false); RepoCat.Transmission.Models.ProjectInfo prj2 = new RepoCat.Transmission.Models.ProjectInfo() { ProjectName = "Project2", ProjectUri = "SomeLocation", DocumentationUri = "http://google.com/Somewhere", RepositoryInfo = new RepoCat.Transmission.Models.RepositoryInfo() { RepositoryName = this.testRepoOne.RepositoryName, OrganizationName = this.testRepoOne.OrganizationName, }, TargetExtension = "exe", RepositoryStamp = "1.0", AssemblyName = "Project2AssName", Components = { new ComponentManifest(new List <string>() { "One", "Two" }, new PropertiesCollection() { ("KeyOne", "ValueOne") } ) } }; ProjectInfo returnedPrj2 = await service.Upsert(prj2).ConfigureAwait(false); allProjects = await service.GetAllCurrentProjects(this.testRepoOne).ConfigureAwait(false); allProjects.Projects.Count.Should().Be(2, "because we just added 2 projects with same stamp"); allProjects.Projects.Should().OnlyContain(x => x.ProjectInfo.RepositoryStamp == "1.0"); return(returnedPrj2); }
public void UpdateAllIssues(PerformContext context) { var repoManagementService = new RepositoryManagementService(); var repositories = repoManagementService.GetAllPublicRepositories(); var gitHubService = new GitHubService(); foreach (var repository in repositories) { //RecurringJob.AddOrUpdate($"[IssueTracker] FullUpdate {repository.Name}", () => gitHubService.UpdateReviews(context, repository), Cron.Yearly(2, 31)); } }
public void UpdateGitHubIssues(PerformContext context) { var repoManagementService = new RepositoryManagementService(); var repositories = repoManagementService.GetAllPublicRepositories(); var gitHubService = new GitHubService(); foreach (var repository in repositories) { RecurringJob.AddOrUpdate($"[IssueTracker] Update {repository.Name}", () => gitHubService.UpdateIssues(context, repository), Cron.MinuteInterval(5)); } }
public List <ProcessedPullRequest> GetPullRequestCloseData(int startMonth = 6, int startYear = 2010, string repository = "") { var repoService = new RepositoryManagementService(); var pulls = string.IsNullOrWhiteSpace(repository) ? repoService.GetAllIssues(true).ToList() : repoService.GetAllIssues(true).Where(x => x.RepositoryName == repository).ToList(); var date = new DateTime(startYear, startMonth, 1); var prsCreated = pulls.Where(x => x.CreateDateTime >= date).ToList(); var processedPullRequests = new List <ProcessedPullRequest>(); foreach (var pr in prsCreated) { if (pr.State != "closed") { // still open, continue continue; } var processedPr = new ProcessedPullRequest(); processedPr.Number = pr.Number; processedPr.Repository = pr.RepositoryName; processedPr.Title = pr.Title; if (pr.ClosedDateTime.HasValue) { processedPr.CloseDateTime = pr.ClosedDateTime.Value; } processedPr.ClosedByUser = pr.CloseUser?.Login; // GitHub marks all merged PRs as "closed", so we want to differentiate: if there's no "merged" event then it was closed without merging if (pr.Events.Any(y => y.Name == "merged") == false) { var closeEvent = pr.Events.LastOrDefault(y => y.Name == "closed"); processedPr.ClosedByUser = closeEvent?.Actor?.Login; processedPr.CloseType = "closed"; } // There was a "merged" event if (pr.Events.Any(y => y.Name == "merged")) { var mergeEvent = pr.Events.LastOrDefault(y => y.Name == "merged"); processedPr.ClosedByUser = mergeEvent?.Actor?.Login; processedPr.CloseType = "merged"; } processedPullRequests.Add(processedPr); } return(processedPullRequests); }
public List <Issue> GetIdeasIssues() { var repoService = new RepositoryManagementService(); var ideasIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.ClosedDateTime == null && x.Labels.Any(l => l.Name == "status/idea")).ToList(); foreach (var issue in ideasIssues) { var ideaLabelEvent = issue.Events.FirstOrDefault(x => x.Name == "labeled" && x.Label.Name == "status/idea"); if (ideaLabelEvent != null) { issue.SetToIdea = ideaLabelEvent.CreateDateTime; } } return(ideasIssues); }
private static async Task SeedProjects(RepositoryManagementService service, string projectName, RepositoryInfo repo, params string[] stamps) { foreach (string stamp in stamps) { RepoCat.Transmission.Models.ProjectInfo prj = new RepoCat.Transmission.Models.ProjectInfo() { ProjectName = projectName, RepositoryStamp = stamp, RepositoryInfo = new RepoCat.Transmission.Models.RepositoryInfo() { OrganizationName = repo.OrganizationName, RepositoryName = repo.RepositoryName } }; await service.Upsert(prj).ConfigureAwait(false); } }
public List <string> GetPullRequestStats(string startDate, string endDate) { if (DateTime.TryParse(startDate, out var start) == false) { return(null); } if (DateTime.TryParse(endDate, out var end) == false) { return(null); } var repoManagementService = new RepositoryManagementService(); var repositories = repoManagementService.GetAllPublicRepositories().Where(x => x.InDashboard); var githubService = new GitHubService(); var contributors = new HashSet <string>(); foreach (var repository in repositories) { var allPulls = githubService .GetExistingPullsFromDisk(repository.Alias) .Where(x => x != null && x.IsPr && x.CreateDateTime >= start && x.CreateDateTime < end); foreach (var pull in allPulls) { contributors.Add(pull.User.Login); } } var hqUsersFile = HostingEnvironment.MapPath("~/Config/githubhq.txt"); var hqList = System.IO.File.ReadAllLines(hqUsersFile).Where(x => x.Trim() != "").Distinct().ToArray(); var contribFiltered = new List <string>(); foreach (var contributor in contributors) { if (hqList.Any(x => string.Equals(x, contributor, StringComparison.InvariantCultureIgnoreCase)) == false) { contribFiltered.Add(contributor); } } return(contribFiltered); }
public List <Issue> GetOpenPulls() { var repoService = new RepositoryManagementService(); var openPrs = repoService.GetAllCommunityIssues(true) .Where(x => x.ClosedDateTime == null).ToList(); foreach (var pr in openPrs) { var lastReview = pr.Reviews.LastOrDefault(); if (lastReview != null) { pr.ReviewState = lastReview.State; pr.LastReviewDate = lastReview.CreateDateTime; } } return(openPrs.OrderByDescending(x => x.LastReviewDate).ToList()); }
public List <Issue> GetNoCommentIssues() { var repoService = new RepositoryManagementService(); var communityIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.ClosedDateTime == null && x.Labels.Any(l => l.Name == "status/idea") == false).ToList(); var noCommentIssues = new List <Issue>(); foreach (var issue in communityIssues) { var firstTeamEvent = GetFirstTeamEventDateTime(issue); if (firstTeamEvent == null || firstTeamEvent == default(DateTime)) { noCommentIssues.Add(issue); } } return(noCommentIssues); }
public List <Issue> GetIssuesWithLabel(string label) { var repoService = new RepositoryManagementService(); var labelIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.ClosedDateTime == null && x.Labels.Any(l => l.Name == "status/idea") == false && x.Labels.Any(l => string.Equals(l.Name, label, StringComparison.InvariantCultureIgnoreCase))).ToList(); foreach (var issue in labelIssues) { foreach (var issueEvent in issue.Events) { if (issueEvent.Name == "labeled" && string.Equals(issueEvent.Label.Name, label, StringComparison.InvariantCultureIgnoreCase)) { issue.LabelAdded = issueEvent.CreateDateTime; } } } return(labelIssues.OrderByDescending(x => x.LabelAdded).ToList()); }
public async Task SnapshotRepo_ShouldOnlyReturnLastProjects() { RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), this.telemetryClient); await SetSnapshotMode(database, this.testRepoOne).ConfigureAwait(false); var allProjects = await service.GetAllCurrentProjects(this.testRepoOne).ConfigureAwait(false); allProjects.Projects.Count.Should().Be(0, "because there are no projects yet"); ProjectInfo returnedPrj2 = await this.AddTwoProjectsWithSameRepoStamp(service).ConfigureAwait(false); //now add just one with new stamp RepoCat.Transmission.Models.ProjectInfo prj2Again = new RepoCat.Transmission.Models.ProjectInfo() { ProjectName = "Project2", ProjectUri = "SomeLocation", RepositoryInfo = new RepoCat.Transmission.Models.RepositoryInfo() { RepositoryName = this.testRepoOne.RepositoryName, OrganizationName = this.testRepoOne.OrganizationName, }, TargetExtension = "exe", RepositoryStamp = "2.0" }; var returnedPrj2Again = await service.Upsert(prj2Again).ConfigureAwait(false); allProjects = await service.GetAllCurrentProjects(this.testRepoOne).ConfigureAwait(false); allProjects.Projects.Count.Should().Be(1, "because recently only added 1 project"); allProjects.Projects.Should().OnlyContain(x => x.ProjectInfo.RepositoryStamp == "2.0"); returnedPrj2Again.Id.Should().NotBe(returnedPrj2.Id); returnedPrj2Again.ProjectUri.Should().Be(returnedPrj2.ProjectUri); returnedPrj2Again.ProjectName.Should().Be(returnedPrj2.ProjectName); returnedPrj2Again.RepositoryId.Should().Be(returnedPrj2.RepositoryId); }
public async Task TestMultipleRepos_RelevantProjectsDeleted() { //arrange RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), TelemetryMock.InitializeMockTelemetryClient()); await SeedProjects(service, "Project1", this.snapshotRepoOne, "1.0.0", "2.0.0", "3.0.0"); await SeedProjects(service, "Project2", this.snapshotRepoOne, "1.0.0"); await SeedProjects(service, "Project3", this.snapshotRepoTwo, "1.0.0", "2.0.0", "3.0.0", "4.0.0"); await SeedProjects(service, "Project4", this.snapshotRepoTwo, "1.0.0", "4.0.0"); await SeedProjects(service, "Project5", this.defaultRepoOne, "1.0.0", "5.0.0"); SnapshotRepoCleaner cleaner = new SnapshotRepoCleaner(database); //assuming... Check.That(database.GetAllProjects().Result.Count()).Equals(11); //act SnapshotRepoCleanupResult result = await cleaner.PerformCleanupAsync(new SnapshotRepoCleanupSettings()); //assert Check.That(result.RepositoryResults.Keys.Select(x => x.RepositoryName)).ContainsExactly(this.snapshotRepoOne.RepositoryName, this.snapshotRepoTwo.RepositoryName); Check.That(result.RepositoryResults.Single(x => x.Key.Id == this.snapshotRepoOne.Id).Value.Equals(2)); Check.That(result.RepositoryResults.Single(x => x.Key.Id == this.snapshotRepoTwo.Id).Value.Equals(3)); var allProjects = database.GetAllProjects().Result.ToList(); Check.That(allProjects.Count()).Equals(6); Check.That(allProjects.Where(x => x.RepositoryId == this.snapshotRepoOne.Id).Select(x => x.ProjectName)) .ContainsExactly("Project1", "Project1"); Check.That(allProjects.Where(x => x.RepositoryId == this.snapshotRepoTwo.Id).Select(x => x.ProjectName)) .ContainsExactly("Project3", "Project3", "Project4"); Check.That(allProjects.Where(x => x.RepositoryId == this.defaultRepoOne.Id).Select(x => x.ProjectName)) .ContainsExactly("Project5"); }
public List <Issue> GetOldUpForGrabsIssues() { var repoService = new RepositoryManagementService(); var allCommunityIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.ClosedDateTime == null && x.Labels.Any(l => l.Name == "status/idea") == false).ToList(); var oldDate = DateTime.Now.AddDays(-120); var upForGrabsIssues = allCommunityIssues .Where(x => x.Labels.Any(l => l.Name == "community/up-for-grabs" || l.Name == "help wanted")) .OrderBy(x => x.CreateDateTime) .ToList(); var oldUpForGrabsIssues = new List <Issue>(); foreach (var issue in upForGrabsIssues) { foreach (var issueEvent in issue.Events) { if (issueEvent.Name == "labeled" && (issueEvent.Label.Name == "community/up-for-grabs" || issueEvent.Label.Name == "help wanted")) { if (issueEvent.CreateDateTime <= oldDate) { issue.SetToUpForGrabs = issueEvent.CreateDateTime; if (oldUpForGrabsIssues.Any(x => x.Number == issue.Number) == false) { oldUpForGrabsIssues.Add(issue); } } } } } return(oldUpForGrabsIssues); }
public List <ApproveddPullRequest> GetApprovedRequestCloseData(int startMonth = 6, int startYear = 2010, string repository = "") { var repoService = new RepositoryManagementService(); var date = new DateTime(startYear, startMonth, 1); var approvedPulls = string.IsNullOrWhiteSpace(repository) ? repoService.GetAllIssues(true).Where(x => x.CreateDateTime >= date && x.State != "closed" && x.Reviews.Any(y => y.State == "APPROVED")).ToList() : repoService.GetAllIssues(true).Where(x => x.CreateDateTime >= date && x.State != "closed" && x.Reviews.Any(y => y.State == "APPROVED") && x.RepositoryName == repository).ToList(); var approvedPullRequestData = new List <ApproveddPullRequest>(); foreach (var pull in approvedPulls) { var approvals = pull.Reviews.Where(x => x.State == "APPROVED").ToList(); var approvalNames = new List <string>(); foreach (var approval in approvals) { if (approvalNames.Contains(approval.Actor.Login) == false) { approvalNames.Add(approval.Actor.Login); } } var firstApproval = approvals.OrderBy(x => x.CreateDateTime).First(); var approvers = string.Join(",", approvalNames); approvedPullRequestData.Add(new ApproveddPullRequest { Number = pull.Number, Repository = pull.RepositoryName, Title = pull.Title, ApprovedDateTime = firstApproval.CreateDateTime, ApprovedByUser = approvers }); } return(approvedPullRequestData); }
public List <IssueStatistics> GetIssueStatistics(int startMonth = 6, int startYear = 2010, string repository = "", bool monthly = true) { var repoService = new RepositoryManagementService(); var allCommunityIssues = string.IsNullOrWhiteSpace(repository) ? repoService.GetAllCommunityIssues(false).ToList() : repoService.GetAllCommunityIssues(false).Where(x => x.RepositoryName == repository).ToList(); var issueStatistics = new List <IssueStatistics>(); var date = new DateTime(startYear, startMonth, 1); while (date < DateTime.Now) { var year = date.Year; var endMonth = monthly ? date.AddMonths(1).Month : date.AddYears(1).Month; var endYear = monthly ? date.AddMonths(1).Year : date.AddYears(1).Year; var startDate = new DateTime(year, date.Month, 1); var endDate = new DateTime(endYear, endMonth, 1); var issuesInPeriod = allCommunityIssues.Where(x => x.CreateDateTime >= startDate && x.CreateDateTime < endDate).ToList(); var issuesClosedInPeriod = issuesInPeriod.Where(x => x.State == "closed" && x.ClosedDateTime >= startDate && x.ClosedDateTime < endDate).ToList(); var yearStatistics = new IssueStatistics { CodegardenYear = year, Title = date.ToString(monthly ? "yyyyMM" : "yyyy"), CreatedIssues = issuesInPeriod.Count, ClosedIssues = issuesClosedInPeriod.Count, FirstCommentStatistics = new FirstCommentStatistics { AllFirstEventTimesInHours = new List <double>() }, AllIssues = issuesInPeriod }; var allFirstCommentTimesInHours = new List <double>(); var allClosingTimesInHours = new List <double>(); foreach (var issue in issuesInPeriod) { var firstCommentStatistics = GetFirstEventStatistics(issue); yearStatistics.FirstCommentStatistics.FirstEventOnTime += firstCommentStatistics.FirstEventOnTime; yearStatistics.FirstCommentStatistics.FirstEventLate += firstCommentStatistics.FirstEventLate; yearStatistics.FirstCommentStatistics.TeamEventMissing += firstCommentStatistics.TeamEventMissing; allFirstCommentTimesInHours.AddRange(firstCommentStatistics.AllFirstEventTimesInHours); if (issue.ClosedDateTime != null) { var timeSpan = Convert.ToInt32(issue.CreateDateTime.BusinessHoursUntil(issue.ClosedDateTime.Value)); allClosingTimesInHours.Add(timeSpan); if (issue.Labels.Any(x => x.Name.StartsWith("release/"))) { yearStatistics.ReleaseIssues += 1; } } } if (allFirstCommentTimesInHours.Any()) { yearStatistics.AverageHoursToFirstComment = (int)Math.Round(allFirstCommentTimesInHours.Average()); yearStatistics.MedianHoursToFirstComment = (int)Math.Round(allFirstCommentTimesInHours.Median()); } if (allClosingTimesInHours.Any()) { yearStatistics.AverageHoursToClose = (int)Math.Round(allClosingTimesInHours.Average()); yearStatistics.MedianHoursToClose = (int)Math.Round(allClosingTimesInHours.Median()); } issueStatistics.Add(yearStatistics); date = monthly ? date.AddMonths(1) : date.AddYears(1); } return(issueStatistics); }
public List <IssuesInPeriod> GetGroupedIssuesData(int fromDay, int fromMonth, int fromYear, int toDay, int toMonth, int toYear, string repository = "") { var gitHubService = new GitHubService(); var teamMembers = new List <string>(); foreach (var team in gitHubService.GetTeamMembers()) { teamMembers.AddRange(team.Members); } if (fromDay == 0) { fromDay = 1; } if (toDay == 0) { toDay = DateTime.DaysInMonth(toYear, toMonth); } var fromDate = DateTime.Parse($"{fromYear}-{fromMonth}-{fromDay} 00:00:00"); var toDate = DateTime.Parse($"{toYear}-{toMonth}-{toDay} 23:59:59"); var repoService = new RepositoryManagementService(); var allCommunityIssues = repoService.GetAllCommunityIssues(false) .Where(x => x.Labels.Any(l => l.Name == "status/idea") == false).ToList(); if (string.IsNullOrWhiteSpace(repository) == false) { allCommunityIssues = allCommunityIssues.Where(x => x.RepositoryName == repository).ToList(); } var issues = allCommunityIssues .Where(x => x.CreateDateTime >= fromDate && x.CreateDateTime <= toDate) .OrderBy(x => x.CreateDateTime) .GroupBy(x => new { x.CreateDateTime.Year, x.CreateDateTime.Month }) .ToDictionary(x => x.Key, x => x.ToList()); var groupedIssues = new List <IssuesInPeriod>(); foreach (var issuesInPeriod in issues) { var period = $"{issuesInPeriod.Key.Year}{issuesInPeriod.Key.Month:00}"; var groupName = $"{DateTimeFormatInfo.CurrentInfo.GetAbbreviatedMonthName(issuesInPeriod.Key.Month)} {issuesInPeriod.Key.Year}"; var issuesList = new IssuesInPeriod { MonthYear = period, GroupName = groupName, AllIssueClosingTimesInHours = string.Empty, IssueAverageClosingTimeInHours = 0, IssueMedianClosingTimeInHours = 0, TargetClosingTimeInHours = 2880, // 120 business days AllIssueFirstCommentTimesInHours = string.Empty, IssueAverageFirstCommentTimesInHours = 0, IssueMedianFirstCommentTimesInHours = 0, TargetFirstCommentTimeInHours = 48, // 2 business days NumberClosed = 0, NumberOpen = 0, NumberCreated = issuesInPeriod.Value.Count }; var year = issuesInPeriod.Key.Year; var month = issuesInPeriod.Key.Month; var periodFirstDay = new DateTime(year, month, 1); var periodLastDay = new DateTime(year, month, DateTime.DaysInMonth(year, month)); foreach (var issue in allCommunityIssues) { if (issue.CreateDateTime <= periodLastDay && issue.State != "closed") { issuesList.NumberOpen = issuesList.NumberOpen + 1; } } var allClosingTimesInHours = new List <double>(); var allFirstCommentTimesInHours = new List <double>(); foreach (var issue in issuesInPeriod.Value) { if (issue.State == "closed" && issue.ClosedDateTime.HasValue) { var createDateTime = issue.CreateDateTime; var closedDateTime = issue.ClosedDateTime.Value; if (closedDateTime < periodFirstDay || closedDateTime > periodLastDay) { continue; } issuesList.NumberClosed = issuesList.NumberClosed + 1; var hoursOpen = createDateTime.BusinessHoursUntil(closedDateTime); allClosingTimesInHours.Add(hoursOpen); } else { //var dateLastDayOfMonth = issue.CreateDateTime.GetDateLastDayOfMonth().AddDays(1).AddSeconds(-1); var hoursOpen = issue.CreateDateTime.BusinessHoursUntil(DateTime.Now); allClosingTimesInHours.Add(hoursOpen); } double hoursBeforeFirstReply = 0; double hoursBeforeFirstLabel = 0; foreach (var comment in issue.Comments.OrderBy(x => x.CreateDateTime)) { if (teamMembers.InvariantContains(comment.User.Login)) { hoursBeforeFirstReply = issue.CreateDateTime.BusinessHoursUntil(comment.CreateDateTime); } else { //var dateLastDayOfMonth = issue.CreateDateTime.GetDateLastDayOfMonth().AddDays(1).AddSeconds(-1); hoursBeforeFirstReply = issue.CreateDateTime.BusinessHoursUntil(DateTime.Now); } } if (issue.Events.Any()) { var firstLabel = issue.Events.OrderBy(x => x.CreateDateTime) .FirstOrDefault(x => x.Name == "labeled"); if (firstLabel != null) { hoursBeforeFirstLabel = issue.CreateDateTime.BusinessDaysUntil(firstLabel.CreateDateTime); } } if (hoursBeforeFirstLabel != 0 && hoursBeforeFirstReply != 0) { double hours; if (hoursBeforeFirstLabel < hoursBeforeFirstReply) { hours = hoursBeforeFirstLabel; } else { hours = hoursBeforeFirstReply; } allFirstCommentTimesInHours.Add(hours); } } issuesList.AllIssueClosingTimesInHours = string.Join(",", allClosingTimesInHours); if (allClosingTimesInHours.Any()) { issuesList.IssueAverageClosingTimeInHours = allClosingTimesInHours.Average(); issuesList.IssueMedianClosingTimeInHours = allClosingTimesInHours.Median(); } issuesList.AllIssueFirstCommentTimesInHours = string.Join(",", allFirstCommentTimesInHours); if (allFirstCommentTimesInHours.Any()) { issuesList.IssueAverageFirstCommentTimesInHours = allFirstCommentTimesInHours.Average(); issuesList.IssueMedianFirstCommentTimesInHours = allFirstCommentTimesInHours.Median(); } groupedIssues.Add(issuesList); } //foreach (var issuesInPeriod in issues) //{ // foreach (var issue in issuesInPeriod.Value) // { // if(issue.CreateDateTime >= fromDate && issue.CreateDateTime <= toDate) // { // var year = issuesInPeriod.Key.Year; // var month = issuesInPeriod.Key.Month; // if(issue.ClosedDateTime != null && issue.ClosedDateTime > new DateTime(year, month, DateTime.DaysInMonth(year, month)) // groupedIssues.Where(x => x.MonthYear == ) // } // } //} return(groupedIssues.OrderBy(x => x.MonthYear).ToList()); }
public List <Contributions> GetContributorStatistics(int startMonth = 6, int startYear = 2010, string repository = "", bool monthly = true) { var totalContributors = new List <Contributions>(); var firstPrs = new List <string>(); var repoService = new RepositoryManagementService(); var pullsNonHq = string.IsNullOrWhiteSpace(repository) ? repoService.GetAllCommunityIssues(true).ToList() : repoService.GetAllCommunityIssues(true).Where(x => x.RepositoryName == repository).ToList(); var date = new DateTime(startYear, startMonth, 1); while (date < DateTime.Now) { var year = date.Year; var endMonth = monthly ? date.AddMonths(1).Month : date.AddYears(1).Month; var endYear = monthly ? date.AddMonths(1).Year : date.AddYears(1).Year; var startDate = new DateTime(year, date.Month, 1); var endDate = new DateTime(endYear, endMonth, 1); var prsCreated = pullsNonHq.Where(x => x.CreateDateTime >= startDate && x.CreateDateTime < endDate).ToList(); var repoStatistics = new Contributions { CodegardenYear = year, Title = date.ToString(monthly ? "yyyyMM" : "yyyy"), FirstCommentStatistics = new FirstCommentStatistics { AllFirstEventTimesInHours = new List <double>() }, AllPulls = prsCreated }; var allFirstCommentTimesInHours = new List <double>(); var allClosingTimesInHours = new List <double>(); foreach (var pr in prsCreated) { var firstCommentStatistics = GetFirstEventStatistics(pr); repoStatistics.FirstCommentStatistics.FirstEventOnTime += firstCommentStatistics.FirstEventOnTime; repoStatistics.FirstCommentStatistics.FirstEventLate += firstCommentStatistics.FirstEventLate; repoStatistics.FirstCommentStatistics.TeamEventMissing += firstCommentStatistics.TeamEventMissing; allFirstCommentTimesInHours.AddRange(firstCommentStatistics.AllFirstEventTimesInHours); if (pr.ClosedDateTime != null) { var timeSpan = Convert.ToInt32(pr.CreateDateTime.BusinessHoursUntil(pr.ClosedDateTime.Value)); allClosingTimesInHours.Add(timeSpan); if (pr.Labels.Any(x => x.Name.StartsWith("release/"))) { repoStatistics.ReleasePullRequests += 1; } } } if (allFirstCommentTimesInHours.Any()) { repoStatistics.AverageHoursToFirstComment = (int)Math.Round(allFirstCommentTimesInHours.Average()); repoStatistics.MedianHoursToFirstComment = (int)Math.Round(allFirstCommentTimesInHours.Median()); } if (allClosingTimesInHours.Any()) { repoStatistics.AverageHoursToClose = (int)Math.Round(allClosingTimesInHours.Average()); repoStatistics.MedianHoursToClose = (int)Math.Round(allClosingTimesInHours.Median()); } repoStatistics.PullRequestsCreated = prsCreated.Count; // GitHub marks all merged PRs as "closed", so we want to differentiate: if there's no "merged" event then it was closed without merging var prsClosed = pullsNonHq.Where(x => x.State == "closed" && x.Events.Any(y => y.Name == "merged") == false && x.ClosedDateTime >= startDate && x.ClosedDateTime < endDate).ToList(); // There was a "merged" event and it was in the current period var prsMerged = pullsNonHq.Where(x => x.State == "closed" && x.Events.Any(y => y.Name == "merged") == true && x.Events.First(y => y.Name == "merged").CreateDateTime >= startDate && x.Events.First(y => y.Name == "merged").CreateDateTime < endDate).ToList(); // Created in this period and still open now or merged/closed after the last date in this period var prsStillOpen = pullsNonHq.Where(x => x.CreateDateTime >= startDate && x.CreateDateTime < endDate && (x.State == "open" || x.ClosedDateTime >= endDate || x.ClosedDateTime > endDate)).ToList(); repoStatistics.PullRequestsClosed = prsClosed.Count; repoStatistics.PullRequestsMerged = prsMerged.Count; repoStatistics.PullRequestsProcessed = prsClosed.Count + prsMerged.Count; repoStatistics.PullRequestsStillOpenInPeriod = prsStillOpen.Count; foreach (var pr in prsMerged) { if (firstPrs.Any(x => x == pr.User.Login)) { continue; } firstPrs.Add(pr.User.Login); repoStatistics.FirstAcceptedPullRequests += 1; } var contributors = prsMerged.Select(x => x.User.Login).Distinct().ToList(); repoStatistics.UniqueContributorCount = contributors.Count; totalContributors.Add(repoStatistics); date = monthly ? date.AddMonths(1) : date.AddYears(1); } return(new List <Contributions>(totalContributors.Where(x => x.UniqueContributorCount != 0).OrderBy(x => x.CodegardenYear))); }
public async Task DefaultRepo_ShouldReturnUpdatedProjects() { RepositoryDatabase database = new RepositoryDatabase(Settings); var service = new RepositoryManagementService(database, new Mapper(MappingConfigurationFactory.Create()), this.telemetryClient); var allProjects = await service.GetAllCurrentProjects(this.testRepoOne).ConfigureAwait(false); allProjects.Projects.Count.Should().Be(0, "because there are no projects yet"); await this.AddTwoProjectsWithSameRepoStamp(service).ConfigureAwait(false); ProjectInfo returnedPrj2 = await this.AddTwoProjectsWithSameRepoStamp(service).ConfigureAwait(false); //now add just one with new stamp and some changed properties (except for name and URI) RepoCat.Transmission.Models.ProjectInfo prj2Again = new RepoCat.Transmission.Models.ProjectInfo() { ProjectName = "Project2", ProjectUri = "SomeLocation", Owner = "An Owner", ProjectDescription = "A description", RepositoryInfo = new RepoCat.Transmission.Models.RepositoryInfo() { RepositoryName = this.testRepoOne.RepositoryName, OrganizationName = this.testRepoOne.OrganizationName, }, TargetExtension = "exe", RepositoryStamp = "2.0", AssemblyName = "Project2AssName_NEW", Components = { new ComponentManifest(new List <string>() { "Three", "Four" }, new PropertiesCollection() { { "KeyTwo", "ValueTwo" } } ) } }; var returnedPrj2Again = await service.Upsert(prj2Again).ConfigureAwait(false); allProjects = await service.GetAllCurrentProjects(this.testRepoOne).ConfigureAwait(false); allProjects.Projects.Count.Should().Be(2, "because we don't return latest stamp only"); allProjects.Projects.Should().Contain(x => x.ProjectInfo.RepositoryStamp == "2.0"); allProjects.Projects.Should().Contain(x => x.ProjectInfo.RepositoryStamp == "1.0"); returnedPrj2Again.Id.Should().Be(returnedPrj2.Id); returnedPrj2Again.ProjectUri.Should().Be(returnedPrj2.ProjectUri); returnedPrj2Again.ProjectName.Should().Be(returnedPrj2.ProjectName); returnedPrj2Again.RepositoryId.Should().Be(returnedPrj2.RepositoryId); var prj2ReturnedFromQuery = allProjects.Projects.Single(x => string.Equals(x.ProjectInfo.ProjectName, "Project2", StringComparison.Ordinal)); prj2ReturnedFromQuery.ProjectInfo.Id.Should().Be(returnedPrj2Again.Id); prj2ReturnedFromQuery.ProjectInfo.RepositoryStamp.Should().Be("2.0"); prj2ReturnedFromQuery.ProjectInfo.AssemblyName.Should().Be("Project2AssName_NEW"); prj2ReturnedFromQuery.ProjectInfo.Components.Single().Tags.Count.Should().Be(2); prj2ReturnedFromQuery.ProjectInfo.Components.Single().Properties.Count.Should().Be(1); prj2ReturnedFromQuery.ProjectInfo.Components.Single().Properties["KeyTwo"].Should().Be("ValueTwo"); prj2ReturnedFromQuery.ProjectInfo.Owner.Should().Be("An Owner"); prj2ReturnedFromQuery.ProjectInfo.ProjectDescription.Should().Be("A description"); }