Exemple #1
0
        public async void Process(IssueEventPayload payload)
        {
            // verify that sender is a github user and not our own events
            Log.Information("Sender: ", payload.Sender);

            // process the hooks based in action type
            Log.Information("Action: ", payload.Action);

            // extract what we need from the issue/repository
            // in order to trigger our events
            Log.Information("Issue: ", payload.Issue);
            Log.Information("Repository: ", payload.Repository);

            // convert github issue to SDE dto objects

            // trigger events
            // sdeClientEvents.TriggerTaskCreated(sdeTask);
            // sdeClientEvents.TriggerTaskUpdate(sdeTask);
            // sdeClientEvents.TriggerTaskNoteCreate(sdeTaskNote);
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "POST", Route = null)]
            HttpRequestMessage req, ILogger log)
        {
            var payloadJson = await req.Content.ReadAsStringAsync();

            SimpleJsonSerializer serializer   = new SimpleJsonSerializer();
            IssueEventPayload    issuePayload = serializer.Deserialize <IssueEventPayload>(payloadJson);

            if (issuePayload.Issue.User.Type.HasValue &&
                issuePayload.Issue.User.Type.Value == AccountType.Bot)
            {
                log.LogInformation("Comment is from DarcBot, ignoring.");
                return(new OkObjectResult($"Ignoring DarcBot comment"));
            }

            if (issuePayload.Action != "opened" &&
                issuePayload.Action != "reopened" &&
                issuePayload.Action != "closed")
            {
                log.LogInformation($"Received github action '{issuePayload.Action}', nothing to do");
                return(new OkObjectResult($"DarcBot has nothing to do with github issue action '{issuePayload.Action}'"));
            }

            // Determine identifiable information for triage item
            TriageItem triageItem = GetTriageItemProperties(issuePayload.Issue.Body);

            triageItem.Url = issuePayload.Issue.HtmlUrl;

            if (triageItem == null)
            {
                /* Item is not a triage item (does not contain identifiable information), do nothing */
                log.LogInformation($"{issuePayload.Issue.Url} is not a triage type issue.");
                return(new OkObjectResult("No identifiable information detected"));
            }

            int.TryParse(System.Environment.GetEnvironmentVariable("AppId"), out int appId);

            // Create jwt token
            // Private key is stored in Azure Key vault by downloading the private key (pem file) from GitHub, then
            // using the Azure CLI to store the value in key vault.
            // ie: az keyvault secret set --vault-name [vault name] --name GitHubApp-DarcBot-PrivateKey --encoding base64 --file [pem key file path]
            GitHubAppTokenProvider gitHubTokenProvider = new GitHubAppTokenProvider();
            var installationToken = gitHubTokenProvider.GetAppTokenFromEnvironmentVariableBase64(appId, "PrivateKey");

            // create client using jwt as a bearer token
            var          userAgent = new Octokit.ProductHeaderValue("DarcBot");
            GitHubClient appClient = new GitHubClient(userAgent)
            {
                Credentials = new Credentials(installationToken, AuthenticationType.Bearer),
            };

            // using the client, create an installation token
            AccessToken token = await appClient.GitHubApps.CreateInstallationToken(issuePayload.Installation.Id);

            // with the installation token, create a new GitHubClient that has the apps permissions
            var gitHubClient = new GitHubClient(new ProductHeaderValue("DarcBot-Installation"))
            {
                Credentials = new Credentials(token.Token)
            };

            if (issuePayload.Action == "created" ||
                issuePayload.Action == "opened" ||
                issuePayload.Action == "reopened")
            {
                // First, look for duplicate issues that are open
                var openIssues = new RepositoryIssueRequest
                {
                    Filter        = IssueFilter.All,
                    State         = ItemStateFilter.Open,
                    SortProperty  = IssueSort.Created,
                    SortDirection = SortDirection.Ascending,
                };
                openIssues.Labels.Add(_darcBotLabelName);

                log.LogInformation("Getting open issues");
                var issues = await gitHubClient.Issue.GetAllForRepository(issuePayload.Repository.Id, openIssues);

                log.LogInformation($"There are {issues.Count} open issues with the '{_darcBotLabelName}' label");
                foreach (var checkissue in issues)
                {
                    if (checkissue.Number != issuePayload.Issue.Number)
                    {
                        TriageItem issueItem = GetTriageItemProperties(checkissue.Body);
                        if (triageItem.Equals(issueItem))
                        {
                            await gitHubClient.Issue.Comment.Create(issuePayload.Repository.Id, issuePayload.Issue.Number, $"DarcBot has detected a duplicate issue.\n\nClosing as duplicate of {checkissue.HtmlUrl}\n\nFor more information see {_docLink}");

                            var issueUpdate = new IssueUpdate
                            {
                                State = ItemState.Closed,
                            };
                            await gitHubClient.Issue.Update(issuePayload.Repository.Id, issuePayload.Issue.Number, issueUpdate);

                            return(new OkObjectResult($"Resolved as duplicate of {checkissue.Number}"));
                        }
                    }
                }

                // No duplicates, add label and move issue to triage
                var issue = await gitHubClient.Issue.Get(issuePayload.Repository.Id, issuePayload.Issue.Number);

                var update = issue.ToUpdate();
                update.AddLabel(_darcBotLabelName);
                await gitHubClient.Issue.Update(issuePayload.Repository.Id, issuePayload.Issue.Number, update);

                triageItem.UpdatedCategory = "InTriage";
            }

            if (issuePayload.Action == "closed")
            {
                IReadOnlyList <IssueComment> comments = gitHubClient.Issue.Comment.GetAllForIssue(issuePayload.Repository.Id, issuePayload.Issue.Number).Result;

                foreach (var comment in comments)
                {
                    // Look for category information in comment
                    string category = GetDarcBotProperty("category", comment.Body);
                    if (!string.IsNullOrEmpty(category))
                    {
                        triageItem.UpdatedCategory = category;
                    }
                }
            }

            log.LogInformation($"buildId: {triageItem.BuildId}, recordId: {triageItem.RecordId}, index: {triageItem.Index}, category: {triageItem.UpdatedCategory}, url: {triageItem.Url}");

            await IngestTriageItemsIntoKusto(new[] { triageItem }, log);

            await gitHubClient.Issue.Comment.Create(issuePayload.Repository.Id, issuePayload.Issue.Number, $"DarcBot has updated the 'TimelineIssuesTriage' database.\n**PowerBI reports may take up to 24 hours to refresh**\n\nSee {_docLink} for more information and 'darcbot' usage.");

            return(new OkObjectResult("Success"));
        }