コード例 #1
0
        protected override async Task ExecuteCoreAsync(ReportExecutionContext context)
        {
            context.Log.LogInformation($"Started function execution: {DateTime.Now}");

            var storageConnString   = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            BlobServiceClient   bsc = new BlobServiceClient(storageConnString);
            BlobContainerClient bcc = bsc.GetBlobContainerClient(ContainerName);

            // create the container
            bcc.CreateIfNotExists();

            context.Log.LogInformation("Storage account accessed");

            DateTime to = DateTime.UtcNow;

            foreach (RepositoryConfiguration repositoryConfiguration in context.RepositoryConfigurations)
            {
                // retrieve the last accessed time for this repository
                BlobClient bc          = bcc.GetBlobClient($"{repositoryConfiguration.Owner}_{repositoryConfiguration.Name}");
                DateTime   lastDateRun = DateTime.UtcNow.AddDays(-1);

                try
                {
                    string content = StreamHelpers.GetContentAsString(bc.Download().Value.Content);
                    lastDateRun = DateTime.Parse(content);
                }
                catch
                {
                }

                context.Log.LogInformation("Last processed date for {0} is {1}", repositoryConfiguration, lastDateRun);

                string owner = repositoryConfiguration.Owner;
                string repo  = repositoryConfiguration.Name;

                context.Log.LogInformation("Processing repository {0}\\{1}", owner, repo);

                HtmlPageCreator emailBody = new HtmlPageCreator($"New items in {repo}");

                // get new issues
                RetrieveNewItems(context, CreateQueryForNewItems(repositoryConfiguration, IssueIsQualifier.Issue), lastDateRun, emailBody, "New issues");

                // get new PRs
                RetrieveNewItems(context, CreateQueryForNewItems(repositoryConfiguration, IssueIsQualifier.PullRequest), lastDateRun, emailBody, "New PRs");

                // get needs attention issues
                RetrieveNeedsAttentionIssues(context, repositoryConfiguration, emailBody);

                emailBody.AddContent($"<p>Last checked range: {lastDateRun} -> {to} </p>");

                context.Log.LogInformation("Sending email...");
                // send the email
                EmailSender.SendEmail(context.SendGridToken, context.FromAddress, emailBody.GetContent(), repositoryConfiguration.ToEmail, repositoryConfiguration.CcEmail, $"New issues in the {repo} repo as of {to.ToShortDateString()}", context.Log);

                context.Log.LogInformation("Email sent...");

                bc.Upload(StreamHelpers.GetStreamForString(to.ToUniversalTime().ToString()), overwrite: true);
                context.Log.LogInformation($"Persisted last event time for {repositoryConfiguration.Owner}\\{repositoryConfiguration.Name} as {to}");
            }
        }
コード例 #2
0
        public override void Execute()
        {
            foreach (RepositoryConfig repositoryConfig in _cmdLine.RepositoriesList)
            {
                HtmlPageCreator emailBody   = new HtmlPageCreator($"Pull Requests older than 3 months in {repositoryConfig.Name}");
                bool            hasFoundPRs = FindStalePRsInRepo(repositoryConfig, emailBody);

                if (hasFoundPRs)
                {
                    // send the email
                    EmailSender.SendEmail(_cmdLine.EmailToken, _cmdLine.FromEmail, emailBody.GetContent(), repositoryConfig.ToEmail, repositoryConfig.CcEmail,
                                          $"Pull Requests older than 3 months in {repositoryConfig.Name}", _log);
                }
            }
        }
コード例 #3
0
        public override void Execute()
        {
            foreach (var repositoryConfig in _cmdLine.RepositoriesList)
            {
                HtmlPageCreator emailBody      = new HtmlPageCreator($"Customer reported issues with invalid state in {repositoryConfig.Repo}");
                bool            hasFoundIssues = ValidateCustomerReportedIssues(repositoryConfig, emailBody);

                if (hasFoundIssues)
                {
                    // send the email
                    EmailSender.SendEmail(_cmdLine.EmailToken, _cmdLine.FromEmail, emailBody.GetContent(), repositoryConfig.ToEmail, repositoryConfig.CcEmail,
                                          $"Customer reported issues in invalid state in repo {repositoryConfig.Repo}", _log);
                }
            }
        }
