Skip to content

Commit e0fa8cd

Browse files
author
Aayush Maini
committed
Merge remote-tracking branch 'origin/main' into user/aamaini/dependency-graph-identity-reconciliation
2 parents 476f113 + 87ae1f8 commit e0fa8cd

29 files changed

Lines changed: 5933 additions & 544 deletions

.github/workflows/build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ jobs:
4343
- name: Run tests
4444
# The '--' separator forwards options to the Microsoft Testing Platform runner.
4545
# After upgrading to .NET 10 SDK, these can be passed directly without '--'.
46-
run: dotnet test --no-build --configuration Debug -- --coverage --coverage-output-format cobertura
46+
# Disable the default Integration-test exclusion from test/Directory.Build.props.
47+
run: dotnet test --no-build --configuration Debug -p:ExcludeIntegrationTests=false -p:TestingPlatformCommandLineArguments="--coverage --coverage-output-format cobertura"
4748

4849
- name: Upload coverage reports to Codecov
4950
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2

CONTRIBUTING.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ Analysis rulesets are defined in [analyzers.ruleset](analyzers.ruleset) and vali
6161

6262
### Testing
6363

64-
L0s are defined in `Microsoft.ComponentDetection.*.Tests`.
64+
**Unit tests (L0s)** are defined in `Microsoft.ComponentDetection.*.Tests` and should be fast, isolated, and free of external process calls.
6565

