private async Task <QuantifierResult> QuantifyPullRequest(PullRequestEventPayload payload) { var gitHubClientAdapter = await gitHubClientAdapterFactory.GetGitHubClientAdapterAsync( payload.Installation.Id, new Uri(payload.PullRequest.HtmlUrl).DnsSafeHost); var quantifierInput = await GetQuantifierInputFromPullRequest(payload, gitHubClientAdapter); var context = await GetContextFromRepoIfPresent(payload, gitHubClientAdapter); var quantifyClient = new QuantifyClient(context); var quantifierClientResult = await quantifyClient.Compute(quantifierInput); await ApplyLabelToPullRequest( payload, gitHubClientAdapter, quantifierClientResult, quantifyClient.Context.Thresholds.Select(t => t.Label)); var quantifierContextLink = !string.IsNullOrWhiteSpace(context) ? $"{payload.Repository.HtmlUrl}/blob/{payload.Repository.DefaultBranch}/prquantifier.yaml" : string.Empty; await UpdateCommentOnPullRequest( payload, gitHubClientAdapter, quantifierClientResult, quantifierContextLink); return(quantifierClientResult); }
private async Task <QuantifierResult> QuantifyPullRequest(PullRequestEventPayload payload) { var gitHubClientAdapter = await gitHubClientAdapterFactory.GetGitHubClientAdapterAsync( payload.Installation.Id, new Uri(payload.PullRequest.HtmlUrl).DnsSafeHost); // get pull request var pullRequest = await gitHubClientAdapter.GetPullRequestAsync( payload.Repository.Id, payload.PullRequest.Number); // get pull request files var pullRequestFiles = await gitHubClientAdapter.GetPullRequestFilesAsync( payload.Repository.Id, payload.PullRequest.Number); // convert to quantifier input var quantifierInput = new QuantifierInput(); foreach (var pullRequestFile in pullRequestFiles) { if (pullRequestFile.Patch == null) { continue; } var changeType = GitChangeType.Modified; switch (pullRequestFile.Status) { case "modified": break; case "added": changeType = GitChangeType.Added; break; case "deleted": changeType = GitChangeType.Deleted; break; } var fileExtension = !string.IsNullOrWhiteSpace(pullRequestFile.FileName) ? new FileInfo(pullRequestFile.FileName).Extension : string.Empty; var gitFilePatch = new GitFilePatch( pullRequestFile.FileName, fileExtension) { ChangeType = changeType, AbsoluteLinesAdded = pullRequestFile.Additions, AbsoluteLinesDeleted = pullRequestFile.Deletions, DiffContent = pullRequestFile.Patch, }; quantifierInput.Changes.Add(gitFilePatch); } // get context if present string context = null; try { var rawContext = await gitHubClientAdapter.GetRawFileAsync( payload.Repository.Owner.Login, payload.Repository.Name, "/prquantifier.yaml"); context = Encoding.UTF8.GetString(rawContext); } catch (NotFoundException) { } catch { // ignored } var quantifyClient = new QuantifyClient(context); var quantifierClientResult = await quantifyClient.Compute(quantifierInput); // create a new label in the repository if doesn't exist try { var existingLabel = await gitHubClientAdapter.GetLabelAsync( payload.Repository.Id, quantifierClientResult.Label); } catch (NotFoundException) { // create new label var color = Color.FromName(quantifierClientResult.Color); await gitHubClientAdapter.CreateLabelAsync( payload.Repository.Id, new NewLabel(quantifierClientResult.Label, ConvertToHex(color))); } // apply label to pull request await gitHubClientAdapter.ApplyLabelAsync( payload.Repository.Id, payload.PullRequest.Number, new[] { quantifierClientResult.Label }); // create a comment on the issue var defaultBranch = payload.Repository.DefaultBranch; var quantifierContextLink = $"{payload.Repository.HtmlUrl}/blob/{defaultBranch}/prquantifier.yaml"; var comment = await quantifierClientResult.ToMarkdownCommentAsync( payload.Repository.HtmlUrl, quantifierContextLink, payload.PullRequest.HtmlUrl, payload.PullRequest.User.Login); await gitHubClientAdapter.CreateIssueCommentAsync( payload.Repository.Id, payload.PullRequest.Number, comment); return(quantifierClientResult); }
public async Task HandleEvent(string gitHubEvent) { var payload = new Octokit.Internal.SimpleJsonSerializer().Deserialize <InstallationEventPayload>(gitHubEvent); if (Enum.TryParse( payload.Action, true, out GitHubEventActions parsedAction) && parsedAction != GitHubEventActions.Created) { logger.LogInformation("Ignoring installation event with {action} action", payload.Action); return; } logger.LogInformation("Handling installation event for {account}", payload.Installation.Account.Login); foreach (var payloadRepository in payload.Repositories) { if (payloadRepository.Fork) { logger.LogInformation( "Ignoring forked repository {account}/{repository}", payload.Installation.Account.Login, payloadRepository.Name); continue; } var repoDirectory = Guid.NewGuid().ToString(); var clonePath = fileSystem.Path.Combine(fileSystem.Path.GetTempPath(), repoDirectory); try { var dnsSafeHost = new Uri(payload.Installation.HtmlUrl).DnsSafeHost; var gitHubClientAdapter = await gitHubClientAdapterFactory.GetGitHubClientAdapterAsync( payload.Installation.Id, dnsSafeHost); var installationToken = gitHubClientAdapter.Credentials.Password; logger.LogInformation( "Cloning repository {account}/{repository}", payload.Installation.Account.Login, payloadRepository.Name); Repository.Clone( $"https://*****:*****@{dnsSafeHost}/{payload.Installation.Account.Login}/{payloadRepository.Name}.git", clonePath); await Tools.QuantifyRepositories.Program.Main(new[] { "-repoPath", clonePath }); using var streamReader = new StreamReader(fileSystem.Path.Combine(clonePath, $"{repoDirectory}_QuantifierResults.csv")); using var csv = new CsvReader(streamReader, CultureInfo.InvariantCulture); csv.Context.RegisterClassMap <CommitStatsMap>(); var commitStats = csv.GetRecords <CommitStats>(); commitStats = commitStats.Select( r => { r.PartitionKey = $"{payload.Installation.Account.Login}-{payloadRepository.Name}"; r.RowKey = r.CommitSha1; return(r); }).ToList(); var commitStatsMap = commitStats.ToDictionary(c => c.CommitSha1); // get all closed pull requests var closedPrs = await gitHubClientAdapter.GetClosedPullRequestsAsync(payloadRepository.Id); foreach (var pr in closedPrs) { var prLeadTime = pr.MergedAt?.Subtract(pr.CreatedAt); if (prLeadTime != null && commitStatsMap.TryGetValue(pr.MergeCommitSha, out var commitStat)) { commitStat.PullRequestLeadTime = (TimeSpan)prLeadTime; commitStat.PullRequestId = pr.Id; commitStat.PullRequestAuthor = pr.User.Login; } } // upload only the commits for which there was a PR var commitStatsToUpload = commitStatsMap.Values.Where(c => c.PullRequestId != 0).ToList(); logger.LogInformation( "Calculated {commitCount} commits to upload for {account}/{repository}", commitStatsToUpload.Count, payload.Installation.Account.Login, payloadRepository.Name); await blobStorage.CreateTableAsync(nameof(CommitStats)); await blobStorage.InsertOrReplaceTableEntitiesAsync(nameof(CommitStats), commitStatsToUpload); } catch (Exception e) { logger.LogError( e, "Error during processing installation event for {account}/{repository}", payload.Installation.Account.Login, payloadRepository.Name); throw; } finally { fileSystem.DeleteDirectory(clonePath); } } }