コード例 #4
0
        public override void Execute()
        {
            foreach (RepositoryConfig repositoryConfig in _cmdLine.RepositoriesList)
            {
                HtmlPageCreator emailBody      = new HtmlPageCreator($"Issues in expired milestones for {repositoryConfig.Name}");
                bool            hasFoundIssues = GetIssuesInBacklogMilestones(repositoryConfig, emailBody);

                if (hasFoundIssues)
                {
                    // send the email
                    EmailSender.SendEmail(_cmdLine.EmailToken, _cmdLine.FromEmail, emailBody.GetContent(), repositoryConfig.ToEmail, repositoryConfig.CcEmail,
                                          $"Issues in old milestone for {repositoryConfig.Name}", _log);
                }
            }
        }
コード例 #5
0
        protected override async Task ExecuteCoreAsync(ReportExecutionContext context)
        {
            foreach (RepositoryConfiguration repositoryConfiguration in context.RepositoryConfigurations)
            {
                HtmlPageCreator emailBody   = new HtmlPageCreator($"Pull Requests older than 3 months in {repositoryConfiguration.Name}");
                bool            hasFoundPRs = FindStalePRsInRepo(context, repositoryConfiguration, emailBody);

                if (hasFoundPRs)
                {
                    // send the email
                    EmailSender.SendEmail(context.SendGridToken, context.FromAddress, emailBody.GetContent(), repositoryConfiguration.ToEmail, repositoryConfiguration.CcEmail,
                                          $"Pull Requests older than 3 months in {repositoryConfiguration.Name}", context.Log);
                }
            }
        }
コード例 #6
0
        protected override async Task ExecuteCoreAsync(ReportExecutionContext context)
        {
            foreach (RepositoryConfiguration repositoryConfiguration in context.RepositoryConfigurations)
            {
                HtmlPageCreator emailBody      = new HtmlPageCreator($"Customer reported issues with invalid state in {repositoryConfiguration.Name}");
                bool            hasFoundIssues = ValidateCustomerReportedIssues(context, repositoryConfiguration, emailBody);

                if (hasFoundIssues)
                {
                    // send the email
                    EmailSender.SendEmail(context.SendGridToken, context.FromAddress, emailBody.GetContent(), repositoryConfiguration.ToEmail, repositoryConfiguration.CcEmail,
                                          $"Customer reported issues in invalid state in repo {repositoryConfiguration.Name}", context.Log);
                }
            }
        }
コード例 #7
0
        protected override async Task ExecuteCoreAsync(ReportExecutionContext context)
        {
            foreach (RepositoryConfiguration repositoryConfiguration in context.RepositoryConfigurations)
            {
                HtmlPageCreator emailBody      = new HtmlPageCreator($"Issues in expired milestones for {repositoryConfiguration.Name}");
                bool            hasFoundIssues = GetIssuesInBacklogMilestones(context, repositoryConfiguration, emailBody);

                if (hasFoundIssues)
                {
                    // send the email
                    EmailSender.SendEmail(context.SendGridToken, context.FromAddress, emailBody.GetContent(), repositoryConfiguration.ToEmail, repositoryConfiguration.CcEmail,
                                          $"Issues in old milestone for {repositoryConfiguration.Name}", context.Log);
                }
            }
        }
コード例 #8
0
        protected override async Task ExecuteCoreAsync(ReportExecutionContext context)
        {
            foreach (RepositoryConfiguration repositoryConfiguration in context.RepositoryConfigurations)
            {
                await ExecuteWithRetryAsync(3, async() =>
                {
                    HtmlPageCreator emailBody = new HtmlPageCreator($"Test related issues in {repositoryConfiguration.Name}");
                    bool hasFoundIssues       = FindIssuesWithLabel(context, repositoryConfiguration, emailBody);

                    if (hasFoundIssues)
                    {
                        // send the email
                        EmailSender.SendEmail(context.SendGridToken, context.FromAddress, emailBody.GetContent(), repositoryConfiguration.ToEmail, repositoryConfiguration.CcEmail,
                                              $"Issues with test-* labels for {repositoryConfiguration.Name}", Logger);
                    }
                });
            }
        }