66-
Verification tests are run on the sample projects defined in [microsoft/componentdetection-verification](https://github.com/microsoft/componentdetection-verification).
66+
**Integration tests** spawn real processes (e.g. `dotnet build`, `dotnet restore`) and are therefore slower and environment-dependent. Tag these with `[TestCategory("Integration")]` so they can be filtered during local development.
67+
68+
By default, `dotnet test` **excludes** Integration tests (configured in `test/Directory.Build.props`). CI runs all tests including Integration (see `.github/workflows/build.yml`).
69+
70+
To run only Integration tests locally:
71+
```bash
72+
dotnet test -- --filter "TestCategory=Integration"
73+
```
74+
75+
To run everything (same as CI):
76+
```bash
77+
dotnet test -p:ExcludeIntegrationTests=false
78+
```
79+
80+
**Verification tests** are run on the sample projects defined in [microsoft/componentdetection-verification](https://github.com/microsoft/componentdetection-verification).

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
1717
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
1818
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
19+
<PackageVersion Include="MSBuild.StructuredLogger" Version="2.3.113" />
1920
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" />
2021
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="8.0.0" />
2122
<PackageVersion Include="MinVer" Version="7.0.0" />

docs/detectors/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@
7070

7171
- [NuGet](nuget.md)
7272

73-
| Detector | Status |
74-
| ------------------------------------------------ | ------ |
75-
| NuGetComponentDetector | Stable |
76-
| NuGetPackagesConfigDetector | Stable |
77-
| NuGetProjectModelProjectCentricComponentDetector | Stable |
73+
| Detector | Status |
74+
| ------------------------------------------------ | ---------- |
75+
| NuGetComponentDetector | Stable |
76+
| NuGetPackagesConfigDetector | Stable |
77+
| NuGetProjectModelProjectCentricComponentDetector | Stable |
78+
| MSBuildBinaryLogComponentDetector | DefaultOff |
7879

7980
- [Pip](pip.md)
8081

docs/detectors/nuget.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,49 @@ The `NuGetPackagesConfig` detector raises NuGet components referenced by project
3636

3737
[7]: https://learn.microsoft.com/en-us/nuget/reference/packages-config
3838

39+
## MSBuildBinaryLog
40+
41+
The `MSBuildBinaryLog` detector is a **DefaultOff** detector intended to eventually replace both the `NuGetProjectCentric` and `DotNet` detectors. It combines MSBuild binary log (binlog) information with `project.assets.json` to provide enhanced component detection with project-level classifications.
42+
43+
It looks for `project.assets.json` files and separately discovers `*.binlog` files. The binlog provides build-time context that isn't available from `project.assets.json` alone.
44+
45+
### MSBuild Properties
46+
47+
The detector extracts the following MSBuild properties from binlog data:
48+
49+
| Property | Usage |
50+
| --- | --- |
51+
| `NETCoreSdkVersion` | Registered as the SDK version for the DotNet component. More accurate than `dotnet --version`, which can differ due to `global.json` rollforward. |
52+
| `OutputType` | Classifies projects as "application" (`Exe`, `WinExe`, `AppContainerExe`) or "library" (`Library`, `Module`). The `DotNet` detector uses PE header inspection, which requires compiled output. |
53+
| `ProjectAssetsFile` | Maps binlog project info to the corresponding `project.assets.json` on disk. |
54+
| `TargetFramework` / `TargetFrameworks` | Identifies inner builds for multi-targeted projects and determines per-TFM properties. |
55+
| `IsTestProject` | When `true`, all dependencies of the project are marked as development dependencies. |
56+
| `IsShipping` | When `false`, all dependencies are marked as development dependencies. |
57+
| `IsDevelopment` | When `true`, all dependencies are marked as development dependencies. |
58+
| `IsPackable` | Indicates whether the project produces a NuGet package. |
59+
| `SelfContained` | Detects self-contained deployment. Combined with lock file heuristics. |
60+
| `PublishAot` | When `true`, project is treated as self-contained. Typically only set during publish pass. |
61+
62+
### PackageReference and PackageDownload Metadata
63+
64+
The detector reads `IsDevelopmentDependency` metadata from `PackageReference` and `PackageDownload` items in the binlog:
65+
66+
- **PackageReference**: When `IsDevelopmentDependency` is `true`, the package and **all of its transitive dependencies** are marked as development dependencies. This allows annotating a single top-level dependency to classify its entire closure as dev-only. If a transitive dependency should remain non-dev, reference it directly (or transitively via a non-overridden dependency) so that it is also registered through a non-dev path.
67+
- **PackageReference**: When `IsDevelopmentDependency` is `false`, the package and all of its transitive dependencies are classified using the explicit override rather than the default heuristics.
68+
- **PackageDownload**: Packages are registered as development dependencies by default unless explicitly overridden via `IsDevelopmentDependency` metadata.
69+
70+
### Multi-Targeting and Multi-Pass Merging
71+
72+
For multi-targeted projects, the detector understands the MSBuild outer/inner build structure. Properties from inner builds (per-TFM) are tracked separately, and when a project appears in multiple binlogs (e.g., a build pass and a publish pass), their properties are merged so that values like `PublishAot` (typically only set during publish) are available when processing the shared `project.assets.json`.
73+
74+
### Fallback Mode
75+
76+
When no binlog is available for a project, the detector falls back to standard NuGet detection behavior (equivalent to the `NuGetProjectCentric` detector).
77+
78+
### Enabling the Detector
79+
80+
Pass `--DetectorArgs MSBuildBinaryLog=EnableIfDefaultOff` and ensure a `*.binlog` file is present in the scan directory (e.g., by building with `dotnet build -bl`).
81+
3982
## Known Limitations
4083

4184
- Any components that are only found in `*.nuspec` or `*.nupkg` files will not be detected with the latest NuGet Detector approach, because the NuGet detector that scans `*.nuspec` or `*.nupkg` files overreports. This is due to of NuGet's [restore behaviour][8] which downloads all possible dependencies before [resolving the final dependency graph][9].

docs/detectors/spdx.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ The detector:
1919
- Document name
2020
- SPDX version
2121
- Root element ID from `documentDescribes` (defaults to `SPDXRef-Document` if not specified)
22+
- Creator tool from `creationInfo.creators` (e.g., `Tool: microsoft/sbom-tool-2.2.0`)
23+
- Creator organization from `creationInfo.creators` (e.g., `Organization: Microsoft`)
2224
- Creates an `SpdxComponent` to represent the SPDX document
2325

2426
The detector does not parse or register individual packages listed within the SPDX document; it only registers the SPDX document itself as a component.

docs/feature-overview.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
| NPM | <ul><li>package.json</li><li>package-lock.json</li><li>npm-shrinkwrap.json</li><li>lerna.json</li></ul> | - | ✔ (dev-dependencies in package.json, dev flag in package-lock.json) ||
1212
| Yarn (v1, v2) | <ul><li>package.json</li><li>yarn.lock</li></ul> | - | ✔ (dev-dependencies in package.json) ||
1313
| Pnpm | <ul><li>shrinkwrap.yaml</li><li>pnpm-lock.yaml</li></ul> | - | ✔ (packages/{package}/dev flag) ||
14-
| NuGet | <ul><li>project.assets.json</li><li>*.nupkg</li><li>*.nuspec</li><li>packages.config</li><li>nuget.config</li></ul> | - | - | ✔ (required project.assets.json) |
14+
| NuGet | <ul><li>project.assets.json</li><li>*.nupkg</li><li>*.nuspec</li><li>packages.config</li><li>nuget.config</li><li>*.binlog (DefaultOff)</li></ul> | - | - | ✔ (required project.assets.json) |
1515
| Pip (Python) | <ul><li>setup.py</li><li>requirements.txt</li><li>*setup=distutils.core.run_setup({setup.py}); setup.install_requires*</li><li>dist package METADATA file</li></ul> | <ul><li>Python 2 or Python 3</li><li>Internet connection</li></ul> |||
1616
| Poetry (Python) | <ul><li>poetry.lock</li><ul> | - |||
1717
| Ruby | <ul><li>gemfile.lock</li></ul> | - |||

src/Microsoft.ComponentDetection.Contracts/TypedComponent/SpdxComponent.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,15 @@ public SpdxComponent(string spdxVersion, Uri documentNamespace, string name, str
4242
[JsonPropertyName("path")]
4343
public string Path { get; set; }
4444

45+
#nullable enable
46+
[JsonPropertyName("creatorTool")]
47+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
48+
public string? CreatorTool { get; set; }
49+
50+
[JsonPropertyName("creatorOrganization")]
51+
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
52+
public string? CreatorOrganization { get; set; }
53+
#nullable disable
54+
4555
protected override string ComputeBaseId() => $"{this.Name}-{this.SpdxVersion}-{this.Checksum}";
4656
}

src/Microsoft.ComponentDetection.Detectors/Microsoft.ComponentDetection.Detectors.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
<InternalsVisibleTo Include="Microsoft.ComponentDetection.Orchestrator.Tests" />
66
<InternalsVisibleTo Include="Microsoft.ComponentDetection.Detectors.Tests" />
77
<InternalsVisibleTo Include="Microsoft.ComponentDetection.TestsUtilities" />
8+
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
89
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" Key="0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" />
910
</ItemGroup>
1011

1112
<ItemGroup>
13+
<PackageReference Include="MSBuild.StructuredLogger" />
1214
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" />
1315
<PackageReference Include="Microsoft.Extensions.Logging" />
1416
<PackageReference Include="morelinq" />

0 commit comments

Comments
 (0)