Skip to content

Commit 5a86c1c

Browse files
authored
Merge branch 'main' into dependabot/github_actions/actions/checkout-4.2.1
2 parents 772caa1 + 319c39f commit 5a86c1c

File tree

8 files changed

+594
-1606
lines changed

8 files changed

+594
-1606
lines changed

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<PackageVersion Include="System.Memory" Version="4.5.5" />
4747
<PackageVersion Include="System.Reactive" Version="6.0.1" />
4848
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0" />
49-
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
49+
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
5050
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="8.0.0" />
5151
<PackageVersion Include="Tomlyn.Signed" Version="0.17.0" />
5252
<PackageVersion Include="yamldotnet" Version="15.1.6" />
@@ -55,4 +55,4 @@
5555
<!-- Fix security alerts -->
5656
<PackageVersion Include="System.Formats.Asn1" Version="6.0.1" />
5757
</ItemGroup>
58-
</Project>
58+
</Project>

src/Microsoft.ComponentDetection.Common/Telemetry/Records/GoGraphTelemetryRecord.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ public class GoGraphTelemetryRecord : BaseDetectionTelemetryRecord
1919
public string GoCliCommandError { get; set; }
2020

2121
public string GoModVersion { get; set; }
22+
23+
public string ExceptionMessage { get; set; }
2224
}

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

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ namespace Microsoft.ComponentDetection.Detectors.Go;
1919

2020
public class GoComponentDetector : FileComponentDetector
2121
{
22+
private const string StartString = "require ";
23+
2224
private static readonly Regex GoSumRegex = new(
2325
@"(?<name>.*)\s+(?<version>.*?)(/go\.mod)?\s+(?<hash>.*)",
2426
RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);
@@ -27,19 +29,22 @@ public class GoComponentDetector : FileComponentDetector
2729

2830
private readonly ICommandLineInvocationService commandLineInvocationService;
2931
private readonly IEnvironmentVariableService envVarService;
32+
private readonly IFileUtilityService fileUtilityService;
3033

3134
public GoComponentDetector(
3235
IComponentStreamEnumerableFactory componentStreamEnumerableFactory,
3336
IObservableDirectoryWalkerFactory walkerFactory,
3437
ICommandLineInvocationService commandLineInvocationService,
3538
IEnvironmentVariableService envVarService,
36-
ILogger<GoComponentDetector> logger)
39+
ILogger<GoComponentDetector> logger,
40+
IFileUtilityService fileUtilityService)
3741
{
3842
this.ComponentStreamEnumerableFactory = componentStreamEnumerableFactory;
3943
this.Scanner = walkerFactory;
4044
this.commandLineInvocationService = commandLineInvocationService;
4145
this.envVarService = envVarService;
4246
this.Logger = logger;
47+
this.fileUtilityService = fileUtilityService;
4348
}
4449

