Skip to content

feat: Add CSV output format support#484

Closed
vincent067 wants to merge 1 commit into
sensslen:mainfrom
vincent067:feature/csv-output-format
Closed

feat: Add CSV output format support#484
vincent067 wants to merge 1 commit into
sensslen:mainfrom
vincent067:feature/csv-output-format

Conversation

@vincent067
Copy link
Copy Markdown

@vincent067 vincent067 commented Mar 20, 2026

Hi maintainers! 👋

First off, thank you for creating and maintaining this excellent tool! nuget-license has been incredibly helpful for license compliance analysis in our .NET projects.

Feature Description

This PR adds CSV output format support to nuget-license, allowing users to export license analysis results in a structured CSV format that can be easily consumed by other tools and systems.

Use Cases

  • Excel Import: Import license data directly into Excel for further analysis and reporting
  • Compliance Reporting: Generate compliance reports that can be shared with legal teams and stakeholders
  • CI/CD Pipelines: Integrate license checks into automated build pipelines with machine-readable outputs
  • Data Processing: Feed license data into custom scripts and automation workflows

Implementation Details

  • Added command-line option
  • CSV output includes package name, version, license type, and license URL
  • Proper CSV escaping for fields containing commas or quotes
  • Headers included for easy parsing
  • Maintains backward compatibility with existing output formats

Related Issue

This implementation addresses the feature request in #423.


I hope this contribution helps make the tool even more useful for the community. Please let me know if you'd like any adjustments to the implementation or documentation!

Thanks again for the great work on this project! 🙏

Summary by CodeRabbit

  • New Features
    • Added CSV output format option for exporting license information, complementing existing Table, Markdown, and JSON formats. CSV includes package metadata (ID, version, license details, URL) and validation error columns for comprehensive license reporting.

This commit adds support for CSV output format, which is useful for:
- Importing license data into Excel
- Compliance and audit reporting
- Feeding data into internal tools and CI/CD pipelines

Changes:
- Added Csv to OutputType enum
- Created CsvOutputFormatter class with proper escaping
- Updated CommandLineOptionsParser to handle CSV format
- Updated help text to include CSV option

Closes sensslen#423
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 20, 2026

Walkthrough

This pull request adds CSV output format support to the NuGet license tool. A new Csv member was added to the OutputType enum. A new CsvOutputFormatter class was implemented to handle CSV formatting with configurable filtering for error-only results and ignored packages. The command-line parser was updated to instantiate this formatter when the Csv output type is selected, and the command-line documentation was updated to reflect Csv as a valid output format option alongside the existing Table, Markdown, Json, and JsonPretty formats.

Possibly related PRs

  • PR #418: Extends CommandLineOptionsParser.GetOutputFormatter() method to support the newly added OutputType.Csv with CsvOutputFormatter instantiation.
  • PR #412: Modifies output-format selection logic in CommandLineOptionsParser.GetOutputFormatter() and command-line options handling infrastructure that this PR builds upon.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding CSV output format support to the application.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

Migrating from UI to YAML configuration.

Use the @coderabbitai configuration command in a PR comment to get a dump of all your UI settings in YAML format. You can then edit this YAML file and upload it to the root of your repository to configure CodeRabbit programmatically.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs (1)

17-23: Add XML docs to the new public constructor and Write method.

These are public APIs and should be documented with XML comments for consistency and consumer clarity. As per coding guidelines, "Public APIs in C# should have XML documentation comments using <summary>, <param>, <returns>, <exception> tags as appropriate".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs` around lines 17 - 23, Add
XML documentation comments for the public CsvOutputFormatter constructor and the
public Write method: for the constructor CsvOutputFormatter(bool
printErrorsOnly, bool skipIgnoredPackages) add a <summary> describing the
purpose of the constructor and <param> tags for printErrorsOnly and
skipIgnoredPackages; for the method Task Write(Stream stream,
IList<LicenseValidationResult> results) add a <summary> explaining what the
method writes, <param> tags for stream and results, a <returns> documenting the
returned Task, and an <exception> tag if the method can throw (e.g.,
ArgumentNullException for null arguments or IOException for stream errors) —
place the comments immediately above the constructor and method declarations
using standard C# XML doc syntax.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs`:
- Around line 42-60: The ValidationErrors are being escaped twice: each item is
passed through EscapeCsvField in the Select and then the joined string (errors /
errorContexts) is passed through EscapeCsvField again when building the CSV
line; change this by removing the per-item escaping in the Selects that build
errors and errorContexts so they produce plain strings (e.g. string.Join("; ",
result.ValidationErrors.Select(e => e.Error))) and keep the single
EscapeCsvField call when adding errors and errorContexts to the CSV line; update
references in CsvOutputFormatter.cs to only call EscapeCsvField on the final
errors and errorContexts variables.

---