コード例 #9
0
        private bool FindStalePRsInRepo(RepositoryConfig repositoryConfig, HtmlPageCreator emailBody)
        {
            TableCreator tc = new TableCreator($"Pull Requests older than {DateTime.Now.AddMonths(-3).ToShortDateString()}");

            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

            _log.LogInformation($"Retrieving PR information for repo {repositoryConfig.Name}");
            List <ReportIssue> oldPrs = new List <ReportIssue>();

            foreach (Issue issue in _gitHub.SearchForGitHubIssues(CreateQuery(repositoryConfig)))
            {
                _log.LogInformation($"Found stale PR  {issue.Number}");
                oldPrs.Add(new ReportIssue()
                {
                    Issue = issue, Note = string.Empty, Milestone = null
                });
            }

            emailBody.AddContent(tc.GetContent(oldPrs));
            return(oldPrs.Any());
        }
コード例 #10
0
        private bool RetrieveNeedsAttentionIssues(RepositoryConfig repositoryConfig, HtmlPageCreator emailBody)
        {
            TableCreator tc = new TableCreator("Issues that need attention");

            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

            List <ReportIssue> issues = new List <ReportIssue>();

            foreach (Issue issue in _gitHub.SearchForGitHubIssues(CreateQueryForNeedsAttentionItems(repositoryConfig)))
            {
                issues.Add(new ReportIssue()
                {
                    Issue     = issue,
                    Milestone = issue.Milestone,
                    Note      = string.Empty
                });
            }

            emailBody.AddContent(tc.GetContent(issues));
            return(issues.Any());
        }
コード例 #11
0
        private bool FindIssuesInPastDuesMilestones(ReportExecutionContext context, RepositoryConfiguration repositoryConfig, HtmlPageCreator emailBody)
        {
            TableCreator tc = new TableCreator("Issues in past-due milestones");

            tc.DefineTableColumn("Milestone", TableCreator.Templates.Milestone);
            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

            context.Log.LogInformation($"Retrieving milestone information for repo {repositoryConfig.Name}");
            IEnumerable <Milestone> milestones = context.GitHubClient.ListMilestones(repositoryConfig).GetAwaiter().GetResult();

            List <Milestone> pastDueMilestones = new List <Milestone>();

            foreach (Milestone item in milestones)
            {
                if (item.DueOn != null && DateTimeOffset.Now > item.DueOn)
                {
                    context.Log.LogWarning($"Milestone {item.Title} past due ({item.DueOn.Value}) has {item.OpenIssues} open issue(s).");
                    if (item.OpenIssues > 0)
                    {
                        pastDueMilestones.Add(item);
                    }
                }
            }

            context.Log.LogInformation($"Found {pastDueMilestones.Count} past due milestones with active issues");

            List <ReportIssue> issuesInPastMilestones = new List <ReportIssue>();

            foreach (Milestone item in pastDueMilestones)
            {
                context.Log.LogInformation($"Retrieve issues for milestone {item.Title}");

                foreach (Issue issue in context.GitHubClient.SearchForGitHubIssues(CreateQuery(repositoryConfig, item)))
                {
                    issuesInPastMilestones.Add(new ReportIssue()
                    {
                        Issue     = issue,
                        Milestone = item,
                        Note      = string.Empty
                    });
                }
            }

            emailBody.AddContent(tc.GetContent(issuesInPastMilestones));
            return(issuesInPastMilestones.Any());
        }