4550
public override string Id => "Go";
@@ -50,7 +55,7 @@ public GoComponentDetector(
5055

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

53-
public override int Version => 7;
58+
public override int Version => 8;
5459

5560
protected override Task<IObservable<ProcessRequest>> OnPrepareDetectionAsync(
5661
IObservable<ProcessRequest> processRequests,
@@ -180,6 +185,7 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
180185
catch (Exception ex)
181186
{
182187
this.Logger.LogError(ex, "Failed to detect components using go cli. Location: {Location}", file.Location);
188+
record.ExceptionMessage = ex.Message;
183189
}
184190
finally
185191
{
@@ -246,7 +252,7 @@ private async Task<bool> UseGoCliToScanAsync(string location, ISingleFileCompone
246252
return false;
247253
}
248254

249-
this.RecordBuildDependencies(goDependenciesProcess.StdOut, singleFileComponentRecorder);
255+
this.RecordBuildDependencies(goDependenciesProcess.StdOut, singleFileComponentRecorder, projectRootDirectory.FullName);
250256

251257
var generateGraphProcess = await this.commandLineInvocationService.ExecuteCommandAsync("go", null, workingDirectory: projectRootDirectory, new List<string> { "mod", "graph" }.ToArray());
252258
if (generateGraphProcess.ExitCode == 0)
@@ -299,9 +305,9 @@ private async Task ParseGoModFileAsync(
299305

300306
// In go >= 1.17, direct dependencies are listed as "require x/y v1.2.3", and transitive dependencies
301307
// are listed in the require () section
302-
if (line.StartsWith("require "))
308+
if (line.StartsWith(StartString))
303309
{
304-
this.TryRegisterDependencyFromModLine(line[8..], singleFileComponentRecorder);
310+
this.TryRegisterDependencyFromModLine(line[StartString.Length..], singleFileComponentRecorder);
305311
}
306312

307313
line = await reader.ReadLineAsync();
@@ -421,14 +427,16 @@ private bool IsModuleInBuildList(ISingleFileComponentRecorder singleFileComponen
421427
return singleFileComponentRecorder.GetComponent(component.Id) != null;
422428
}
423429

424-
private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRecorder singleFileComponentRecorder)
430+
private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRecorder singleFileComponentRecorder, string projectRootDirectoryFullName)
425431
{
426432
var goBuildModules = new List<GoBuildModule>();
427433
var reader = new JsonTextReader(new StringReader(goListOutput))
428434
{
429435
SupportMultipleContent = true,
430436
};
431437

438+
using var record = new GoReplaceTelemetryRecord();
439+
432440
while (reader.Read())
433441
{
434442
var serializer = new JsonSerializer();
@@ -439,13 +447,45 @@ private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRe
439447

440448
foreach (var dependency in goBuildModules)
441449
{
450+
var dependencyName = $"{dependency.Path} {dependency.Version}";
451+
442452
if (dependency.Main)
443453
{
444454
// main is the entry point module (superfluous as we already have the file location)
445455
continue;
446456
}
447457

448-
var goComponent = new GoComponent(dependency.Path, dependency.Version);
458+
if (dependency.Replace?.Path != null && dependency.Replace.Version == null)
459+
{
460+
var dirName = projectRootDirectoryFullName;
461+
var combinedPath = Path.Combine(dirName, dependency.Replace.Path, "go.mod");
462+
var goModFilePath = Path.GetFullPath(combinedPath);
463+
if (this.fileUtilityService.Exists(goModFilePath))
464+
{
465+
this.Logger.LogInformation("go Module {GoModule} is being replaced with module at path {GoModFilePath}", dependencyName, goModFilePath);
466+
record.GoModPathAndVersion = dependencyName;
467+
record.GoModReplacement = goModFilePath;
468+
continue;
469+
}
470+
471+
this.Logger.LogWarning("go.mod file {GoModFilePath} does not exist in the relative path given for replacement", goModFilePath);
472+
record.GoModPathAndVersion = goModFilePath;
473+
record.GoModReplacement = null;
474+
}
475+
476+
GoComponent goComponent;
477+
if (dependency.Replace?.Path != null && dependency.Replace.Version != null)
478+
{
479+
var dependencyReplacementName = $"{dependency.Replace.Path} {dependency.Replace.Version}";
480+
goComponent = new GoComponent(dependency.Replace.Path, dependency.Replace.Version);
481+
this.Logger.LogInformation("go Module {GoModule} being replaced with module {GoModuleReplacement}", dependencyName, dependencyReplacementName);
482+
record.GoModPathAndVersion = dependencyName;
483+
record.GoModReplacement = dependencyReplacementName;
484+
}
485+
else
486+
{
487+
goComponent = new GoComponent(dependency.Path, dependency.Version);
488+
}
449489

450490
if (dependency.Indirect)
451491
{
@@ -485,5 +525,7 @@ private class GoBuildModule
485525
public string Version { get; set; }
486526

487527
public bool Indirect { get; set; }
528+
529+
public GoBuildModule Replace { get; set; }
488530
}
489531
}

0 commit comments

Comments
 (0)