Nitpick comments:
In `@src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs`:
- Around line 17-23: Add XML documentation comments for the public
CsvOutputFormatter constructor and the public Write method: for the constructor
CsvOutputFormatter(bool printErrorsOnly, bool skipIgnoredPackages) add a
<summary> describing the purpose of the constructor and <param> tags for
printErrorsOnly and skipIgnoredPackages; for the method Task Write(Stream
stream, IList<LicenseValidationResult> results) add a <summary> explaining what
the method writes, <param> tags for stream and results, a <returns> documenting
the returned Task, and an <exception> tag if the method can throw (e.g.,
ArgumentNullException for null arguments or IOException for stream errors) —
place the comments immediately above the constructor and method declarations
using standard C# XML doc syntax.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 14b1e840-eb6d-4dba-ac53-a03894d12f1d

📥 Commits

Reviewing files that changed from the base of the PR and between a821788 and 68465fc.

📒 Files selected for processing (4)
  • src/NuGetLicense/CommandLineOptionsParser.cs
  • src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs
  • src/NuGetLicense/Program.cs
  • src/NuGetUtility/OutputType.cs

Comment on lines +42 to +60
string errors = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Error)))
: "";
string errorContexts = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Context)))
: "";

var line = string.Join(",",
EscapeCsvField(result.PackageId),
EscapeCsvField(result.PackageVersion.ToString()),
EscapeCsvField(result.LicenseInformationOrigin.ToString()),
EscapeCsvField(result.License),
EscapeCsvField(result.LicenseUrl),
EscapeCsvField(result.Copyright),
EscapeCsvField(result.Authors),
EscapeCsvField(result.Description),
EscapeCsvField(result.Summary),
EscapeCsvField(errors),
EscapeCsvField(errorContexts)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid double-escaping Error and Error Context values.

Line 42–47 escapes each error item, and Line 59–60 escapes the joined field again. This can produce incorrect CSV cell content (extra quotes).

Proposed fix
-                string errors = result.ValidationErrors.Any() 
-                    ? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Error))) 
-                    : "";
-                string errorContexts = result.ValidationErrors.Any() 
-                    ? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Context))) 
-                    : "";
+                string errors = result.ValidationErrors.Any()
+                    ? string.Join("; ", result.ValidationErrors.Select(e => e.Error))
+                    : string.Empty;
+                string errorContexts = result.ValidationErrors.Any()
+                    ? string.Join("; ", result.ValidationErrors.Select(e => e.Context))
+                    : string.Empty;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
string errors = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Error)))
: "";
string errorContexts = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => EscapeCsvField(e.Context)))
: "";
var line = string.Join(",",
EscapeCsvField(result.PackageId),
EscapeCsvField(result.PackageVersion.ToString()),
EscapeCsvField(result.LicenseInformationOrigin.ToString()),
EscapeCsvField(result.License),
EscapeCsvField(result.LicenseUrl),
EscapeCsvField(result.Copyright),
EscapeCsvField(result.Authors),
EscapeCsvField(result.Description),
EscapeCsvField(result.Summary),
EscapeCsvField(errors),
EscapeCsvField(errorContexts)
string errors = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => e.Error))
: string.Empty;
string errorContexts = result.ValidationErrors.Any()
? string.Join("; ", result.ValidationErrors.Select(e => e.Context))
: string.Empty;
var line = string.Join(",",
EscapeCsvField(result.PackageId),
EscapeCsvField(result.PackageVersion.ToString()),
EscapeCsvField(result.LicenseInformationOrigin.ToString()),
EscapeCsvField(result.License),
EscapeCsvField(result.LicenseUrl),
EscapeCsvField(result.Copyright),
EscapeCsvField(result.Authors),
EscapeCsvField(result.Description),
EscapeCsvField(result.Summary),
EscapeCsvField(errors),
EscapeCsvField(errorContexts)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NuGetLicense/Output/Csv/CsvOutputFormatter.cs` around lines 42 - 60, The
ValidationErrors are being escaped twice: each item is passed through
EscapeCsvField in the Select and then the joined string (errors / errorContexts)
is passed through EscapeCsvField again when building the CSV line; change this
by removing the per-item escaping in the Selects that build errors and
errorContexts so they produce plain strings (e.g. string.Join("; ",
result.ValidationErrors.Select(e => e.Error))) and keep the single
EscapeCsvField call when adding errors and errorContexts to the CSV line; update
references in CsvOutputFormatter.cs to only call EscapeCsvField on the final
errors and errorContexts variables.

@sensslen
Copy link
Copy Markdown
Owner

@vincent067 thank you for your contribution. There is already an open pull-request to add csv support: #468. can you help bring this across the finish line?

@sensslen sensslen closed this Mar 23, 2026
@sensslen
Copy link
Copy Markdown
Owner

Csv support has been merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants