* Wrap up opt-in behavior

* Verify needs to be called after

* 🎨

* 🎨

* Fix service creation

* 🛠️

* 🐛 fix
This commit is contained in:
Teo Voinea 2021-12-17 09:19:02 -08:00 коммит произвёл GitHub
Родитель 11935c1cc3
Коммит 70c149cd3c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 123 добавлений и 27 удалений

2
.vscode/launch.json поставляемый
Просмотреть файл

@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/Microsoft.ComponentDetection/bin/Debug/net6.0/Microsoft.ComponentDetection.dll",
"program": "${workspaceFolder}/src/Microsoft.ComponentDetection/bin/Debug/netcoreapp3.1/Microsoft.ComponentDetection.dll",
"args": ["scan", "--Debug", "--Verbosity", "Verbose", "--Output", "${workspaceFolder}/scan-output", "--SourceDirectory", "${workspaceFolder}"],
"cwd": "${workspaceFolder}/src/Microsoft.ComponentDetection",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console

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

@ -26,5 +26,8 @@ namespace Microsoft.ComponentDetection.Common
[Import]
public IDockerService DockerService { get; set; }
[Import]
public IEnvironmentVariableService EnvironmentVariableService { get; set; }
}
}

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

@ -0,0 +1,16 @@
using System;
using System.Composition;
using Microsoft.ComponentDetection.Contracts;
namespace Microsoft.ComponentDetection.Common
{
[Export(typeof(IEnvironmentVariableService))]
public class EnvironmentVariableService : IEnvironmentVariableService
{
public bool DoesEnvironmentVariableExist(string name)
{
var enabledVar = Environment.GetEnvironmentVariable(name);
return !string.IsNullOrEmpty(enabledVar);
}
}
}

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

@ -15,5 +15,7 @@
IObservableDirectoryWalkerFactory DirectoryWalkerFactory { get; set; }
IDockerService DockerService { get; set; }
IEnvironmentVariableService EnvironmentVariableService { get; set; }
}
}

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

@ -0,0 +1,7 @@
namespace Microsoft.ComponentDetection.Contracts
{
public interface IEnvironmentVariableService
{
bool DoesEnvironmentVariableExist(string name);
}
}

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

@ -25,6 +25,7 @@ namespace Microsoft.ComponentDetection.Contracts.Internal
fileUtilityServiceStatic = detectorDependencies.FileUtilityService;
observableDirectoryWalkerFactoryServiceStatic = detectorDependencies.DirectoryWalkerFactory;
dockerServiceStatic = detectorDependencies.DockerService;
environmentVariableServiceStatic = detectorDependencies.EnvironmentVariableService;
}
private static ILogger loggerStatic;
@ -35,6 +36,8 @@ namespace Microsoft.ComponentDetection.Contracts.Internal
private static IObservableDirectoryWalkerFactory observableDirectoryWalkerFactoryServiceStatic;
private static IDockerService dockerServiceStatic;
private static IEnvironmentVariableService environmentVariableServiceStatic;
[Export(typeof(ILogger))]
public ILogger Logger => loggerStatic;
@ -55,5 +58,8 @@ namespace Microsoft.ComponentDetection.Contracts.Internal
[Export(typeof(IDockerService))]
public IDockerService DockerService => dockerServiceStatic;
[Export(typeof(IEnvironmentVariableService))]
public IEnvironmentVariableService EnvironmentVariableService => environmentVariableServiceStatic;
}
}

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

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.ComponentDetection.Common;
using Microsoft.ComponentDetection.Common.Telemetry.Records;
using Microsoft.ComponentDetection.Contracts;
using Microsoft.ComponentDetection.Contracts.Internal;
@ -18,6 +19,9 @@ namespace Microsoft.ComponentDetection.Detectors.Go
[Import]
public ICommandLineInvocationService CommandLineInvocationService { get; set; }
[Import]
public IEnvironmentVariableService EnvVarService { get; set; }
private static readonly Regex GoSumRegex = new Regex(
@"(?<name>.*)\s+(?<version>.*?)(/go\.mod)?\s+(?<hash>.*)",
RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
@ -34,35 +38,62 @@ namespace Microsoft.ComponentDetection.Detectors.Go
private HashSet<string> projectRoots = new HashSet<string>();
protected override Task OnFileFound(ProcessRequest processRequest, IDictionary<string, string> detectorArgs)
protected override async Task OnFileFound(ProcessRequest processRequest, IDictionary<string, string> detectorArgs)
{
var singleFileComponentRecorder = processRequest.SingleFileComponentRecorder;
var file = processRequest.ComponentStream;
var fileExtension = Path.GetExtension(file.Location).ToLowerInvariant();
switch (fileExtension)
{
case ".mod":
{
Logger.LogVerbose("Found Go.mod: " + file.Location);
ParseGoModFile(singleFileComponentRecorder, file);
break;
}
case ".sum":
{
Logger.LogVerbose("Found Go.sum: " + file.Location);
ParseGoSumFile(singleFileComponentRecorder, file);
break;
}
default:
{
throw new Exception("Unexpected file type detected in go detector");
}
}
return Task.CompletedTask;
var projectRootDirectory = Directory.GetParent(file.Location);
if (projectRoots.Any(path => projectRootDirectory.FullName.StartsWith(path)))
{
return;
}
var wasGoCliScanSuccessful = false;
try
{
if (IsGoCliManuallyEnabled())
{
Logger.LogInfo("Go cli scan was manually enabled");
wasGoCliScanSuccessful = await UseGoCliToScan(file.Location, singleFileComponentRecorder);
}
}
catch
{
Logger.LogInfo("Failed to detect components using go cli.");
}
finally
{
if (wasGoCliScanSuccessful)
{
projectRoots.Add(projectRootDirectory.FullName);
}
else
{
var fileExtension = Path.GetExtension(file.Location).ToLowerInvariant();
switch (fileExtension)
{
case ".mod":
{
Logger.LogVerbose("Found Go.mod: " + file.Location);
ParseGoModFile(singleFileComponentRecorder, file);
break;
}
case ".sum":
{
Logger.LogVerbose("Found Go.sum: " + file.Location);
ParseGoSumFile(singleFileComponentRecorder, file);
break;
}
default:
{
throw new Exception("Unexpected file type detected in go detector");
}
}
}
}
}
private async Task<bool> UseGoCliToScan(string location, ISingleFileComponentRecorder singleFileComponentRecorder)
@ -223,5 +254,10 @@ namespace Microsoft.ComponentDetection.Detectors.Go
goComponent = new GoComponent(componentParts[0], componentParts[1]);
return true;
}
private bool IsGoCliManuallyEnabled()
{
return EnvVarService.DoesEnvironmentVariableExist("EnableGoCliScan");
}
}
}

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

