Skip to content

Commit 89f3429

Browse files
authored
Merge pull request #2 from dborgards/claude/cyclonedx-nuget-package-01EkX7VTfBKakXEbsnQoSXCb
feat: Implement CycloneDX.MSBuild NuGet package with corrected parameters
2 parents 1c42279 + ac5f6ca commit 89f3429

File tree

8 files changed

+94
-71
lines changed

8 files changed

+94
-71
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ Documentation locations:
122122

123123
## License
124124

125-
By contributing, you agree that your contributions will be licensed under the Apache License 2.0.
125+
By contributing, you agree that your contributions will be licensed under the MIT License.

README.md

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CycloneDX.MSBuild
22

3-
[![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](LICENSE)
3+
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
44
[![NuGet](https://img.shields.io/nuget/v/CycloneDX.MSBuild.svg)](https://www.nuget.org/packages/CycloneDX.MSBuild/)
55

66
MSBuild targets for automatic **CycloneDX SBOM** (Software Bill of Materials) generation during build and pack operations. Seamlessly integrates the [CycloneDX .NET tool](https://github.com/CycloneDX/cyclonedx-dotnet) into your build pipeline.
@@ -42,7 +42,7 @@ Or add it manually to your `.csproj`:
4242
dotnet build
4343
```
4444

45-
That's it! Your SBOM will be generated at `bin/Debug/net8.0/bom.json` (or your output directory).
45+
That's it! Your SBOM will be generated at `bin/Debug/net8.0/sbom.json` (or your output directory).
4646

4747
## 📋 Features
4848

@@ -60,7 +60,7 @@ SBOMs are generated automatically:
6060

6161
### CycloneDX Specification Versions
6262

63-
Supports CycloneDX spec versions: `1.2`, `1.3`, `1.4`, `1.5`, `1.6` (default)
63+
The tool automatically uses the latest CycloneDX specification version supported by the installed tool version (typically 1.6).
6464

6565
## ⚙️ Configuration
6666

@@ -109,15 +109,6 @@ All configuration is done via MSBuild properties. Set them in your `.csproj`, `D
109109
</PropertyGroup>
110110
```
111111

112-
#### Specification Version
113-
114-
```xml
115-
<PropertyGroup>
116-
<!-- CycloneDX spec version: 1.2, 1.3, 1.4, 1.5, or 1.6 (default) -->
117-
<CycloneDxSpecVersion>1.5</CycloneDxSpecVersion>
118-
</PropertyGroup>
119-
```
120-
121112
### Advanced Options
122113

123114
#### Exclude Dependencies
@@ -132,21 +123,25 @@ All configuration is done via MSBuild properties. Set them in your `.csproj`, `D
132123
</PropertyGroup>
133124
```
134125

135-
#### License Information
126+
#### Serial Number Control
136127

137128
```xml
138129
<PropertyGroup>
139-
<!-- Include full license text (default: false, only IDs) -->
140-
<CycloneDxIncludeLicenseText>true</CycloneDxIncludeLicenseText>
130+
<!-- Disable auto-generated SBOM serial number -->
131+
<CycloneDxDisableSerialNumber>true</CycloneDxDisableSerialNumber>
141132
</PropertyGroup>
142133
```
143134

144-
#### Serial Number
135+
#### GitHub License Resolution
145136

146137
```xml
147138
<PropertyGroup>
148-
<!-- Set custom SBOM serial number (UUID) -->
149-
<CycloneDxSerialNumber>urn:uuid:12345678-1234-1234-1234-123456789abc</CycloneDxSerialNumber>
139+
<!-- Enable GitHub license resolution -->
140+
<CycloneDxEnableGitHubLicenses>true</CycloneDxEnableGitHubLicenses>
141+
142+
<!-- GitHub credentials (optional, for higher rate limits) -->
143+
<CycloneDxGitHubUsername>your-username</CycloneDxGitHubUsername>
144+
<CycloneDxGitHubToken>ghp_yourtoken</CycloneDxGitHubToken>
150145
</PropertyGroup>
151146
```
152147

@@ -172,7 +167,7 @@ Consumers of your NuGet package can inspect the SBOM:
172167
```bash
173168
# Extract and view
174169
unzip -q MyPackage.1.0.0.nupkg -d extracted
175-
cat extracted/sbom/bom.json
170+
cat extracted/sbom/sbom.json
176171
```
177172

178173
## 🏗️ Architecture
@@ -274,7 +269,7 @@ Contributions are welcome! Please feel free to submit issues, feature requests,
274269

275270
## 📄 License
276271

277-
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
272+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
278273

279274
## 🔗 Related Projects
280275

src/CycloneDX.MSBuild/CycloneDX.MSBuild.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<PackageProjectUrl>https://github.com/CycloneDX/cyclonedx-msbuild</PackageProjectUrl>
1515
<RepositoryUrl>https://github.com/CycloneDX/cyclonedx-msbuild</RepositoryUrl>
1616
<RepositoryType>git</RepositoryType>
17-
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
17+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1818
<PackageReadmeFile>README.md</PackageReadmeFile>
1919

2020
<!-- Build Configuration -->

src/CycloneDX.MSBuild/build/CycloneDX.MSBuild.props

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,23 @@
2727
<PropertyGroup Label="CycloneDX Output Configuration">
2828

2929
<!--
30-
Output format: json, xml, or spdx-json
30+
Output format: json, xml
3131
Default: json
3232
-->
3333
<CycloneDxOutputFormat Condition="'$(CycloneDxOutputFormat)' == ''">json</CycloneDxOutputFormat>
3434

3535
<!--
3636
Output directory for generated SBOM
37-
Default: $(OutputPath) (e.g., bin/Debug/net8.0/)
37+
Default: $(OutputPath) - set at build time in .targets file
38+
Users can override this in their project file
3839
-->
39-
<CycloneDxOutputDirectory Condition="'$(CycloneDxOutputDirectory)' == ''">$(OutputPath)</CycloneDxOutputDirectory>
40+
<!-- CycloneDxOutputDirectory default is set in .targets, not here -->
4041

4142
<!--
4243
Output filename (without extension)
43-
Default: bom (results in bom.json or bom.xml)
44+
Default: sbom (results in sbom.json or sbom.xml)
4445
-->
45-
<CycloneDxOutputFilename Condition="'$(CycloneDxOutputFilename)' == ''">bom</CycloneDxOutputFilename>
46+
<CycloneDxOutputFilename Condition="'$(CycloneDxOutputFilename)' == ''">sbom</CycloneDxOutputFilename>
4647

4748
</PropertyGroup>
4849

@@ -54,12 +55,6 @@
5455
-->
5556
<CycloneDxToolVersion Condition="'$(CycloneDxToolVersion)' == ''">5.5.0</CycloneDxToolVersion>
5657

57-
<!--
58-
CycloneDX specification version
59-
Supported: 1.2, 1.3, 1.4, 1.5, 1.6
60-
-->
61-
<CycloneDxSpecVersion Condition="'$(CycloneDxSpecVersion)' == ''">1.6</CycloneDxSpecVersion>
62-
6358
</PropertyGroup>
6459

6560
<PropertyGroup Label="CycloneDX Advanced Options">
@@ -77,16 +72,32 @@
7772
<CycloneDxExcludeTestProjects Condition="'$(CycloneDxExcludeTestProjects)' == ''">false</CycloneDxExcludeTestProjects>
7873

7974
<!--
80-
Include license text in SBOM
81-
Default: false (only license IDs)
75+
Disable SBOM serial number generation
76+
Default: false (serial number is auto-generated)
77+
-->
78+
<CycloneDxDisableSerialNumber Condition="'$(CycloneDxDisableSerialNumber)' == ''">false</CycloneDxDisableSerialNumber>
79+
80+
</PropertyGroup>
81+
82+
<PropertyGroup Label="CycloneDX License Resolution">
83+
84+
<!--
85+
Enable GitHub license resolution
86+
Default: false
87+
-->
88+
<CycloneDxEnableGitHubLicenses Condition="'$(CycloneDxEnableGitHubLicenses)' == ''">false</CycloneDxEnableGitHubLicenses>
89+
90+
<!--
91+
GitHub username for license resolution
92+
Leave empty to disable GitHub license lookups
8293
-->
83-
<CycloneDxIncludeLicenseText Condition="'$(CycloneDxIncludeLicenseText)' == ''">false</CycloneDxIncludeLicenseText>
94+
<CycloneDxGitHubUsername Condition="'$(CycloneDxGitHubUsername)' == ''"></CycloneDxGitHubUsername>
8495

8596
<!--
86-
Set SBOM serial number (UUID)
87-
Leave empty for auto-generation
97+
GitHub personal access token for license resolution
98+
Leave empty to use unauthenticated requests (rate limited)
8899
-->
89-
<CycloneDxSerialNumber Condition="'$(CycloneDxSerialNumber)' == ''"></CycloneDxSerialNumber>
100+
<CycloneDxGitHubToken Condition="'$(CycloneDxGitHubToken)' == ''"></CycloneDxGitHubToken>
90101

91102
</PropertyGroup>
92103

src/CycloneDX.MSBuild/build/CycloneDX.MSBuild.targets

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,35 +33,15 @@
3333
<_CycloneDxValidationFailed>false</_CycloneDxValidationFailed>
3434
</PropertyGroup>
3535

36-
<!-- Define valid output formats and spec versions -->
37-
<ItemGroup>
38-
<_ValidCycloneDxOutputFormat Include="json" />
39-
<_ValidCycloneDxOutputFormat Include="xml" />
40-
<_ValidCycloneDxSpecVersion Include="1.2" />
41-
<_ValidCycloneDxSpecVersion Include="1.3" />
42-
<_ValidCycloneDxSpecVersion Include="1.4" />
43-
<_ValidCycloneDxSpecVersion Include="1.5" />
44-
<_ValidCycloneDxSpecVersion Include="1.6" />
45-
</ItemGroup>
46-
4736
<!-- Validate output format -->
4837
<Warning
49-
Condition="! $([MSBuild]::Contains('@(_ValidCycloneDxOutputFormat)', '$(CycloneDxOutputFormat)'))"
50-
Text="[CycloneDX] Invalid output format '$(CycloneDxOutputFormat)'. Supported formats: @( _ValidCycloneDxOutputFormat->', ' ). Defaulting to json." />
38+
Condition="'$(CycloneDxOutputFormat)' != 'json' AND '$(CycloneDxOutputFormat)' != 'xml'"
39+
Text="[CycloneDX] Invalid output format '$(CycloneDxOutputFormat)'. Supported formats: json, xml. Defaulting to json." />
5140

52-
<PropertyGroup Condition="! $([MSBuild]::Contains('@(_ValidCycloneDxOutputFormat)', '$(CycloneDxOutputFormat)'))">
41+
<PropertyGroup Condition="'$(CycloneDxOutputFormat)' != 'json' AND '$(CycloneDxOutputFormat)' != 'xml'">
5342
<CycloneDxOutputFormat>json</CycloneDxOutputFormat>
5443
</PropertyGroup>
5544

56-
<!-- Validate spec version -->
57-
<Warning
58-
Condition="! $([MSBuild]::Contains('@(_ValidCycloneDxSpecVersion)', '$(CycloneDxSpecVersion)'))"
59-
Text="[CycloneDX] Invalid spec version '$(CycloneDxSpecVersion)'. Supported: @( _ValidCycloneDxSpecVersion->', ' ). Defaulting to 1.6." />
60-
61-
<PropertyGroup Condition="! $([MSBuild]::Contains('@(_ValidCycloneDxSpecVersion)', '$(CycloneDxSpecVersion)'))">
62-
<CycloneDxSpecVersion>1.6</CycloneDxSpecVersion>
63-
</PropertyGroup>
64-
6545
<!-- Ensure output directory exists -->
6646
<MakeDir Directories="$(CycloneDxOutputDirectory)" Condition="!Exists('$(CycloneDxOutputDirectory)')" />
6747

@@ -125,20 +105,40 @@
125105

126106
<Message Importance="high" Text="[CycloneDX] Generating SBOM for $(MSBuildProjectName)..." />
127107

108+
<!-- Set output directory default now, when $(OutputPath) is available -->
109+
<PropertyGroup>
110+
<CycloneDxOutputDirectory Condition="'$(CycloneDxOutputDirectory)' == ''">$(OutputPath)</CycloneDxOutputDirectory>
111+
<!-- Remove trailing backslash/slash to avoid escaping the closing quote in command-line arguments -->
112+
<CycloneDxOutputDirectory>$(CycloneDxOutputDirectory.TrimEnd('\\').TrimEnd('/'))</CycloneDxOutputDirectory>
113+
</PropertyGroup>
114+
128115
<PropertyGroup>
129116
<!-- Build command line arguments -->
130117
<_CycloneDxArgs></_CycloneDxArgs>
131118
<_CycloneDxArgs>$(_CycloneDxArgs) "$(MSBuildProjectFullPath)"</_CycloneDxArgs>
132-
<_CycloneDxArgs>$(_CycloneDxArgs) --output-directory "$(CycloneDxOutputDirectory)"</_CycloneDxArgs>
133-
<_CycloneDxArgs>$(_CycloneDxArgs) --output-filename "$(CycloneDxOutputFilename)"</_CycloneDxArgs>
134-
<_CycloneDxArgs>$(_CycloneDxArgs) --output-format $(CycloneDxOutputFormat)</_CycloneDxArgs>
135-
<_CycloneDxArgs>$(_CycloneDxArgs) --spec-version $(CycloneDxSpecVersion)</_CycloneDxArgs>
119+
<_CycloneDxArgs>$(_CycloneDxArgs) -o "$(CycloneDxOutputDirectory)"</_CycloneDxArgs>
120+
121+
<!-- Build full filename with extension based on format -->
122+
<_CycloneDxFullFilename Condition="'$(CycloneDxOutputFormat)' == 'json'">$(CycloneDxOutputFilename).json</_CycloneDxFullFilename>
123+
<_CycloneDxFullFilename Condition="'$(CycloneDxOutputFormat)' == 'xml'">$(CycloneDxOutputFilename).xml</_CycloneDxFullFilename>
124+
<!-- Fallback to json if format is invalid -->
125+
<_CycloneDxFullFilename Condition="'$(_CycloneDxFullFilename)' == ''">$(CycloneDxOutputFilename).json</_CycloneDxFullFilename>
126+
<_CycloneDxArgs>$(_CycloneDxArgs) -fn "$(_CycloneDxFullFilename)"</_CycloneDxArgs>
127+
128+
<!-- Output format: json or xml (capitalize first letter for tool) -->
129+
<_CycloneDxOutputFormat Condition="'$(CycloneDxOutputFormat)' == 'json'">Json</_CycloneDxOutputFormat>
130+
<_CycloneDxOutputFormat Condition="'$(CycloneDxOutputFormat)' == 'xml'">Xml</_CycloneDxOutputFormat>
131+
<!-- Fallback to Json if format is invalid -->
132+
<_CycloneDxOutputFormat Condition="'$(_CycloneDxOutputFormat)' == ''">Json</_CycloneDxOutputFormat>
133+
<_CycloneDxArgs>$(_CycloneDxArgs) -F $(_CycloneDxOutputFormat)</_CycloneDxArgs>
136134

137135
<!-- Optional arguments -->
138-
<_CycloneDxArgs Condition="'$(CycloneDxExcludeDev)' == 'true'">$(_CycloneDxArgs) --exclude-dev</_CycloneDxArgs>
139-
<_CycloneDxArgs Condition="'$(CycloneDxExcludeTestProjects)' == 'true'">$(_CycloneDxArgs) --exclude-test-projects</_CycloneDxArgs>
140-
<_CycloneDxArgs Condition="'$(CycloneDxIncludeLicenseText)' == 'true'">$(_CycloneDxArgs) --include-license-text</_CycloneDxArgs>
141-
<_CycloneDxArgs Condition="'$(CycloneDxSerialNumber)' != ''">$(_CycloneDxArgs) --serial-number $(CycloneDxSerialNumber)</_CycloneDxArgs>
136+
<_CycloneDxArgs Condition="'$(CycloneDxExcludeDev)' == 'true'">$(_CycloneDxArgs) -ed</_CycloneDxArgs>
137+
<_CycloneDxArgs Condition="'$(CycloneDxExcludeTestProjects)' == 'true'">$(_CycloneDxArgs) -t</_CycloneDxArgs>
138+
<_CycloneDxArgs Condition="'$(CycloneDxDisableSerialNumber)' == 'true'">$(_CycloneDxArgs) -ns</_CycloneDxArgs>
139+
<_CycloneDxArgs Condition="'$(CycloneDxEnableGitHubLicenses)' == 'true'">$(_CycloneDxArgs) -egl</_CycloneDxArgs>
140+
<_CycloneDxArgs Condition="'$(CycloneDxGitHubUsername)' != ''">$(_CycloneDxArgs) -gu "$(CycloneDxGitHubUsername)"</_CycloneDxArgs>
141+
<_CycloneDxArgs Condition="'$(CycloneDxGitHubToken)' != ''">$(_CycloneDxArgs) -gt "$(CycloneDxGitHubToken)"</_CycloneDxArgs>
142142
</PropertyGroup>
143143

144144
<!-- Execute CycloneDX tool -->

tests/Integration.Tests/DisabledProject/DisabledProject.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<OutputType>Library</OutputType>
66
</PropertyGroup>
77

8+
<!-- Import CycloneDX.MSBuild targets manually for local testing -->
9+
<Import Project="..\..\..\src\CycloneDX.MSBuild\build\CycloneDX.MSBuild.props" />
10+
<Import Project="..\..\..\src\CycloneDX.MSBuild\build\CycloneDX.MSBuild.targets" />
11+
812
<!-- Explicitly disable SBOM generation for this project -->
913
<PropertyGroup>
1014
<GenerateCycloneDxSbom>false</GenerateCycloneDxSbom>

tests/Integration.Tests/MultiTargetProject/MultiTargetProject.csproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,20 @@
33
<PropertyGroup>
44
<!-- Multi-targeting: .NET 6, .NET 8, and .NET Standard 2.0 -->
55
<TargetFrameworks>net6.0;net8.0;netstandard2.0</TargetFrameworks>
6+
<LangVersion>10.0</LangVersion>
7+
<OutputType>Library</OutputType>
8+
</PropertyGroup>
9+
10+
<!-- Enable ImplicitUsings and Nullable only for .NET 6+ (not for netstandard2.0) -->
11+
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net8.0'">
612
<ImplicitUsings>enable</ImplicitUsings>
713
<Nullable>enable</Nullable>
8-
<OutputType>Library</OutputType>
914
</PropertyGroup>
1015

16+
<!-- Import CycloneDX.MSBuild targets manually for local testing -->
17+
<Import Project="..\..\..\src\CycloneDX.MSBuild\buildMultiTargeting\CycloneDX.MSBuild.props" />
18+
<Import Project="..\..\..\src\CycloneDX.MSBuild\buildMultiTargeting\CycloneDX.MSBuild.targets" />
19+
1120
<ItemGroup>
1221
<!-- Reference the local CycloneDX.MSBuild package -->
1322
<ProjectReference Include="..\..\..\src\CycloneDX.MSBuild\CycloneDX.MSBuild.csproj">

tests/Integration.Tests/SimpleProject/SimpleProject.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
<OutputType>Library</OutputType>
88
</PropertyGroup>
99

10+
<!-- Import CycloneDX.MSBuild targets manually for local testing -->
11+
<Import Project="..\..\..\src\CycloneDX.MSBuild\build\CycloneDX.MSBuild.props" />
12+
<Import Project="..\..\..\src\CycloneDX.MSBuild\build\CycloneDX.MSBuild.targets" />
13+
1014
<ItemGroup>
1115
<!-- Reference the local CycloneDX.MSBuild package -->
1216
<ProjectReference Include="..\..\..\src\CycloneDX.MSBuild\CycloneDX.MSBuild.csproj">

0 commit comments

Comments
 (0)