コード例 #12
0
        private bool GetIssuesInBacklogMilestones(RepositoryConfig repositoryConfig, HtmlPageCreator emailBody)
        {
            _log.LogInformation($"Retrieving milestone information for repo {repositoryConfig.Name}");
            IEnumerable <Milestone> milestones = _gitHub.ListMilestones(repositoryConfig).GetAwaiter().GetResult();

            List <Milestone> backlogMilestones = new List <Milestone>();

            foreach (Milestone item in milestones)
            {
                if (item.DueOn == null)
                {
                    _log.LogWarning($"Milestone {item.Title} has {item.OpenIssues} open issue(s).");
                    if (item.OpenIssues > 0)
                    {
                        backlogMilestones.Add(item);
                    }
                }
            }

            _log.LogInformation($"Found {backlogMilestones.Count} past due milestones with active issues");
            List <ReportIssue> issuesInBacklogMilestones = new List <ReportIssue>();

            foreach (Milestone item in backlogMilestones)
            {
                _log.LogInformation($"Retrieve issues for milestone {item.Title}");

                foreach (Issue issue in _gitHub.SearchForGitHubIssues(CreateQuery(repositoryConfig, item)))
                {
                    issuesInBacklogMilestones.Add(new ReportIssue()
                    {
                        Issue     = issue,
                        Milestone = item,
                        Note      = string.Empty
                    });
                }
            }

            // Split the list into 3:
            // > 12months
            // > 6months
            // 0-6months

            IEnumerable <IGrouping <string, ReportIssue> > groups = issuesInBacklogMilestones.GroupBy(i =>
                                                                                                      i.Issue.CreatedAt > DateTime.Now.AddMonths(-6) ?
                                                                                                      "C. Issues created in the last 6 months" :
                                                                                                      i.Issue.CreatedAt <= DateTime.Now.AddMonths(-6) && i.Issue.CreatedAt > DateTime.Now.AddMonths(-12) ?
                                                                                                      "B. Issues created between 6 and 12 months ago" :
                                                                                                      "A. Issues created more than 12 months ago");

            foreach (IGrouping <string, ReportIssue> group in groups.OrderBy(g => g.Key))
            {
                TableCreator tc = new TableCreator(group.Key);
                tc.DefineTableColumn("Milestone", TableCreator.Templates.Milestone);
                tc.DefineTableColumn("Created", i => i.Issue.CreatedAt.UtcDateTime.ToShortDateString());
                tc.DefineTableColumn("Title", TableCreator.Templates.Title);
                tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
                tc.DefineTableColumn("Author", TableCreator.Templates.Author);
                tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

                emailBody.AddContent(tc.GetContent(group));
            }

            return(issuesInBacklogMilestones.Any());
        }
コード例 #13
0
        public override void Execute()
        {
            _log.LogInformation($"Started function execution: {DateTime.Now}");

            var storageConnString   = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
            BlobServiceClient   bsc = new BlobServiceClient(storageConnString);
            BlobContainerClient bcc = bsc.GetBlobContainerClient(ContainerName);

            // create the container
            bcc.CreateIfNotExists();

            _log.LogInformation("Storage account accessed");

            DateTime to = DateTime.UtcNow;
            DateTime fromTwoDaysBack = DateTime.UtcNow.AddDays(-2);

            foreach (var repositoryConfig in _cmdLine.RepositoriesList)
            {
                // retrieve the last accessed time for this repository
                BlobClient bc          = bcc.GetBlobClient($"{repositoryConfig.Owner}_{repositoryConfig.Repo}");
                DateTime   lastDateRun = DateTime.UtcNow.AddDays(-1);

                try
                {
                    string content = StreamHelpers.GetContentAsString(bc.Download().Value.Content);
                    lastDateRun = DateTime.Parse(content);
                }
                catch
                {
                }

                _log.LogInformation("Last processed date for {0} is {1}", repositoryConfig, lastDateRun);

                string owner = repositoryConfig.Owner;
                string repo  = repositoryConfig.Repo;

                _log.LogInformation("Processing repository {0}\\{1}", owner, repo);

                HtmlPageCreator emailBody = new HtmlPageCreator($"New items in {repo}");

                SearchIssuesRequest requestOptions = new SearchIssuesRequest()
                {
#pragma warning disable CS0618 // Type or member is obsolete
                    Created = DateRange.Between(fromTwoDaysBack, to),
#pragma warning restore CS0618 // Type or member is obsolete
                    Order = SortDirection.Descending,
                    Repos = new RepositoryCollection()
                };

                requestOptions.Repos.Add(owner, repo);

                // get the issues
                requestOptions.Is = new[] { IssueIsQualifier.Open, IssueIsQualifier.Issue };
                RetrieveItemsFromGitHub(requestOptions, lastDateRun, emailBody, "New issues");

                // get the PRs
                requestOptions.Is = new[] { IssueIsQualifier.Open, IssueIsQualifier.PullRequest };
                RetrieveItemsFromGitHub(requestOptions, lastDateRun, emailBody, "New PRs");

                emailBody.AddContent($"<p>Last checked range: {lastDateRun} -> {to} </p>");

                _log.LogInformation("Sending email...");
                // send the email
                EmailSender.SendEmail(_cmdLine.EmailToken, _cmdLine.FromEmail, emailBody.GetContent(), repositoryConfig.ToEmail, repositoryConfig.CcEmail, $"New issues in the {repo} repo as of {to.ToShortDateString()}", _log);

                _log.LogInformation("Email sent...");

                bc.Upload(StreamHelpers.GetStreamForString(to.ToUniversalTime().ToString()), overwrite: true);
                _log.LogInformation($"Persisted last event time for {repositoryConfig.Owner}\\{repositoryConfig.Repo} as {to}");
            }
        }
コード例 #14
0
        private bool RetrieveNewItems(ReportExecutionContext context, SearchIssuesRequest requestOptions, DateTime from, HtmlPageCreator emailBody, string header)
        {
            TableCreator tc = new TableCreator(header);

            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("State", i => i.Issue.State.ToString());
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

            List <ReportIssue> issues = new List <ReportIssue>();

            foreach (Issue issue in context.GitHubClient.SearchForGitHubIssues(requestOptions))
            {
                if (issue.CreatedAt.ToUniversalTime() >= from.ToUniversalTime())
                {
                    issues.Add(new ReportIssue()
                    {
                        Issue = issue, Note = string.Empty, Milestone = null
                    });
                }
            }

            //sort the issues by state, descending becasue Open should show up before Closed
            emailBody.AddContent(tc.GetContent(issues.OrderByDescending(i => i.Issue.State.ToString())));

            return(issues.Any());
        }
コード例 #15
0
        private bool RetrieveItemsFromGitHub(SearchIssuesRequest requestOptions, DateTime from, HtmlPageCreator emailBody, string header)
        {
            TableCreator tc = new TableCreator(header);

            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

            Colorizer.WriteLine("Retrieving issues");
            List <ReportIssue> issues = new List <ReportIssue>();

            foreach (var issue in _gitHub.SearchForGitHubIssues(requestOptions))
            {
                if (issue.CreatedAt.ToUniversalTime() >= from.ToUniversalTime())
                {
                    issues.Add(new ReportIssue()
                    {
                        Issue = issue, Note = string.Empty, Milestone = null
                    });
                }
            }

            emailBody.AddContent(tc.GetContent(issues));

            return(issues.Any());
        }
コード例 #16
0
        private bool FindIssuesWithLabel(ReportExecutionContext context, RepositoryConfiguration repositoryConfig, HtmlPageCreator emailBody)
        {
            List <ReportIssue> testIssues = new List <ReportIssue>();

            foreach (string label in _labels)
            {
                Logger.LogInformation($"Retrieve issues for label {label}");

                foreach (Issue issue in context.GitHubClient.SearchForGitHubIssues(CreateQuery(repositoryConfig, label)))
                {
                    testIssues.Add(new ReportIssue()
                    {
                        Issue = issue,
                        Note  = $"Label: {label}"
                    });
                }
            }

            IEnumerable <IGrouping <string, ReportIssue> > groups = testIssues.GroupBy(g => g.Note);

            foreach (IGrouping <string, ReportIssue> group in groups.OrderBy(g => g.Key))
            {
                TableCreator tc = new TableCreator(group.Key);
                tc.DefineTableColumn("Milestone", TableCreator.Templates.Milestone);
                tc.DefineTableColumn("Title", TableCreator.Templates.Title);
                tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
                tc.DefineTableColumn("Author", TableCreator.Templates.Author);
                tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);

                emailBody.AddContent(tc.GetContent(group));
            }

            return(testIssues.Any());
        }
        private bool ValidateCustomerReportedIssues(ReportExecutionContext context, RepositoryConfiguration repositoryConfig, HtmlPageCreator emailBody)
        {
            TableCreator tc = new TableCreator("Customer reported issues");

            tc.DefineTableColumn("Title", TableCreator.Templates.Title);
            tc.DefineTableColumn("Labels", TableCreator.Templates.Labels);
            tc.DefineTableColumn("Author", TableCreator.Templates.Author);
            tc.DefineTableColumn("Assigned", TableCreator.Templates.Assigned);
            tc.DefineTableColumn("Issues Found", i => i.Note);

            List <ReportIssue> issuesWithNotes = new List <ReportIssue>();

            foreach (Issue issue in context.GitHubClient.SearchForGitHubIssues(CreateQuery(repositoryConfig)))
            {
                if (!ValidateIssue(issue, out string issuesFound))
                {
                    issuesWithNotes.Add(new ReportIssue()
                    {
                        Issue = issue, Note = issuesFound
                    });
                    Logger.LogWarning($"{issue.Number}: {issuesFound}");
                }
            }

            // order the issues by the list of issues they have.
            issuesWithNotes = issuesWithNotes.OrderBy(i => i.Note).ToList();

            emailBody.AddContent(tc.GetContent(issuesWithNotes));

            return(issuesWithNotes.Any());
        }