public async Task FilesWithoutExt_ShowFullPathInSummary() { // Arrange gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 2); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2", 4); gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 5); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2", 2); var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName); // Assert Assert.True(comment.IndexOf("fake2 : +0 -2", StringComparison.Ordinal) > -1); Assert.True(comment.IndexOf(".cs : +3 -0", StringComparison.Ordinal) > -1); }
public async Task ToMarkdownCommentAsync_Successful() { // Arrange gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 2); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 4); gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 5); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 2); var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName); // Assert Assert.True(!string.IsNullOrWhiteSpace(comment)); Assert.StartsWith("### Pull Request Quantified", comment); }
private static async Task Quantify(string repoPath) { if (string.IsNullOrWhiteSpace(repoPath)) { return; } var fileInfoRepoPath = new FileInfo(repoPath); var quantifyClient = new QuantifyClient(string.Empty); var resultFile = Path.Combine(repoPath, $"{fileInfoRepoPath.Name}_QuantifierResults.csv"); if (File.Exists(resultFile)) { File.Delete(resultFile); } await InitializeResultFile(resultFile); await RunQuantifier( quantifyClient, resultFile, repoPath); }
public async Task QuantifyClient_AgainstCommit() { // Arrange gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 2); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 4); gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake3.cs", 5); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake4.cs", 2); var commit = gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake6.cs", 3); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake5.cs", 6); gitRepoHelpers.CommitFilesToRepo(); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute( gitRepoHelpers.RepoPath, commit.Sha); // Assert Assert.True(!string.IsNullOrEmpty(quantifierResult.Label)); Assert.Equal(7, quantifierResult.QuantifiedLinesAdded); Assert.Equal(0, quantifierResult.QuantifiedLinesDeleted); Assert.Equal(2, (int)quantifierResult.PercentileAddition); Assert.Equal(0, quantifierResult.PercentileDeletion); Assert.Equal(2, (int)quantifierResult.FormulaPercentile); }
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); }
public async Task QuantifyClient_AgainstCommitNotFound() { var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute( gitRepoHelpers.RepoPath, nameof(string.Empty)); // Assert Assert.Equal("No Changes", quantifierResult.Label); Assert.Equal(0, quantifierResult.QuantifiedLinesAdded); Assert.Equal(0, quantifierResult.QuantifiedLinesDeleted); Assert.Equal(0, quantifierResult.PercentileAddition); Assert.Equal(0, quantifierResult.PercentileDeletion); Assert.Equal(0, quantifierResult.FormulaPercentile); }
private static async Task Quantify( IEnumerable <Organization> organizations, string clonePath) { var repositories = organizations.Select(o => o.Projects.Select(p => p.Repositories.Select(r => new { Organization = o.Name, Project = p.Name, Repository = r.Name }))) .SelectMany(a => a) .SelectMany(a => a); var gitEngine = new GitEngine(); var quantifyClient = new QuantifyClient(string.Empty); foreach (var repository in repositories) { var saveResultsToDatabase = new Dictionary <string, QuantifierResult>(); var repoPath = Path.Combine(clonePath, repository.Repository); var commitsSha1 = gitEngine.GetAllCommits(repoPath).Select(c => c.Sha).ToArray(); Console.WriteLine($"Total commits to evaluate : {commitsSha1.Length}. Repo name {repository.Repository}."); foreach (var commitSha1 in commitsSha1) { try { var quantifierResult = await quantifyClient.Compute(repoPath, commitSha1); saveResultsToDatabase[commitSha1] = quantifierResult; } catch (Exception e) { Console.WriteLine(e); } } await SaveToCsv( saveResultsToDatabase, Path.Combine(clonePath, $"{repository.Repository}_QuantifierResults.csv")); } }
public async Task ToMarkdownCommentAsync_Options_CollapseChangesSummarySection( bool collapseChangesSummarySection) { // Arrange gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 2); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 4); gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 5); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 2); var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName, new MarkdownCommentOptions { CollapseChangesSummarySection = collapseChangesSummarySection }); // Assert Assert.True(!string.IsNullOrWhiteSpace(comment)); Assert.StartsWith("### Pull Request Quantified", comment); if (collapseChangesSummarySection) { Assert.True(comment.IndexOf( await File.ReadAllTextAsync(@"Data/AssertCommentSummaryCollapsed.txt"), StringComparison.Ordinal) > -1); } else { Assert.True(comment.IndexOf( await File.ReadAllTextAsync(@"Data/AssertCommentSummaryNotCollapsed.txt"), StringComparison.Ordinal) > -1); } }
public async Task ToMarkdownCommentAsync_Successful() { // Arrange var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName); // Assert Assert.True(!string.IsNullOrWhiteSpace(comment)); Assert.StartsWith("### ![](https://img.shields.io/static/v1?label=Quantified&message=Extra%20Small&color=green)", comment); }
public async Task ToMarkdownCommentAsync_Options_CollapseQuantificationDetailsSection(bool collapseQuantifiedDetailsSection) { // Arrange var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName, false, new MarkdownCommentOptions { CollapsePullRequestQuantifiedSection = collapseQuantifiedDetailsSection }); // Assert Assert.True(!string.IsNullOrWhiteSpace(comment)); Assert.StartsWith("### ![](https://img.shields.io/static/v1?label=Quantified&message=Extra%20Small&color=green)", comment); if (collapseQuantifiedDetailsSection) { Assert.True( comment.IndexOf( await File.ReadAllTextAsync(@"Data/AssertCommentSummaryCollapsed.txt"), StringComparison.Ordinal) > -1); } else { Assert.True( comment.IndexOf( await File.ReadAllTextAsync(@"Data/AssertCommentSummaryNotCollapsed.txt"), StringComparison.Ordinal) > -1); } }
public async Task ToMarkdownCommentAsync_IdealSizeCheck(int formulaLinesChanged, bool isIdeal) { // Arrange var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(string.Empty); var quantifierResult = await quantifyClient.Compute(quantifierInput); quantifierResult.FormulaLinesChanged = formulaLinesChanged; var comment = await quantifierResult.ToMarkdownCommentAsync( RepositoryLink, ContextFileLink, PullRequestLink, AuthorName); // Assert var idealJobIndex = comment.IndexOf("Great job", StringComparison.Ordinal); Assert.True((isIdeal && idealJobIndex > -1) || (!isIdeal && idealJobIndex == -1)); }
private static async Task Quantify( IEnumerable <Organization> organizations, string clonePath) { var repositories = organizations.Select( o => o.Projects.Select( p => p.Repositories.Select( r => new { Organization = o.Name, Project = p.Name, Repository = r.Name }))) .SelectMany(a => a) .SelectMany(a => a); var quantifyClient = new QuantifyClient(string.Empty); foreach (var repository in repositories) { var resultFile = Path.Combine(clonePath, $"{repository.Repository}_QuantifierResults.csv"); if (File.Exists(resultFile)) { File.Delete(resultFile); } await InitializeResultFile(resultFile); var repoPath = Path.Combine(clonePath, repository.Repository); await RunQuantifier( quantifyClient, resultFile, repoPath); } }
public async Task QuantifyClient_MissingFormulaPercentileContext() { // Arrange gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 2); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 4); gitRepoHelpers.CommitFilesToRepo(); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake.cs", 5); gitRepoHelpers.AddUntrackedFileToRepoWithNumLines("fake2.cs", 2); var quantifierInput = new QuantifierInput(); quantifierInput.Changes.AddRange(gitEngine.GetGitChanges(gitRepoHelpers.RepoPath)); var quantifyClient = new QuantifyClient(@"Data/MissingFormulaPercentileContext.prquantifier.yaml"); // Act var quantifierResult = await quantifyClient.Compute(quantifierInput); // Assert Assert.True(!string.IsNullOrEmpty(quantifierResult.Label)); Assert.Equal(3, quantifierResult.QuantifiedLinesAdded); Assert.Equal(2, quantifierResult.QuantifiedLinesDeleted); Assert.Equal(0, quantifierResult.PercentileAddition); Assert.Equal(0, quantifierResult.PercentileDeletion); Assert.Equal(0, quantifierResult.FormulaPercentile); }
private static async Task RunQuantifier( QuantifyClient quantifyClient, string resultFile, string repoPath) { var repoRoot = LibGit2Sharp.Repository.Discover(repoPath); if (repoRoot == null) { Console.WriteLine($"No repo found at {repoPath}"); return; } using var repo = new LibGit2Sharp.Repository(repoRoot); var commits = repo.Commits.QueryBy( new CommitFilter { FirstParentOnly = true }); Console.WriteLine($"Total commits to evaluate : {commits.Count()}. Repository path {repoPath}."); var sw = new Stopwatch(); sw.Reset(); sw.Start(); var batchSize = 100; var quantifierResults = new ConcurrentDictionary <string, QuantifierResult>(); for (int page = 0; page < (commits.Count() / batchSize) + 1; page++) { var commitBatch = commits.Skip(batchSize * page).Take(batchSize); var quantifyTasks = commitBatch.Select( async commit => { try { var quantifierInput = new QuantifierInput(); var firstParent = commit.Parents.FirstOrDefault(); if (firstParent != null) { var patch = repo.Diff.Compare <Patch>(firstParent.Tree, commit.Tree); foreach (var gitFilePatch in patch.GetGitFilePatch()) { quantifierInput.Changes.Add(gitFilePatch); } } var quantifierResult = await quantifyClient.Compute(quantifierInput); quantifierResults.TryAdd(commit.Sha, quantifierResult); } catch (Exception e) { Console.WriteLine(e); } }); await Task.WhenAll(quantifyTasks); await AddResultsToFile(quantifierResults, resultFile); quantifierResults = new ConcurrentDictionary <string, QuantifierResult>(); Console.WriteLine($"{page * batchSize}/{commits.Count()} {sw.Elapsed}"); } Console.WriteLine("Completed!"); }
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); }