Automatically gather Git information (#534)

* Automatically populate git repository information

Populates based on the repository information detected for the first source location argument.

* Report auto gathered git information in sarif report

* Include LibGit2Sharp dependency

* Update comment on CreateFresh

This internal method is used to create a refreshed metadata object after depends on removes invalidated records.

* Only create a fresh metadata object when needed
This commit is contained in:
Gabe Stocco 2023-03-08 15:52:43 -08:00 коммит произвёл GitHub
Родитель 44933030c4
Коммит f591a0acb7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 101 добавлений и 7 удалений

Просмотреть файл

@ -56,7 +56,7 @@ public record CLICustomRulesCommandOptions : CLICommandOptions
public bool RequireMustNotMatch { get; set; }
[Option('R', "non-backtracking-regex", Required = false,
HelpText = "Enables non-backtracking regex for all rules. A warning will be displayed for all regular expressions that require backtracking support. Default: Off.",
HelpText = "Prefer non-backtracking regex for all rules unless they require the backtracking engine. A warning will be displayed for all regular expressions that require backtracking support. Default: Off.",
Default = false),]
public bool EnableNonBacktrackingRegex { get; set; }
}
@ -166,10 +166,10 @@ public record CLIAnalyzeCmdOptions : CLIAnalysisSharedCommandOptions
HelpText = "If set, when outputting sarif, will have paths made relative to the provided path.")]
public string? BasePath { get; set; } = null;
[Option("repository-uri", Required = false, HelpText = "If set, when outputting sarif, include this information.")]
[Option("repository-uri", Required = false, HelpText = "If set, override any automatically detected RepositoryUri in Sarif report.")]
public string? RepositoryUri { get; set; } = null;
[Option("commit-hash", Required = false, HelpText = "If set, when outputting sarif, include this information.")]
[Option("commit-hash", Required = false, HelpText = "If set, override any automatically detected CommitHash in Sarif report.")]
public string? CommitHash { get; set; } = null;
}

Просмотреть файл

@ -74,6 +74,18 @@ public class AnalyzeSarifWriter : CommandResultsWriter
}
};
}
else if (analyzeResult.Metadata.RepositoryUri is { })
{
run.VersionControlProvenance = new List<VersionControlDetails>
{
new()
{
RepositoryUri = analyzeResult.Metadata.RepositoryUri,
RevisionId = analyzeResult.Metadata.CommitHash ?? string.Empty,
Branch = analyzeResult.Metadata.Branch ?? string.Empty
}
};
}
var artifacts = new List<Artifact>();
run.Tool = new Tool

Просмотреть файл

@ -54,6 +54,7 @@
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="DotLiquid" Version="2.2.677" />
<PackageReference Include="Glob" Version="1.1.9" />
<PackageReference Include="LibGit2Sharp" Version="0.26.2" />
<PackageReference Include="Microsoft.CST.OAT" Version="1.2.43" />
<PackageReference Include="Microsoft.CST.RecursiveExtractor" Version="1.2.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />

Просмотреть файл

@ -18,6 +18,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Text.Json.Serialization;
using ShellProgressBar;
using LibGit2Sharp;
namespace Microsoft.ApplicationInspector.Commands;
@ -148,6 +149,10 @@ public class AnalyzeOptions
/// </summary>
public bool RequireMustNotMatch { get; set; }
/// <summary>
/// If set, prefer to build rule Regex with the Non-BackTracking engine unless the modifiers contain `b`
/// Will fall back to BackTracking engine if the Rule cannot be built with Non-BackTracking.
/// </summary>
public bool EnableNonBacktrackingRegex { get; set; }
}
@ -389,6 +394,8 @@ public class AnalyzeCommand
RemoveDependsOnNotPresent();
}
_metaDataHelper.AddGitInformation(GenerateGitInformation(Path.GetFullPath(_options.SourcePath.FirstOrDefault())));
return AnalyzeResult.ExitCode.Success;
void ProcessAndAddToMetadata(FileEntry file)
@ -533,22 +540,58 @@ public class AnalyzeCommand
}
}
private GitInformation? GenerateGitInformation(string optsPath)
{
try
{
using var repo = new Repository(optsPath);
var info = new GitInformation()
{
Branch = repo.Head.FriendlyName
};
if (repo.Network.Remotes.Any())
{
info.RepositoryUri = new Uri(repo.Network.Remotes.First().Url);
}
if (repo.Head.Commits.Any())
{
info.CommitHash = repo.Head.Commits.First().Sha;
}
return info;
}
catch
{
if (Directory.GetParent(optsPath) is { } notNullParent)
{
return GenerateGitInformation(notNullParent.FullName);
}
}
return null;
}
/// <summary>
/// Remove matches from the metadata when the DependsOnTags are not satisfied.
/// </summary>
private void RemoveDependsOnNotPresent()
{
bool anyChanges = false;
List<MatchRecord> previousMatches = _metaDataHelper.Matches.ToList();
List<MatchRecord> nextMatches = FilterRecordsByMissingDependsOnTags(previousMatches);
// Continue iterating as long as records were removed in the last iteration, as their tags may have been depended on by another rule
while (nextMatches.Count != previousMatches.Count)
{
anyChanges = true;
(nextMatches, previousMatches) = (FilterRecordsByMissingDependsOnTags(nextMatches), nextMatches);
}
_metaDataHelper = _metaDataHelper.CreateFresh();
foreach (MatchRecord matchRecord in nextMatches)
if (anyChanges)
{
_metaDataHelper.AddMatchRecord(matchRecord);
_metaDataHelper = _metaDataHelper.CreateFresh();
foreach (MatchRecord matchRecord in nextMatches)
{
_metaDataHelper.AddMatchRecord(matchRecord);
}
}
}
@ -594,6 +637,8 @@ public class AnalyzeCommand
RemoveDependsOnNotPresent();
}
_metaDataHelper.AddGitInformation(GenerateGitInformation(Path.GetFullPath(_options.SourcePath.FirstOrDefault())));
return AnalyzeResult.ExitCode.Success;
async Task ProcessAndAddToMetadata(FileEntry file, CancellationToken cancellationToken)

Просмотреть файл

@ -0,0 +1,11 @@
namespace Microsoft.ApplicationInspector.Commands
{
using System;
public record GitInformation
{
public Uri? RepositoryUri { get; set; }
public string? CommitHash { get; set; }
public string? Branch { get; set; }
}
}

Просмотреть файл

@ -27,6 +27,24 @@ public class MetaData
[JsonPropertyName("applicationName")]
public string? ApplicationName { get; set; }
/// <summary>
/// Detected repository uri
/// </summary>
[JsonPropertyName("repositoryUri")]
public Uri? RepositoryUri { get; set; }
/// <summary>
/// Detected CommitHash
/// </summary>
[JsonPropertyName("commitHash")]
public string? CommitHash { get; set; }
/// <summary>
/// Detected Branch Name
/// </summary>
[JsonPropertyName("branch")]
public string? Branch { get; set; }
/// <summary>
/// Source path provided argument
/// </summary>

Просмотреть файл

@ -332,7 +332,7 @@ public class MetaDataHelper
}
/// <summary>
/// Returns a new MetaDataHelper with the same SourcePath, Files, Languages and FileExtensions
/// Returns a new MetaDataHelper with the same SourcePath, Files, Languages and FileExtensions but no Matches
/// </summary>
/// <returns></returns>
internal MetaDataHelper CreateFresh()
@ -344,4 +344,11 @@ public class MetaDataHelper
Languages = Languages
};
}
internal void AddGitInformation(GitInformation? information)
{
Metadata.RepositoryUri = information?.RepositoryUri;
Metadata.CommitHash = information?.CommitHash;
Metadata.Branch = information?.Branch;
}
}