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 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); }
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); }
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 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 <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 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); }