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());
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #11
0
 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);
     }
 }
Beispiel #12
0
        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);
        }
Beispiel #17
0
        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);
        }
Beispiel #21
0
        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");
        }