@ -11,6 +11,7 @@ using Microsoft.ComponentDetection.Detectors.Go;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Microsoft.ComponentDetection.TestsUtilities;
using Microsoft.ComponentDetection.Common;
namespace Microsoft.ComponentDetection.Detectors.Tests
{
@ -21,18 +22,25 @@ namespace Microsoft.ComponentDetection.Detectors.Tests
{
private DetectorTestUtility<GoComponentDetector> detectorTestUtility;
private Mock<ICommandLineInvocationService> commandLineMock;
private Mock<IEnvironmentVariableService> envVarService;
private ScanRequest scanRequest;
[TestInitialize]
public void TestInitialize()
{
commandLineMock = new Mock<ICommandLineInvocationService>();
envVarService = new Mock<IEnvironmentVariableService>();
var loggerMock = new Mock<ILogger>();
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(false);
var detector = new GoComponentDetector
{
CommandLineInvocationService = commandLineMock.Object,
Logger = loggerMock.Object,
EnvVarService = envVarService.Object,
};
var tempPath = Path.GetTempPath();
@ -254,6 +262,8 @@ replace (
commandLineMock.Setup(x => x.CanCommandBeLocated("go", null, It.IsAny<DirectoryInfo>(), It.IsAny<string[]>()))
.ReturnsAsync(false);
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(true);
await TestGoSumDetectorWithValidFile_ReturnsSuccessfully();
}
@ -263,6 +273,8 @@ replace (
commandLineMock.Setup(x => x.CanCommandBeLocated("go", null, It.IsAny<DirectoryInfo>(), It.IsAny<string[]>()))
.ReturnsAsync(() => throw new Exception("Some horrible error occured"));
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(true);
await TestGoSumDetectorWithValidFile_ReturnsSuccessfully();
}
@ -278,6 +290,8 @@ replace (
ExitCode = 1,
});
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(true);
await TestGoSumDetectorWithValidFile_ReturnsSuccessfully();
}
@ -290,6 +304,8 @@ replace (
commandLineMock.Setup(x => x.ExecuteCommand("go mod graph", null, It.IsAny<DirectoryInfo>(), It.IsAny<string>()))
.ReturnsAsync(() => throw new Exception("Some horrible error occured"));
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(true);
await TestGoSumDetectorWithValidFile_ReturnsSuccessfully();
}
@ -308,6 +324,8 @@ replace (
StdOut = goGraph,
});
envVarService.Setup(x => x.DoesEnvironmentVariableExist("EnableGoCliScan")).Returns(true);
var (scanResult, componentRecorder) = await detectorTestUtility
.WithFile("go.mod", string.Empty)
.ExecuteDetector();
@ -315,7 +333,15 @@ replace (
Assert.AreEqual(ProcessingResultCode.Success, scanResult.ResultCode);
var detectedComponents = componentRecorder.GetDetectedComponents();
Assert.AreEqual(0, detectedComponents.Count());
Assert.AreEqual(4, detectedComponents.Count());
}
[TestMethod]
public async Task TestGoDetector_GoCliRequiresEnvVarToRun()
{
await TestGoSumDetectorWithValidFile_ReturnsSuccessfully();
commandLineMock.Verify(x => x.CanCommandBeLocated("go", null, It.IsAny<DirectoryInfo>(), It.IsAny<string[]>()), Times.Never);
}
}
}