Skip to content

Commit a1025df

Browse files
AMaini503Aayush Maini
and
Aayush Maini
authored
User/aamaini/2281511 (#1409)
* Use Go CLI scan instead of go.sum if available * Track project roots with successful CLI scan * Add unit test for new CLI logic * CR: Fix method name that filters go.sum * CR: Bump Go117 version --------- Co-authored-by: Aayush Maini <[email protected]>
1 parent f7af5db commit a1025df

File tree

4 files changed

+71
-17
lines changed

4 files changed

+71
-17
lines changed

src/Microsoft.ComponentDetection.Detectors/go/Go117ComponentDetector.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public Go117ComponentDetector(
4848

4949
public override IEnumerable<ComponentType> SupportedComponentTypes { get; } = [ComponentType.Go];
5050

51-
public override int Version => 1;
51+
public override int Version => 2;
5252

5353
protected override Task<IObservable<ProcessRequest>> OnPrepareDetectionAsync(
5454
IObservable<ProcessRequest> processRequests,
@@ -75,7 +75,7 @@ protected override Task<IObservable<ProcessRequest>> OnPrepareDetectionAsync(
7575
return true;
7676
}
7777

78-
return GoDetectorUtils.ShouldRemoveGoSumFromDetection(goSumFilePath: processRequest.ComponentStream.Location, goModFile, this.Logger);
78+
return GoDetectorUtils.ShouldIncludeGoSumFromDetection(goSumFilePath: processRequest.ComponentStream.Location, goModFile, this.Logger);
7979
}
8080
finally
8181
{
@@ -97,7 +97,11 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
9797
return;
9898
}
9999

100-
var record = new GoGraphTelemetryRecord();
100+
using var record = new GoGraphTelemetryRecord();
101+
var wasGoCliDisabled = this.IsGoCliManuallyDisabled();
102+
record.WasGoCliDisabled = wasGoCliDisabled;
103+
record.WasGoFallbackStrategyUsed = false;
104+
101105
var fileExtension = Path.GetExtension(file.Location).ToUpperInvariant();
102106
switch (fileExtension)
103107
{
@@ -123,7 +127,29 @@ await GoDependencyGraphUtility.GenerateAndPopulateDependencyGraphAsync(
123127
case ".SUM":
124128
{
125129
this.Logger.LogDebug("Found Go.sum: {Location}", file.Location);
126-
await this.goParserFactory.CreateParser(GoParserType.GoSum, this.Logger).ParseAsync(singleFileComponentRecorder, file, record);
130+
131+
// check if we can use Go CLI instead
132+
var wasGoCliScanSuccessful = false;
133+
if (!wasGoCliDisabled)
134+
{
135+
wasGoCliScanSuccessful = await this.goParserFactory.CreateParser(GoParserType.GoCLI, this.Logger).ParseAsync(singleFileComponentRecorder, file, record);
136+
}
137+
138+
this.Logger.LogDebug("Status of Go CLI scan when considering {GoSumLocation}: {Status}", file.Location, wasGoCliScanSuccessful);
139+
140+
// If Go CLI scan was not successful/disabled, scan go.sum because this go.sum was recorded due to go.mod
141+
// containing go < 1.17. So go.mod is incomplete. We need to parse go.sum to make list of dependencies complete
142+
if (!wasGoCliScanSuccessful)
143+
{
144+
record.WasGoFallbackStrategyUsed = true;
145+
this.Logger.LogDebug("Go CLI scan when considering {GoSumLocation} was not successful. Falling back to scanning go.sum", file.Location);
146+
await this.goParserFactory.CreateParser(GoParserType.GoSum, this.Logger).ParseAsync(singleFileComponentRecorder, file, record);
147+
}
148+
else
149+
{
150+
this.projectRoots.Add(projectRootDirectory.FullName);
151+
}
152+
127153
break;
128154
}
129155

src/Microsoft.ComponentDetection.Detectors/go/GoComponentDetector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected override Task<IObservable<ProcessRequest>> OnPrepareDetectionAsync(
9494
return true;
9595
}
9696

97-
return GoDetectorUtils.ShouldRemoveGoSumFromDetection(goSumFilePath: processRequest.ComponentStream.Location, goModFile, this.Logger);
97+
return GoDetectorUtils.ShouldIncludeGoSumFromDetection(goSumFilePath: processRequest.ComponentStream.Location, goModFile, this.Logger);
9898
}
9999
finally
100100
{

src/Microsoft.ComponentDetection.Detectors/go/Utils/GoDetectorUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public static class GoDetectorUtils
1515
/// <param name="adjacentGoModFile">Component stream representing the adjacent go.mod file.</param>
1616
/// <param name="logger">The logger to use for logging messages.</param>
1717
/// <returns>True if the adjacent go.mod file is present and has a go version >= 1.17.</returns>
18-
public static bool ShouldRemoveGoSumFromDetection(string goSumFilePath, ComponentStream adjacentGoModFile, ILogger logger)
18+
public static bool ShouldIncludeGoSumFromDetection(string goSumFilePath, ComponentStream adjacentGoModFile, ILogger logger)
1919
{
2020
using var reader = new StreamReader(adjacentGoModFile.Stream);
2121
var goModFileContents = reader.ReadToEnd();

test/Microsoft.ComponentDetection.Detectors.Tests/Go117ComponentDetectorTests.cs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,29 +139,57 @@ public async Task Go117ModDetector_GoModFileFound_GoModParserIsExecuted()
139139
goModParserMock.Verify(parser => parser.ParseAsync(It.IsAny<ISingleFileComponentRecorder>(), It.IsAny<IComponentStream>(), It.IsAny<GoGraphTelemetryRecord>()), Times.Once);
140140
}
141141

142-
[TestMethod]
143-
public async Task Go117ModDetector_GoSumFileFound_GoSumParserIsExecuted()
142+
/// <summary>
143+
/// Verifies that if Go CLI is enabled/available and succeeds, go.sum file is not parsed and vice-versa.
144+
/// </summary>
145+
/// <returns>Task.</returns>
146+
[DataTestMethod]
147+
[DataRow(true)]
148+
[DataRow(false)]
149+
public async Task Go117Detector_GoSum_GoSumParserExecuted(bool goCliSucceeds)
144150
{
151+
var nInvocationsOfSumParser = goCliSucceeds ? 0 : 1;
145152
var goSumParserMock = new Mock<IGoParser>();
153+
var goCliParserMock = new Mock<IGoParser>();
146154
this.mockParserFactory.Setup(x => x.CreateParser(GoParserType.GoSum, It.IsAny<ILogger>())).Returns(goSumParserMock.Object);
155+
this.mockParserFactory.Setup(x => x.CreateParser(GoParserType.GoCLI, It.IsAny<ILogger>())).Returns(goCliParserMock.Object);
147156

148-
this.commandLineMock.Setup(x => x.CanCommandBeLocatedAsync("go", null, null, It.Is<string[]>(p => p.SequenceEqual(new List<string> { "version" }.ToArray()))))
149-
.ReturnsAsync(true);
157+
// Setup go cli parser to succeed/fail
158+
goCliParserMock.Setup(p => p.ParseAsync(It.IsAny<ISingleFileComponentRecorder>(), It.IsAny<IComponentStream>(), It.IsAny<GoGraphTelemetryRecord>())).ReturnsAsync(goCliSucceeds);
150159

151-
this.commandLineMock.Setup(x => x.ExecuteCommandAsync("go", null, null, default, It.Is<string[]>(p => p.SequenceEqual(new List<string> { "version" }.ToArray()))))
152-
.ReturnsAsync(new CommandLineExecutionResult
153-
{
154-
ExitCode = 0,
155-
StdOut = "go version go1.10.6 windows/amd64",
156-
});
160+
// Setup go sum parser to succeed
161+
goSumParserMock.Setup(p => p.ParseAsync(It.IsAny<ISingleFileComponentRecorder>(), It.IsAny<IComponentStream>(), It.IsAny<GoGraphTelemetryRecord>())).ReturnsAsync(true);
157162

158163
var (scanResult, componentRecorder) = await this.DetectorTestUtility
159164
.WithFile("go.sum", string.Empty)
160165
.ExecuteDetectorAsync();
161166

162167
scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
168+
this.mockParserFactory.Verify(clm => clm.CreateParser(GoParserType.GoSum, It.IsAny<ILogger>()), nInvocationsOfSumParser == 0 ? Times.Never : Times.Once);
169+
}
170+
171+
/// <summary>
172+
/// Verifies that if Go CLI is disabled, go.sum is parsed.
173+
/// </summary>
174+
/// <returns>Task.</returns>
175+
[TestMethod]
176+
public async Task Go117Detector_GoSum_GoSumParserExecutedIfCliDisabled()
177+
{
178+
var goSumParserMock = new Mock<IGoParser>();
179+
this.mockParserFactory.Setup(x => x.CreateParser(GoParserType.GoSum, It.IsAny<ILogger>())).Returns(goSumParserMock.Object);
180+
181+
// Setup environment variable to disable CLI scan
182+
this.envVarService.Setup(s => s.IsEnvironmentVariableValueTrue("DisableGoCliScan")).Returns(true);
183+
184+
// Setup go sum parser to succed
185+
goSumParserMock.Setup(p => p.ParseAsync(It.IsAny<ISingleFileComponentRecorder>(), It.IsAny<IComponentStream>(), It.IsAny<GoGraphTelemetryRecord>())).ReturnsAsync(true);
163186

164-
goSumParserMock.Verify(parser => parser.ParseAsync(It.IsAny<ISingleFileComponentRecorder>(), It.IsAny<IComponentStream>(), It.IsAny<GoGraphTelemetryRecord>()), Times.Once);
187+
var (scanResult, componentRecorder) = await this.DetectorTestUtility
188+
.WithFile("go.sum", string.Empty)
189+
.ExecuteDetectorAsync();
190+
191+
scanResult.ResultCode.Should().Be(ProcessingResultCode.Success);
192+
this.mockParserFactory.Verify(clm => clm.CreateParser(GoParserType.GoSum, It.IsAny<ILogger>()), Times.Once);
165193
}
166194

167195
[TestMethod]

0 commit comments

Comments
 (0)