From bc7186f8e1838c51220622a82bd38e55cda56f53 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Thu, 9 Dec 2021 14:26:47 -0800 Subject: [PATCH 01/23] Add spec proposal for machinereadable output json --- proposed/2021/MachineReadableOutput.md | 793 +++++++++++++++++++++++++ 1 file changed, 793 insertions(+) create mode 100644 proposed/2021/MachineReadableOutput.md diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md new file mode 100644 index 0000000000..f2882dae1c --- /dev/null +++ b/proposed/2021/MachineReadableOutput.md @@ -0,0 +1,793 @@ +# Machine readable JSON output for dotnet list package + +* Status: **In Review** +* Author: [Erick Yondon](https://github.com/erdembayar) +* GitHub Issue [7752](https://github.com/NuGet/Home/issues/7752) + +## Problem background + +Many organization are required by [regulation](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) to audit packages that they're using in repository. +Currently there's no easy way produce Software Bill of Material (SBOM) output which can be consumed by another auditing system or historic keeping. + +* Parse-friendly output. Other PMP like Npm already have it(`npm ls --parseable` and `npm ls --json`). +* Useful for CI/CD auditing(compliance, security ..) + * Produce Software Bill of Material (SBOM) (compliance, historic keeping) + * Enhancing Software Supply Chain Security + * check any vulnerable packages + * check any deprecated packages + * Check any outdated packages + * Check license compliance + * Resolve dependency issue (detect duplicate packages, detect new dependency introduced or existing one removed etc ..) + * Making the output machine-readable unlocks additional tooling and automation scenarios in CI/CD pipeline above scenarios. + +## Who are the customers + +Anyone (government/private enterprises, security experts, individual contributors) who wants to consume `dotnet list package` output for auditing tool or historic keeping, CI/CD orchestrating. + +## Explanation + +### Functional explanation + + + + +### --json option + +Ability to use new `--json` option for all `dotnet list package` commands to ensure JSON-formatted output is emitted to the console. + +```dotnetcli +dotnet list [|] package [--config ] + [--deprecated] + [--framework ] [--highest-minor] [--highest-patch] + [--include-prerelease] [--include-transitive] [--interactive] + [--outdated] [--source ] [-v|--verbosity ] + [--vulnerable] + [--json] + +dotnet list package -h|--help +``` + +### dotnet list package + +```dotnetcli +Project 'MyProjectA' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 + +Project 'MyProjectB' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + [net5.0]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 +``` + +### dotnet list package --json + +```json +{ + "version": 1, + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + } + ] +} +``` + +### dotnet list package --outdated + +```dotnetcli + +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +Project `MyProjectA` has the following updates to its packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Latest + > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 6.0.0 + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 6.0.0 + > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 1.1.4 + +Project `MyProjectB` has the following updates to its packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Latest + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 6.0.0 + > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 + + [net5.0]: + Top-level Package Requested Resolved Latest + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 6.0.0 + > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 +``` + +### dotnet list package --outdated --json + +```json +{ + "version": 1, + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0", + "latestVersion": "6.0.0", + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0", + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ] +} +``` + +### dotnet list package --deprecated + +```dotnetcli +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +Project `MyProjectA` has the following deprecated packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Reason(s) Alternative + > EntityFramework.MappingAPI * 6.2.1 Legacy Z.EntityFramework.Extensions >= 0.0.0 + > NuGet.Core 2.13.0 2.13.0 Legacy + +Project `MyProjectB` has the following deprecated packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Reason(s) Alternative + > NuGet.Core 2.13.0 2.13.0 Legacy + + [net5.0]: + Top-level Package Requested Resolved Reason(s) Alternative + > NuGet.Core 2.13.0 2.13.0 Legacy +``` + +### dotnet list package --deprecated --json + +```json +{ + "version": 1, + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "EntityFramework.MappingAPI", + "requestedVersion": "*", + "resolvedVersion": "6.2.1", + "reasons": ["Legacy"], + "alternativePackage": { + "id": "Z.EntityFramework.Extensions", + "versionRange": "[0.0.0,)" + } + }, + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "reasons": ["Legacy"], + "alternativePackage": null + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "reasons": ["Legacy"], + "alternativePackage": null + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "reasons": ["Legacy"], + "alternativePackage": null + } + ] + } + ] +} +``` + +### dotnet list package --vulnerable + +```dotnetcli +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +Project `MyProjectA` has the following vulnerable packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Severity Advisory URL + > DotNetNuke.Core 6.0.0 6.0.0 High https://github.com/advisories/GHSA-g8j6-m4p7-5rfq + Moderate https://github.com/advisories/GHSA-v76m-f5cx-8rg4 + Critical https://github.com/advisories/GHSA-x8f7-h444-97w4 + Moderate https://github.com/advisories/GHSA-5c66-x4wm-rjfx + High https://github.com/advisories/GHSA-x2rg-fmcv-crq5 + High https://github.com/advisories/GHSA-j3g9-6fx5-gjv7 + High https://github.com/advisories/GHSA-xx3h-j3cx-8qfj + Moderate https://github.com/advisories/GHSA-5whq-j5qg-wjvp + > DotNetZip 1.0.0 1.0.0 High https://github.com/advisories/GHSA-7378-6268-4278 + +Project `MyProjectB` has the following vulnerable packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Severity Advisory URL + > DotNetNuke.Core 6.0.0 6.0.0 High https://github.com/advisories/GHSA-g8j6-m4p7-5rfq + Moderate https://github.com/advisories/GHSA-v76m-f5cx-8rg4 + Critical https://github.com/advisories/GHSA-x8f7-h444-97w4 + Moderate https://github.com/advisories/GHSA-5c66-x4wm-rjfx + High https://github.com/advisories/GHSA-x2rg-fmcv-crq5 + High https://github.com/advisories/GHSA-j3g9-6fx5-gjv7 + High https://github.com/advisories/GHSA-xx3h-j3cx-8qfj + Moderate https://github.com/advisories/GHSA-5whq-j5qg-wjvp + + [net5.0]: + Top-level Package Requested Resolved Severity Advisory URL + > DotNetNuke.Core 6.0.0 6.0.0 High https://github.com/advisories/GHSA-g8j6-m4p7-5rfq + Moderate https://github.com/advisories/GHSA-v76m-f5cx-8rg4 + Critical https://github.com/advisories/GHSA-x8f7-h444-97w4 + Moderate https://github.com/advisories/GHSA-5c66-x4wm-rjfx + High https://github.com/advisories/GHSA-x2rg-fmcv-crq5 + High https://github.com/advisories/GHSA-j3g9-6fx5-gjv7 + High https://github.com/advisories/GHSA-xx3h-j3cx-8qfj + Moderate https://github.com/advisories/GHSA-5whq-j5qg-wjvp +``` + +### dotnet list package --vulnerable --json + +```json +{ + "version": 1, + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, +... + ] + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, +... + ] + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, +... + ] + } + ] + } + ] +} +``` + +### dotnet list package --include-transitive + +```dotnetcli +Project 'MyProjectA' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 +... + +Project 'MyProjectB' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 + > Microsoft.Win32.Primitives 4.3.0 +... + + [net5.0]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 +... + +``` + +### dotnet list package --include-transitive --json + +```json +{ + "version": 1, + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, +... + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, +... + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, +... + ] + } + ] +} +``` + +### --flatten option + +Ability to use new `--flatten` option conjunction with `--json` option for all `dotnet list package` commands to ensure JSON-formatted output is emitted to the console for multiproject solution(including multitarget projects)and all projects and target frameworks are flattened. Same package with multiple version entry is possible. It's useful more for SBOM than single `--json` option. + +```dotnetcli +dotnet list [|] package [--config ] + [--deprecated] + [--framework ] [--highest-minor] [--highest-patch] + [--include-prerelease] [--include-transitive] [--interactive] + [--outdated] [--source ] [-v|--verbosity ] + [--vulnerable] + [--json] + [--flatten] + +dotnet list package -h|--help +``` + +### dotnet list package + +```dotnetcli +Project 'MyProjectA' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 + +Project 'MyProjectB' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + [net5.0]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 +``` + +### dotnet list package --json --flatten + +```json +{ + "version": 1, + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ] +} +``` + +### dotnet list package --deprecated + +```dotnetcli +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +Project `MyProjectA` has the following deprecated packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Reason(s) Alternative + > EntityFramework.MappingAPI * 6.2.1 Legacy Z.EntityFramework.Extensions >= 0.0.0 + > NuGet.Core 2.13.0 2.13.0 Legacy + +Project `MyProjectB` has the following deprecated packages + [netcoreapp3.1]: + Top-level Package Requested Resolved Reason(s) Alternative + > NuGet.Core 2.13.0 2.13.0 Legacy + + [net5.0]: + Top-level Package Requested Resolved Reason(s) Alternative + > NuGet.Core 2.13.0 2.13.0 Legacy +``` + +### dotnet list package --deprecated --json --flatten + +```json +{ + "version": 1, + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ] +} +``` + +### dotnet list package --include-transitive + +```dotnetcli +Project 'MyProjectA' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 +... + +Project 'MyProjectB' has the following package references + [netcoreapp3.1]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 + > Microsoft.Win32.Primitives 4.3.0 +... + + [net5.0]: + Top-level Package Requested Resolved + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 + > Text2Xml.Lib 1.1.2 1.1.2 + + Transitive Package Resolved + > Microsoft.CSharp 4.0.1 + > Microsoft.NETCore.Platforms 1.1.0 + > Microsoft.NETCore.Targets 1.1.0 +... + +``` + +### dotnet list package --include-transitive --json --flatten + +```json +{ + "version": 1, + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + { + "id": "Microsoft.NETCore.Targets", + "resolvedVersion": "1.1.0" + } +... + ] +} +``` + +### Compatibility + + We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. + +### Out-of-scope + +* To avoid disk I/O, we won't support saving the machine-readable output to disk as part of this spec. The work-around is for the consumer to read from the console's stdout stream. +* At this point, no other CLI commands (e.g. dotnet list reference) will be within scope for this feature. +"--parsable" option needs separate spec. +* Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. + +## Prior Art + + + + + + +* https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit---json + +* https://github.com/NuGet/Home/wiki/%5BSpec%5D-Machine-readable-output-for-dotnet-list-package From 8807f9db2d06af23fb02c25b50eeb66a0226eaf6 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 11:52:29 -0800 Subject: [PATCH 02/23] Address PR comments by Chris --- proposed/2021/MachineReadableOutput.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index f2882dae1c..65f30e4226 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -6,18 +6,19 @@ ## Problem background -Many organization are required by [regulation](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) to audit packages that they're using in repository. -Currently there's no easy way produce Software Bill of Material (SBOM) output which can be consumed by another auditing system or historic keeping. +Many organizations are required by [regulation](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) to audit packages that they're using in a repository. -* Parse-friendly output. Other PMP like Npm already have it(`npm ls --parseable` and `npm ls --json`). +Currently there's no easy way to produce a [Software Bill of Material (SBOM)](https://blog.sonatype.com/what-is-a-software-bill-of-materials) output which can be consumed by another auditing system or kept for records. + +* Parse-friendly output. Other package managers like [NPM already have it](https://docs.npmjs.com/cli/v7/commands/npm-ls) (`npm ls --parseable` and `npm ls --json`). * Useful for CI/CD auditing(compliance, security ..) * Produce Software Bill of Material (SBOM) (compliance, historic keeping) * Enhancing Software Supply Chain Security - * check any vulnerable packages - * check any deprecated packages + * Check any vulnerable packages + * Check any deprecated packages * Check any outdated packages * Check license compliance - * Resolve dependency issue (detect duplicate packages, detect new dependency introduced or existing one removed etc ..) + * Resolve dependency issues (detect duplicate packages, newly introduced dependencies, dependency removals, etc.) * Making the output machine-readable unlocks additional tooling and automation scenarios in CI/CD pipeline above scenarios. ## Who are the customers From 6bde8f7c961af854439be43546faae468e835c78 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 11:56:59 -0800 Subject: [PATCH 03/23] Anything that is null should just not show up in JSON in my opinion. --- proposed/2021/MachineReadableOutput.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 65f30e4226..7f27d2f9ac 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -283,7 +283,6 @@ Project `MyProjectB` has the following deprecated packages "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", "reasons": ["Legacy"], - "alternativePackage": null } ] } @@ -297,7 +296,6 @@ Project `MyProjectB` has the following deprecated packages "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", "reasons": ["Legacy"], - "alternativePackage": null } ] }, @@ -309,7 +307,6 @@ Project `MyProjectB` has the following deprecated packages "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", "reasons": ["Legacy"], - "alternativePackage": null } ] } From 818183f645d6a6fad76cb7eb556a0d3968b20179 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 12:19:46 -0800 Subject: [PATCH 04/23] Address save to disk comment --- proposed/2021/MachineReadableOutput.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 7f27d2f9ac..0e49056ad3 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -774,7 +774,7 @@ Project 'MyProjectB' has the following package references ### Out-of-scope -* To avoid disk I/O, we won't support saving the machine-readable output to disk as part of this spec. The work-around is for the consumer to read from the console's stdout stream. +* We won't support saving the machine-readable output to disk as part of this spec. The work-around is for the consumer to read from the console's stdout stream. * At this point, no other CLI commands (e.g. dotnet list reference) will be within scope for this feature. "--parsable" option needs separate spec. * Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. From 42bed0190e6ec2b030ab9025af44f0dc83423d33 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 12:27:35 -0800 Subject: [PATCH 05/23] Remove flatten option --- proposed/2021/MachineReadableOutput.md | 194 ------------------------- 1 file changed, 194 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 0e49056ad3..c2fb22c080 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -574,200 +574,6 @@ Project 'MyProjectB' has the following package references } ``` -### --flatten option - -Ability to use new `--flatten` option conjunction with `--json` option for all `dotnet list package` commands to ensure JSON-formatted output is emitted to the console for multiproject solution(including multitarget projects)and all projects and target frameworks are flattened. Same package with multiple version entry is possible. It's useful more for SBOM than single `--json` option. - -```dotnetcli -dotnet list [|] package [--config ] - [--deprecated] - [--framework ] [--highest-minor] [--highest-patch] - [--include-prerelease] [--include-transitive] [--interactive] - [--outdated] [--source ] [-v|--verbosity ] - [--vulnerable] - [--json] - [--flatten] - -dotnet list package -h|--help -``` - -### dotnet list package - -```dotnetcli -Project 'MyProjectA' has the following package references - [netcoreapp3.1]: - Top-level Package Requested Resolved - > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 - -Project 'MyProjectB' has the following package references - [netcoreapp3.1]: - Top-level Package Requested Resolved - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib 1.1.2 1.1.2 - - [net5.0]: - Top-level Package Requested Resolved - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib 1.1.2 1.1.2 -``` - -### dotnet list package --json --flatten - -```json -{ - "version": 1, - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ] -} -``` - -### dotnet list package --deprecated - -```dotnetcli -The following sources were used: - https://api.nuget.org/v3/index.json - https://apidev.nugettest.org/v3-index/index.json - -Project `MyProjectA` has the following deprecated packages - [netcoreapp3.1]: - Top-level Package Requested Resolved Reason(s) Alternative - > EntityFramework.MappingAPI * 6.2.1 Legacy Z.EntityFramework.Extensions >= 0.0.0 - > NuGet.Core 2.13.0 2.13.0 Legacy - -Project `MyProjectB` has the following deprecated packages - [netcoreapp3.1]: - Top-level Package Requested Resolved Reason(s) Alternative - > NuGet.Core 2.13.0 2.13.0 Legacy - - [net5.0]: - Top-level Package Requested Resolved Reason(s) Alternative - > NuGet.Core 2.13.0 2.13.0 Legacy -``` - -### dotnet list package --deprecated --json --flatten - -```json -{ - "version": 1, - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ] -} -``` - -### dotnet list package --include-transitive - -```dotnetcli -Project 'MyProjectA' has the following package references - [netcoreapp3.1]: - Top-level Package Requested Resolved - > Microsoft.Extensions.Primitives [1.0.0, 5.0.0] 1.0.0 - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib [1.1.2, 2.0.0) 1.1.2 - - Transitive Package Resolved - > Microsoft.CSharp 4.0.1 - > Microsoft.NETCore.Platforms 1.1.0 - > Microsoft.NETCore.Targets 1.1.0 -... - -Project 'MyProjectB' has the following package references - [netcoreapp3.1]: - Top-level Package Requested Resolved - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib 1.1.2 1.1.2 - - Transitive Package Resolved - > Microsoft.CSharp 4.0.1 - > Microsoft.NETCore.Platforms 1.1.0 - > Microsoft.NETCore.Targets 1.1.0 - > Microsoft.Win32.Primitives 4.3.0 -... - - [net5.0]: - Top-level Package Requested Resolved - > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 - > Text2Xml.Lib 1.1.2 1.1.2 - - Transitive Package Resolved - > Microsoft.CSharp 4.0.1 - > Microsoft.NETCore.Platforms 1.1.0 - > Microsoft.NETCore.Targets 1.1.0 -... - -``` - -### dotnet list package --include-transitive --json --flatten - -```json -{ - "version": 1, - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, - { - "id": "Microsoft.NETCore.Targets", - "resolvedVersion": "1.1.0" - } -... - ] -} -``` - ### Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. From e49851a70e2faaf42f7f0428f3116a48f36c5e5d Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 12:38:33 -0800 Subject: [PATCH 06/23] Change reasons to deprecationReasons --- proposed/2021/MachineReadableOutput.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index c2fb22c080..e66666caad 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -32,7 +32,7 @@ Anyone (government/private enterprises, security experts, individual contributor -### --json option +#### --json option Ability to use new `--json` option for all `dotnet list package` commands to ensure JSON-formatted output is emitted to the console. @@ -48,7 +48,7 @@ dotnet list [|] package [--config ] dotnet list package -h|--help ``` -### dotnet list package +#### dotnet list package ```dotnetcli Project 'MyProjectA' has the following package references @@ -70,7 +70,7 @@ Project 'MyProjectB' has the following package references > Text2Xml.Lib 1.1.2 1.1.2 ``` -### dotnet list package --json +#### dotnet list package --json ```json { @@ -132,7 +132,7 @@ Project 'MyProjectB' has the following package references } ``` -### dotnet list package --outdated +#### dotnet list package --outdated ```dotnetcli @@ -159,7 +159,7 @@ Project `MyProjectB` has the following updates to its packages > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 ``` -### dotnet list package --outdated --json +#### dotnet list package --outdated --json ```json { @@ -232,7 +232,7 @@ Project `MyProjectB` has the following updates to its packages } ``` -### dotnet list package --deprecated +#### dotnet list package --deprecated ```dotnetcli The following sources were used: @@ -255,7 +255,7 @@ Project `MyProjectB` has the following deprecated packages > NuGet.Core 2.13.0 2.13.0 Legacy ``` -### dotnet list package --deprecated --json +#### dotnet list package --deprecated --json ```json { @@ -272,7 +272,7 @@ Project `MyProjectB` has the following deprecated packages "id": "EntityFramework.MappingAPI", "requestedVersion": "*", "resolvedVersion": "6.2.1", - "reasons": ["Legacy"], + "deprecationReasons": ["Legacy"], "alternativePackage": { "id": "Z.EntityFramework.Extensions", "versionRange": "[0.0.0,)" @@ -282,7 +282,7 @@ Project `MyProjectB` has the following deprecated packages "id": "NuGet.Core", "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", - "reasons": ["Legacy"], + "deprecationReasons": ["Legacy"], } ] } @@ -295,7 +295,7 @@ Project `MyProjectB` has the following deprecated packages "id": "NuGet.Core", "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", - "reasons": ["Legacy"], + "deprecationReasons": ["Legacy"], } ] }, @@ -306,7 +306,7 @@ Project `MyProjectB` has the following deprecated packages "id": "NuGet.Core", "requestedVersion": "2.13.0", "resolvedVersion": "2.13.0", - "reasons": ["Legacy"], + "deprecationReasons": ["Legacy"], } ] } @@ -314,7 +314,7 @@ Project `MyProjectB` has the following deprecated packages } ``` -### dotnet list package --vulnerable +#### dotnet list package --vulnerable ```dotnetcli The following sources were used: @@ -585,7 +585,7 @@ Project 'MyProjectB' has the following package references "--parsable" option needs separate spec. * Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. -## Prior Art +### Prior Art From 2420fd2e2d589127e5e34482e365f9bd31a37238 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 13:21:24 -0800 Subject: [PATCH 07/23] Improve cli command format --- proposed/2021/MachineReadableOutput.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index e66666caad..b23019977e 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -48,7 +48,7 @@ dotnet list [|] package [--config ] dotnet list package -h|--help ``` -#### dotnet list package +#### `> dotnet list package` ```dotnetcli Project 'MyProjectA' has the following package references @@ -70,7 +70,7 @@ Project 'MyProjectB' has the following package references > Text2Xml.Lib 1.1.2 1.1.2 ``` -#### dotnet list package --json +#### `> dotnet list package --json` ```json { @@ -132,7 +132,7 @@ Project 'MyProjectB' has the following package references } ``` -#### dotnet list package --outdated +#### `> dotnet list package --outdated` ```dotnetcli @@ -159,7 +159,7 @@ Project `MyProjectB` has the following updates to its packages > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 ``` -#### dotnet list package --outdated --json +#### `> dotnet list package --outdated --json` ```json { @@ -232,7 +232,7 @@ Project `MyProjectB` has the following updates to its packages } ``` -#### dotnet list package --deprecated +#### `> dotnet list package --deprecated` ```dotnetcli The following sources were used: @@ -255,7 +255,7 @@ Project `MyProjectB` has the following deprecated packages > NuGet.Core 2.13.0 2.13.0 Legacy ``` -#### dotnet list package --deprecated --json +#### `> dotnet list package --deprecated --json` ```json { @@ -314,7 +314,7 @@ Project `MyProjectB` has the following deprecated packages } ``` -#### dotnet list package --vulnerable +#### `> dotnet list package --vulnerable` ```dotnetcli The following sources were used: @@ -358,7 +358,7 @@ Project `MyProjectB` has the following vulnerable packages Moderate https://github.com/advisories/GHSA-5whq-j5qg-wjvp ``` -### dotnet list package --vulnerable --json +### `> dotnet list package --vulnerable --json` ```json { @@ -437,7 +437,7 @@ Project `MyProjectB` has the following vulnerable packages } ``` -### dotnet list package --include-transitive +### `> dotnet list package --include-transitive` ```dotnetcli Project 'MyProjectA' has the following package references @@ -479,7 +479,7 @@ Project 'MyProjectB' has the following package references ``` -### dotnet list package --include-transitive --json +### `> dotnet list package --include-transitive --json` ```json { From 63643df94b30f0ece9d6e149dd5a140bdd15d579 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 13:46:11 -0800 Subject: [PATCH 08/23] Address Chet's comment --- proposed/2021/MachineReadableOutput.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index b23019977e..7fbede9d8b 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -32,9 +32,9 @@ Anyone (government/private enterprises, security experts, individual contributor -#### --json option +#### `--format` option -Ability to use new `--json` option for all `dotnet list package` commands to ensure JSON-formatted output is emitted to the console. +Ability to use new `--format` option for all `dotnet list package` commands to ensure formatted(JSON etc) output is emitted to the console. ```dotnetcli dotnet list [|] package [--config ] @@ -43,11 +43,13 @@ dotnet list [|] package [--config ] [--include-prerelease] [--include-transitive] [--interactive] [--outdated] [--source ] [-v|--verbosity ] [--vulnerable] - [--json] + [--format ] dotnet list package -h|--help ``` +`` - Allowed values as part of spec is `json`. (In the future `parseable`, `yaml` could be candidates.) + #### `> dotnet list package` ```dotnetcli @@ -70,7 +72,7 @@ Project 'MyProjectB' has the following package references > Text2Xml.Lib 1.1.2 1.1.2 ``` -#### `> dotnet list package --json` +#### `> dotnet list package --format json` ```json { @@ -159,7 +161,7 @@ Project `MyProjectB` has the following updates to its packages > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 ``` -#### `> dotnet list package --outdated --json` +#### `> dotnet list package --outdated --format json` ```json { @@ -255,7 +257,7 @@ Project `MyProjectB` has the following deprecated packages > NuGet.Core 2.13.0 2.13.0 Legacy ``` -#### `> dotnet list package --deprecated --json` +#### `> dotnet list package --deprecated --format json` ```json { @@ -358,7 +360,7 @@ Project `MyProjectB` has the following vulnerable packages Moderate https://github.com/advisories/GHSA-5whq-j5qg-wjvp ``` -### `> dotnet list package --vulnerable --json` +### `> dotnet list package --vulnerable --format json` ```json { @@ -479,7 +481,7 @@ Project 'MyProjectB' has the following package references ``` -### `> dotnet list package --include-transitive --json` +### `> dotnet list package --include-transitive --format json` ```json { From f04e17f68e980857eea9f9d59d2cca525b244ba2 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 13:53:02 -0800 Subject: [PATCH 09/23] Fix levels --- proposed/2021/MachineReadableOutput.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 7fbede9d8b..6bc691eea1 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -48,7 +48,7 @@ dotnet list [|] package [--config ] dotnet list package -h|--help ``` -`` - Allowed values as part of spec is `json`. (In the future `parseable`, `yaml` could be candidates.) +`` - Allowed values as part of spec is `json`. (In the future `parseable`, `csv`, `yaml`, `xml` could be candidates.) #### `> dotnet list package` @@ -439,7 +439,7 @@ Project `MyProjectB` has the following vulnerable packages } ``` -### `> dotnet list package --include-transitive` +#### `> dotnet list package --include-transitive` ```dotnetcli Project 'MyProjectA' has the following package references @@ -481,7 +481,7 @@ Project 'MyProjectB' has the following package references ``` -### `> dotnet list package --include-transitive --format json` +#### `> dotnet list package --include-transitive --format json` ```json { @@ -576,18 +576,18 @@ Project 'MyProjectB' has the following package references } ``` -### Compatibility +## Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. -### Out-of-scope +## Out-of-scope * We won't support saving the machine-readable output to disk as part of this spec. The work-around is for the consumer to read from the console's stdout stream. * At this point, no other CLI commands (e.g. dotnet list reference) will be within scope for this feature. "--parsable" option needs separate spec. * Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. -### Prior Art +## Prior Art @@ -597,3 +597,5 @@ Project 'MyProjectB' has the following package references * https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit---json * https://github.com/NuGet/Home/wiki/%5BSpec%5D-Machine-readable-output-for-dotnet-list-package + +## Unresolved Questions \ No newline at end of file From 8a9d816008a45f0be6cbdf99be4e4361061d69e7 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 16:23:23 -0800 Subject: [PATCH 10/23] Summarize feedback inputs. --- proposed/2021/MachineReadableOutput.md | 32 +++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 6bc691eea1..eb064375ca 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -34,7 +34,7 @@ Anyone (government/private enterprises, security experts, individual contributor #### `--format` option -Ability to use new `--format` option for all `dotnet list package` commands to ensure formatted(JSON etc) output is emitted to the console. +Ability to use new `--format` option for all `dotnet list package` commands to ensure formatted(json, text, csv etc) output is emitted to the console. ```dotnetcli dotnet list [|] package [--config ] @@ -48,7 +48,7 @@ dotnet list [|] package [--config ] dotnet list package -h|--help ``` -`` - Allowed values as part of spec is `json`. (In the future `parseable`, `csv`, `yaml`, `xml` could be candidates.) +`` - Allowed values as part of spec is `json`. Also `text` is acceptable value too, it'll just output current cli output. (In the future `parseable`, `csv`, `yaml`, `xml` could be candidates.) #### `> dotnet list package` @@ -587,6 +587,10 @@ Project 'MyProjectB' has the following package references "--parsable" option needs separate spec. * Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. +## Rationale and alternatives +Currently, no other `dotnet command` implemented this, this is the 1st time dotnet command implementing `json`(etc) output, so it could become example for others next time they implement. +Please note, except "tab completion" (for dotnet) part all changes would be inside NuGet.Client repo(under NuGet.Core), and risk of introducing regression is low.(`--format text` refactoring related changes only come into my mind.), no impact on dotnet sdk. + ## Prior Art @@ -598,4 +602,26 @@ Project 'MyProjectB' has the following package references * https://github.com/NuGet/Home/wiki/%5BSpec%5D-Machine-readable-output-for-dotnet-list-package -## Unresolved Questions \ No newline at end of file +## Unresolved Questions + +* Chris: One problem is most `dotnet list package` options outputs are exclusive and have to query separately and join result to get full picture. Both below approach require additional work. + * dotnet cli needs an all up `dotnet list package --all` that shows all deprecated, vulnerable, and outdated top level and transitive packages. [r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629) + * Alternatively the behavior of --outdated and --deprecated could be additive rather than exclusive. That adds to the scope of this work though.[r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629). With this approach we can have single schema to populate. + +* Donnie: When I want to create archival records, will I want something more unique than the project name? +Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github.com/NuGet/Home/pull/11446#discussion_r766920783) + * `name/relative path to solution` could be solution here. + +* Donnie: How can we record in the output that --include-transitive wasn't used here? +In other words, if I look at this output years from now, how would I know whether any transitives were in this project? [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390) + * packages.lock.json format could be used here. + +* Loïc : Should `dotnet list package` include hashes or package source for each dependency? The package ID and version isn't globally unique across package sources? + * If we re-sign package then hash changes? +* Related to above: `dotnet list package --outdated`output include `The following sources were used:`, but `dotnet list package` doesn't. Should we make them same? +* Loïc : Should we include some sort of hash or package source used to restore the package? A package ID and version may have different content across different package sources. In other words, the package ID + version does not actually capture which package your project depends on. [r767030495](https://github.com/NuGet/Home/pull/11446#discussion_r767030495) +* Loïc : How would this format evolve if we add another "package pivot" in addition to top level and transitive packages? For example, what if we add new package kinds for source generators, Roslyn analyzers, etc...? [r767026799](https://github.com/NuGet/Home/pull/11446#discussion_r767026799) + +* Could we use existing packages.lock.json format? [sample](https://gist.github.com/erdembayar/4894b66bde227147b60e60997d20df41) + * Direct/top level packages point to dependency packages. + * Content hash. From 0edba2a68b859c516d5180d11507ea5e244c07d8 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Fri, 10 Dec 2021 18:02:06 -0800 Subject: [PATCH 11/23] Project needs own property. --- proposed/2021/MachineReadableOutput.md | 640 +++++++++++++------------ 1 file changed, 325 insertions(+), 315 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index eb064375ca..a969ea4a7a 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -77,60 +77,62 @@ Project 'MyProjectB' has the following package references ```json { "version": 1, - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ] - } - ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ] - } - ] + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + } + ] + } } ``` @@ -169,68 +171,70 @@ Project `MyProjectB` has the following updates to its packages "sources": [ "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" - ], - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0", - "latestVersion": "6.0.0", - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0", - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - } ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - } - ] + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0", + "latestVersion": "6.0.0", + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0", + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ] + } } ``` @@ -266,53 +270,55 @@ Project `MyProjectB` has the following deprecated packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "EntityFramework.MappingAPI", - "requestedVersion": "*", - "resolvedVersion": "6.2.1", - "deprecationReasons": ["Legacy"], - "alternativePackage": { - "id": "Z.EntityFramework.Extensions", - "versionRange": "[0.0.0,)" + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "EntityFramework.MappingAPI", + "requestedVersion": "*", + "resolvedVersion": "6.2.1", + "deprecationReasons": ["Legacy"], + "alternativePackage": { + "id": "Z.EntityFramework.Extensions", + "versionRange": "[0.0.0,)" + } + }, + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], } - }, - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - } - ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - } - ] + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], + } + ] + } + ] + } } ``` @@ -369,73 +375,75 @@ Project `MyProjectB` has the following vulnerable packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, -... - ] - } - ] - } - ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, -... - ] - } - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, -... - ] - } - ] - } - ] + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + } + ] + } } ``` @@ -486,93 +494,95 @@ Project 'MyProjectB' has the following package references ```json { "version": 1, - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, -... - ] - } - ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, -... - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, -... - ] - } - ] + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + } + ] + } } ``` From 48679b9bbbf353e6596a34d4d93b5b0f011c8799 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Mon, 13 Dec 2021 11:53:25 -0800 Subject: [PATCH 12/23] Address comment by Chris and offline feedback from Chet. --- proposed/2021/MachineReadableOutput.md | 186 ++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 1 deletion(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index a969ea4a7a..c79454772c 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -25,7 +25,13 @@ Currently there's no easy way to produce a [Software Bill of Material (SBOM)](ht Anyone (government/private enterprises, security experts, individual contributors) who wants to consume `dotnet list package` output for auditing tool or historic keeping, CI/CD orchestrating. -## Explanation +## Solution + +In order to solve problem going to introduce 2 new options. + +1. `--format` option for all `dotnet list package` commands to ensure formatted(json, text, csv etc) output is emitted to the console. + +1. `--all` option which works in conjunction with above for that shows all deprecated, vulnerable, and outdated top level and transitive packages. Users can form their own json as a last resort, instead of your team having to respond to every possible user need. ### Functional explanation @@ -503,6 +509,7 @@ Project 'MyProjectB' has the following package references "id": "Microsoft.Extensions.Primitives", "requestedVersion": "[1.0.0, 5.0.0]", "resolvedVersion": "1.0.0" + }, { "id": "NuGet.Commands", @@ -586,6 +593,183 @@ Project 'MyProjectB' has the following package references } ``` +#### `--all` option + +Ability to use new `--all` option in conjunction with `--format` option shows all deprecated, vulnerable, and outdated top level and transitive packages. Users can form their own json as a last resort, instead of your team having to respond to every possible user need. It would result in if `[--deprecated],[--include-transitive],[--outdated],[--vulnerable]` are combined, currently options '--outdated', '--deprecated' and '--vulnerable' cannot be combined on cli. + +```dotnetcli +dotnet list [|] package [--config ] + [--framework ] [--highest-minor] [--highest-patch] + [--include-prerelease] [--interactive] + [--source ] [-v|--verbosity ] + [--format ] + [--all] + +dotnet list package -h|--help +``` + +#### `> dotnet list package --format json --all` + +```json +{ + "version": 1, + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "projects": { + "MyProjectA": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "latestVersion": "6.1.4", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "latestVersion": "4.1.4", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0", + "latestVersion": "2.1.4", + "deprecationReasons": ["Legacy"] + } + ] + } + ], + "MyProjectB": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "latestVersion": "7.0.0", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "latestVersion": "4.1.4", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0", + "latestVersion": "2.1.4", + "deprecationReasons": ["Legacy"] + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "latestVersion": "7.0.0", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "latestVersion": "4.1.4", + "deprecationReasons": ["Legacy"], + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0", + "latestVersion": "2.1.4", + "deprecationReasons": ["Legacy"] + } + ] + } + ] + } +} +``` + ## Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. From 9599d27aecd82ac7500efac06e8095c2b4020ed5 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Tue, 14 Dec 2021 14:21:03 -0800 Subject: [PATCH 13/23] Revert "Address comment by Chris and offline feedback from Chet." This reverts commit 48679b9bbbf353e6596a34d4d93b5b0f011c8799. --- proposed/2021/MachineReadableOutput.md | 186 +------------------------ 1 file changed, 1 insertion(+), 185 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index c79454772c..a969ea4a7a 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -25,13 +25,7 @@ Currently there's no easy way to produce a [Software Bill of Material (SBOM)](ht Anyone (government/private enterprises, security experts, individual contributors) who wants to consume `dotnet list package` output for auditing tool or historic keeping, CI/CD orchestrating. -## Solution - -In order to solve problem going to introduce 2 new options. - -1. `--format` option for all `dotnet list package` commands to ensure formatted(json, text, csv etc) output is emitted to the console. - -1. `--all` option which works in conjunction with above for that shows all deprecated, vulnerable, and outdated top level and transitive packages. Users can form their own json as a last resort, instead of your team having to respond to every possible user need. +## Explanation ### Functional explanation @@ -509,7 +503,6 @@ Project 'MyProjectB' has the following package references "id": "Microsoft.Extensions.Primitives", "requestedVersion": "[1.0.0, 5.0.0]", "resolvedVersion": "1.0.0" - }, { "id": "NuGet.Commands", @@ -593,183 +586,6 @@ Project 'MyProjectB' has the following package references } ``` -#### `--all` option - -Ability to use new `--all` option in conjunction with `--format` option shows all deprecated, vulnerable, and outdated top level and transitive packages. Users can form their own json as a last resort, instead of your team having to respond to every possible user need. It would result in if `[--deprecated],[--include-transitive],[--outdated],[--vulnerable]` are combined, currently options '--outdated', '--deprecated' and '--vulnerable' cannot be combined on cli. - -```dotnetcli -dotnet list [|] package [--config ] - [--framework ] [--highest-minor] [--highest-patch] - [--include-prerelease] [--interactive] - [--source ] [-v|--verbosity ] - [--format ] - [--all] - -dotnet list package -h|--help -``` - -#### `> dotnet list package --format json --all` - -```json -{ - "version": 1, - "sources": [ - "https://api.nuget.org/v3/index.json", - "https://apidev.nugettest.org/v3-index/index.json" - ], - "projects": { - "MyProjectA": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "latestVersion": "6.1.4", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1", - "latestVersion": "4.1.4", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0", - "latestVersion": "2.1.4", - "deprecationReasons": ["Legacy"] - } - ] - } - ], - "MyProjectB": [ - { - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "latestVersion": "7.0.0", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1", - "latestVersion": "4.1.4", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0", - "latestVersion": "2.1.4", - "deprecationReasons": ["Legacy"] - } - ] - }, - { - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "latestVersion": "7.0.0", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1", - "latestVersion": "4.1.4", - "deprecationReasons": ["Legacy"], - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, - { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0", - "latestVersion": "2.1.4", - "deprecationReasons": ["Legacy"] - } - ] - } - ] - } -} -``` - ## Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. From c1def2b47fec63e10b339c7423a10a9601469b32 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Tue, 18 Jan 2022 12:02:42 -0800 Subject: [PATCH 14/23] Address community feedback --- proposed/2021/MachineReadableOutput.md | 48 +++++++++++++++++++------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index a969ea4a7a..07ee92862d 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -48,8 +48,6 @@ dotnet list [|] package [--config ] dotnet list package -h|--help ``` -`` - Allowed values as part of spec is `json`. Also `text` is acceptable value too, it'll just output current cli output. (In the future `parseable`, `csv`, `yaml`, `xml` could be candidates.) - #### `> dotnet list package` ```dotnetcli @@ -80,6 +78,7 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -102,6 +101,7 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -117,6 +117,7 @@ Project 'MyProjectB' has the following package references ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -175,6 +176,7 @@ Project `MyProjectB` has the following updates to its packages "projects": { "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -200,6 +202,7 @@ Project `MyProjectB` has the following updates to its packages ], "MyProjectB": [ { + "Path": "src/tool/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -217,6 +220,7 @@ Project `MyProjectB` has the following updates to its packages ] }, { + "Path": "src/tool/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -271,8 +275,10 @@ Project `MyProjectB` has the following deprecated packages "https://apidev.nugettest.org/v3-index/index.json" ], "projects": { + "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -296,6 +302,7 @@ Project `MyProjectB` has the following deprecated packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -307,6 +314,7 @@ Project `MyProjectB` has the following deprecated packages ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -378,6 +386,7 @@ Project `MyProjectB` has the following vulnerable packages "projects": { "MyProjectA": [ { + "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -401,6 +410,7 @@ Project `MyProjectB` has the following vulnerable packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -422,6 +432,7 @@ Project `MyProjectB` has the following vulnerable packages ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -497,6 +508,7 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { + "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -530,6 +542,7 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -556,6 +569,7 @@ Project 'MyProjectB' has the following package references ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -608,15 +622,13 @@ Please note, except "tab completion" (for dotnet) part all changes would be insi -* https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit---json +* https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit---futjson There're some overlaps, but current spec is one more focused on SBOM and CI/CD actions, while `dotnet audit fix` is more focused detecting/fixing dependencies manually. Current spec already include ideas from this spec like `json format`. -* https://github.com/NuGet/Home/wiki/%5BSpec%5D-Machine-readable-output-for-dotnet-list-package +* https://github.com/NuGet/Home/wiki/%5BSpec%5D-Machine-readable-output-for-dotnet-list-package Basic idea from this spec is still same here and I extended from it. In current spec more orient to `dotnet style syntax` and cover more uses cases like `dotnet list package --vulnerable --format json` and `--include-transitive`, also json schema improved to include project name/identifier for multi-project scenario which would most likely use case. -## Unresolved Questions +* https://docs.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters One idea we can take from `dotnet counter` is we can specify output file with `-o`, `--output` option. So instead of writing output into console, it allows output directly saved into file. It allows both `csv` and `json` formats, currently saved file doesn't have version concept. -* Chris: One problem is most `dotnet list package` options outputs are exclusive and have to query separately and join result to get full picture. Both below approach require additional work. - * dotnet cli needs an all up `dotnet list package --all` that shows all deprecated, vulnerable, and outdated top level and transitive packages. [r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629) - * Alternatively the behavior of --outdated and --deprecated could be additive rather than exclusive. That adds to the scope of this work though.[r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629). With this approach we can have single schema to populate. +## Unresolved Questions * Donnie: When I want to create archival records, will I want something more unique than the project name? Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github.com/NuGet/Home/pull/11446#discussion_r766920783) @@ -626,12 +638,22 @@ Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github In other words, if I look at this output years from now, how would I know whether any transitives were in this project? [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390) * packages.lock.json format could be used here. -* Loïc : Should `dotnet list package` include hashes or package source for each dependency? The package ID and version isn't globally unique across package sources? - * If we re-sign package then hash changes? -* Related to above: `dotnet list package --outdated`output include `The following sources were used:`, but `dotnet list package` doesn't. Should we make them same? -* Loïc : Should we include some sort of hash or package source used to restore the package? A package ID and version may have different content across different package sources. In other words, the package ID + version does not actually capture which package your project depends on. [r767030495](https://github.com/NuGet/Home/pull/11446#discussion_r767030495) * Loïc : How would this format evolve if we add another "package pivot" in addition to top level and transitive packages? For example, what if we add new package kinds for source generators, Roslyn analyzers, etc...? [r767026799](https://github.com/NuGet/Home/pull/11446#discussion_r767026799) +>> Out of scope from MVP, this schema can evolve over time, by the time we have necessity to do change we can make more educated decision. + * Could we use existing packages.lock.json format? [sample](https://gist.github.com/erdembayar/4894b66bde227147b60e60997d20df41) * Direct/top level packages point to dependency packages. - * Content hash. + * Content hash. >> out of scope for now. Tracking issue https://github.com/NuGet/Home/issues/11552 + +## Future Possibilities + +* Show resolution tree for transitive dependencies and constraint for dependency [resolved version](https://github.com/NuGet/Home/pull/11446/files#r777233006), tracking issue: https://github.com/NuGet/Home/issues/11553 + +* Return different exit codes if any vulnerabilities, deprecations, outdated package is [detected](https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit-exit-codes). + +* `--all` option for dotnet list package [r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629), tracking issue https://github.com/NuGet/Home/issues/11551 + +* Include-transitive dependencies by default [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390), tracking issue https://github.com/NuGet/Home/issues/11550 + +* Include hash + source for package, because same package ID+version might have different hash. It can be used to detect [dependency confusion attack](https://github.com/NuGet/Home/pull/11446#discussion_r767030495), tracking issue: https://github.com/NuGet/Home/issues/11552 \ No newline at end of file From b695020bed72c90592ef8d2d165b4d3b2c2ad32c Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Wed, 2 Feb 2022 15:11:11 -0800 Subject: [PATCH 15/23] Add more complex scenarios. --- proposed/2021/MachineReadableOutput.md | 157 +++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 10 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 07ee92862d..7b8b32c8c0 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -75,6 +75,7 @@ Project 'MyProjectB' has the following package references ```json { "version": 1, + "parameters": "", "projects": { "MyProjectA": [ { @@ -169,6 +170,7 @@ Project `MyProjectB` has the following updates to its packages ```json { "version": 1, + "parameters": "--outdated", "sources": [ "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" @@ -270,6 +272,7 @@ Project `MyProjectB` has the following deprecated packages ```json { "version": 1, + "parameters": "--deprecated", "sources": [ "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" @@ -379,6 +382,7 @@ Project `MyProjectB` has the following vulnerable packages ```json { "version": 1, + "parameters": "--vulnerable", "sources": [ "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" @@ -505,6 +509,7 @@ Project 'MyProjectB' has the following package references ```json { "version": 1, + "parameters": "--include-transitive", "projects": { "MyProjectA": [ { @@ -600,6 +605,128 @@ Project 'MyProjectB' has the following package references } ``` + +#### `> dotnet list package --include-transitive --outdated --framework net5.0` + +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +No packages were found for the project `MyProjectA` given the specified frameworks. +Project `MyProjectB` has the following updates to its packages + [net5.0]: + Top-level Package Requested Resolved Latest + > NuGet.Commands 4.8.0-preview3.5278 4.8.0-preview3.5278 6.0.0 + > Text2Xml.Lib 1.1.2 1.1.2 1.1.4 + + Transitive Package Resolved Latest + > Microsoft.CSharp 4.0.1 4.7.0 + > Microsoft.NETCore.Platforms 1.1.0 6.0.1 + > Microsoft.NETCore.Targets 1.1.0 5.0.0 + +#### `> dotnet list package --include-transitive --outdated --framework net5.0 --format json` + +```json +{ + "version": 1, + "parameters": "-include-transitive --outdated --framework net5.0", + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "projects": { + "MyProjectA": [ + ], + "MyProjectB": [ + { + "Path": "src/lib/MyProjectB.csproj", + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0", + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4", + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "latestVersion": "4.7.0", + } + ... + ] + } + ] + } +} +``` + +#### `> dotnet list package --include-transitive --deprecated --framework net5.0` + +The following sources were used: + https://api.nuget.org/v3/index.json + https://apidev.nugettest.org/v3-index/index.json + +No packages were found for the project `MyProjectA` given the specified frameworks. +Project `MyProjectB` has the following deprecated packages + [net5.0]: + Top-level Package Requested Resolved Reason(s) Alternative + > NuGet.Core 2.13.0 2.13.0 Legacy + + Transitive Package Resolved Reason(s) Alternative + > NuGet.Packaging.Core 4.8.0-preview3.5278 Legacy NuGet.Packaging >= 0.0.0 + +#### `> dotnet list package --include-transitive --deprecated --framework net5.0 --format json` + +```json +{ + "version": 1, + "parameters": "--include-transitive --deprecated --framework net5.0", + "sources": [ + "https://api.nuget.org/v3/index.json", + "https://apidev.nugettest.org/v3-index/index.json" + ], + "projects": { + "MyProjectA": [ + ], + "MyProjectB": [ + { + "Path": "src/lib/MyProjectB.csproj", + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"] + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "deprecationReasons": ["Legacy"], + "alternativePackage": { + "id": "NuGet.Packaging", + "versionRange": "[0.0.0,)" + } + } + ... + ] + } + ] + } +} +``` + ## Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. @@ -628,32 +755,42 @@ Please note, except "tab completion" (for dotnet) part all changes would be insi * https://docs.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters One idea we can take from `dotnet counter` is we can specify output file with `-o`, `--output` option. So instead of writing output into console, it allows output directly saved into file. It allows both `csv` and `json` formats, currently saved file doesn't have version concept. +* https://github.com/NuGet/Home/wiki/Enable-repeatable-package-restore-using-lock-file It's very similar what we're doing here, and it has schema versioning. [sample](https://gist.github.com/erdembayar/4894b66bde227147b60e60997d20df41) Only major difference is json object are grouped under TFM unlike `dotnet list package` where items are grouped under projects. Below are possible takeaways. + * Direct/top level packages point to dependency packages. >> Could be included, down side is duplicate information, increase json size. Also I feel https://github.com/NuGet/Home/issues/11553 addresses this issue better, because in the end who transitive dependency brought in is more important than what dependencies exist under each top package. + * Content hash. >> It's very easy to include it, question is how about source? Related issue https://github.com/NuGet/Home/issues/11552 + +* [npm ls --json](https://gist.github.com/erdembayar/ddfbf9c160fbb8a0e31e3596f03ee906), [npm outdated -json](https://gist.github.com/erdembayar/12030f1db89ad9f2e206f2b6ff7d740f) Actually it's less sophisticated than what we have, because it doesn't have multi TFM and projects concept. + ## Unresolved Questions * Donnie: When I want to create archival records, will I want something more unique than the project name? Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github.com/NuGet/Home/pull/11446#discussion_r766920783) - * `name/relative path to solution` could be solution here. + >> `path property` could be solution here, see proposal. * Donnie: How can we record in the output that --include-transitive wasn't used here? In other words, if I look at this output years from now, how would I know whether any transitives were in this project? [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390) - * packages.lock.json format could be used here. + >> We could include options and parameters used here. * Loïc : How would this format evolve if we add another "package pivot" in addition to top level and transitive packages? For example, what if we add new package kinds for source generators, Roslyn analyzers, etc...? [r767026799](https://github.com/NuGet/Home/pull/11446#discussion_r767026799) >> Out of scope from MVP, this schema can evolve over time, by the time we have necessity to do change we can make more educated decision. -* Could we use existing packages.lock.json format? [sample](https://gist.github.com/erdembayar/4894b66bde227147b60e60997d20df41) - * Direct/top level packages point to dependency packages. - * Content hash. >> out of scope for now. Tracking issue https://github.com/NuGet/Home/issues/11552 - ## Future Possibilities +If we address them in plain `dotnet list package` then we'll address in `json output` too. + +* Include source info for all options. https://github.com/NuGet/Home/issues/11556 + +* Include hash + source for package, because same package ID+version might have different hash. It can be used to detect [dependency confusion attack](https://github.com/NuGet/Home/pull/11446#discussion_r767030495), tracking issue: https://github.com/NuGet/Home/issues/11552 + +* Include hash for each package, sub issue of above. This's low hanging fruit I can include it. + +* Some outputs include source info. Maybe we should include package source mapping info into sources, tracking issue https://github.com/NuGet/Home/issues/11557 + * Show resolution tree for transitive dependencies and constraint for dependency [resolved version](https://github.com/NuGet/Home/pull/11446/files#r777233006), tracking issue: https://github.com/NuGet/Home/issues/11553 -* Return different exit codes if any vulnerabilities, deprecations, outdated package is [detected](https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit-exit-codes). +* Include-transitive dependencies by default [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390), workaround pass `--include-transitive`, tracking issue https://github.com/NuGet/Home/issues/11550 * `--all` option for dotnet list package [r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629), tracking issue https://github.com/NuGet/Home/issues/11551 -* Include-transitive dependencies by default [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390), tracking issue https://github.com/NuGet/Home/issues/11550 - -* Include hash + source for package, because same package ID+version might have different hash. It can be used to detect [dependency confusion attack](https://github.com/NuGet/Home/pull/11446#discussion_r767030495), tracking issue: https://github.com/NuGet/Home/issues/11552 \ No newline at end of file +* Return different exit codes if any vulnerabilities, deprecations, outdated package is [detected](https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit-exit-codes). \ No newline at end of file From e71dd72f7beb50a96ccf52ca81f05903e8882706 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Wed, 2 Feb 2022 17:58:44 -0800 Subject: [PATCH 16/23] Address comments by Nikolche. --- proposed/2021/MachineReadableOutput.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 7b8b32c8c0..deab1273f0 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -79,7 +79,7 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { - "Path": "src/tool/MyProjectA.csproj", + "Path": "src/tool/MyProjectA.csproj", // relative to invocation directory "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -767,10 +767,6 @@ Please note, except "tab completion" (for dotnet) part all changes would be insi Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github.com/NuGet/Home/pull/11446#discussion_r766920783) >> `path property` could be solution here, see proposal. -* Donnie: How can we record in the output that --include-transitive wasn't used here? -In other words, if I look at this output years from now, how would I know whether any transitives were in this project? [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390) - >> We could include options and parameters used here. - * Loïc : How would this format evolve if we add another "package pivot" in addition to top level and transitive packages? For example, what if we add new package kinds for source generators, Roslyn analyzers, etc...? [r767026799](https://github.com/NuGet/Home/pull/11446#discussion_r767026799) >> Out of scope from MVP, this schema can evolve over time, by the time we have necessity to do change we can make more educated decision. From 236de549eb10dc5c1115963541997435577699bd Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Thu, 3 Feb 2022 12:09:04 -0800 Subject: [PATCH 17/23] Created issue Path property proposal, address separately. --- proposed/2021/MachineReadableOutput.md | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index deab1273f0..5ab639d1c7 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -79,7 +79,6 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { - "Path": "src/tool/MyProjectA.csproj", // relative to invocation directory "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -102,7 +101,6 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -118,7 +116,6 @@ Project 'MyProjectB' has the following package references ] }, { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -178,7 +175,6 @@ Project `MyProjectB` has the following updates to its packages "projects": { "MyProjectA": [ { - "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -204,7 +200,6 @@ Project `MyProjectB` has the following updates to its packages ], "MyProjectB": [ { - "Path": "src/tool/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -222,7 +217,6 @@ Project `MyProjectB` has the following updates to its packages ] }, { - "Path": "src/tool/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -281,7 +275,6 @@ Project `MyProjectB` has the following deprecated packages "MyProjectA": [ { - "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -305,7 +298,6 @@ Project `MyProjectB` has the following deprecated packages ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -317,7 +309,6 @@ Project `MyProjectB` has the following deprecated packages ] }, { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -390,7 +381,6 @@ Project `MyProjectB` has the following vulnerable packages "projects": { "MyProjectA": [ { - "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -414,7 +404,6 @@ Project `MyProjectB` has the following vulnerable packages ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -436,7 +425,6 @@ Project `MyProjectB` has the following vulnerable packages ] }, { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -513,7 +501,6 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { - "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -547,7 +534,6 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -574,7 +560,6 @@ Project 'MyProjectB' has the following package references ] }, { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -639,7 +624,6 @@ Project `MyProjectB` has the following updates to its packages ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -699,7 +683,6 @@ Project `MyProjectB` has the following deprecated packages ], "MyProjectB": [ { - "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -781,6 +764,8 @@ If we address them in plain `dotnet list package` then we'll address in `json ou * Include hash for each package, sub issue of above. This's low hanging fruit I can include it. +* Include [path info](https://github.com/NuGet/Home/pull/11446#discussion_r798509892) for project (either relative to current working dir or relative to solution): tracking issue: https://github.com/NuGet/Home/issues/11562 + * Some outputs include source info. Maybe we should include package source mapping info into sources, tracking issue https://github.com/NuGet/Home/issues/11557 * Show resolution tree for transitive dependencies and constraint for dependency [resolved version](https://github.com/NuGet/Home/pull/11446/files#r777233006), tracking issue: https://github.com/NuGet/Home/issues/11553 From 6abd4e6380e4ac9aebcb392518e5ee1494579928 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Thu, 3 Feb 2022 16:54:54 -0800 Subject: [PATCH 18/23] Remove unanswered question part. --- proposed/2021/MachineReadableOutput.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 5ab639d1c7..795bb496c3 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -744,16 +744,6 @@ Please note, except "tab completion" (for dotnet) part all changes would be insi * [npm ls --json](https://gist.github.com/erdembayar/ddfbf9c160fbb8a0e31e3596f03ee906), [npm outdated -json](https://gist.github.com/erdembayar/12030f1db89ad9f2e206f2b6ff7d740f) Actually it's less sophisticated than what we have, because it doesn't have multi TFM and projects concept. -## Unresolved Questions - -* Donnie: When I want to create archival records, will I want something more unique than the project name? -Adding the path, repo, commit ID, etc seems complex. [r766920783](https://github.com/NuGet/Home/pull/11446#discussion_r766920783) - >> `path property` could be solution here, see proposal. - -* Loïc : How would this format evolve if we add another "package pivot" in addition to top level and transitive packages? For example, what if we add new package kinds for source generators, Roslyn analyzers, etc...? [r767026799](https://github.com/NuGet/Home/pull/11446#discussion_r767026799) - ->> Out of scope from MVP, this schema can evolve over time, by the time we have necessity to do change we can make more educated decision. - ## Future Possibilities If we address them in plain `dotnet list package` then we'll address in `json output` too. From 3db7a73ebdb8292ec6401ff1ed77b19f99c002f7 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Thu, 3 Feb 2022 17:29:53 -0800 Subject: [PATCH 19/23] Revert "Created issue Path property proposal, address separately." This reverts commit 236de549eb10dc5c1115963541997435577699bd. --- proposed/2021/MachineReadableOutput.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 795bb496c3..1c964268f7 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -79,6 +79,7 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", // relative to invocation directory "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -101,6 +102,7 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -116,6 +118,7 @@ Project 'MyProjectB' has the following package references ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -175,6 +178,7 @@ Project `MyProjectB` has the following updates to its packages "projects": { "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -200,6 +204,7 @@ Project `MyProjectB` has the following updates to its packages ], "MyProjectB": [ { + "Path": "src/tool/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -217,6 +222,7 @@ Project `MyProjectB` has the following updates to its packages ] }, { + "Path": "src/tool/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -275,6 +281,7 @@ Project `MyProjectB` has the following deprecated packages "MyProjectA": [ { + "Path": "src/tool/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -298,6 +305,7 @@ Project `MyProjectB` has the following deprecated packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -309,6 +317,7 @@ Project `MyProjectB` has the following deprecated packages ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -381,6 +390,7 @@ Project `MyProjectB` has the following vulnerable packages "projects": { "MyProjectA": [ { + "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -404,6 +414,7 @@ Project `MyProjectB` has the following vulnerable packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -425,6 +436,7 @@ Project `MyProjectB` has the following vulnerable packages ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -501,6 +513,7 @@ Project 'MyProjectB' has the following package references "projects": { "MyProjectA": [ { + "Path": "src/lib/MyProjectA.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -534,6 +547,7 @@ Project 'MyProjectB' has the following package references ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "netcoreapp3.1", "topLevelPackages": [ { @@ -560,6 +574,7 @@ Project 'MyProjectB' has the following package references ] }, { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -624,6 +639,7 @@ Project `MyProjectB` has the following updates to its packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -683,6 +699,7 @@ Project `MyProjectB` has the following deprecated packages ], "MyProjectB": [ { + "Path": "src/lib/MyProjectB.csproj", "framework": "net5.0", "topLevelPackages": [ { @@ -754,8 +771,6 @@ If we address them in plain `dotnet list package` then we'll address in `json ou * Include hash for each package, sub issue of above. This's low hanging fruit I can include it. -* Include [path info](https://github.com/NuGet/Home/pull/11446#discussion_r798509892) for project (either relative to current working dir or relative to solution): tracking issue: https://github.com/NuGet/Home/issues/11562 - * Some outputs include source info. Maybe we should include package source mapping info into sources, tracking issue https://github.com/NuGet/Home/issues/11557 * Show resolution tree for transitive dependencies and constraint for dependency [resolved version](https://github.com/NuGet/Home/pull/11446/files#r777233006), tracking issue: https://github.com/NuGet/Home/issues/11553 From a23955149092f7b94354ced79060b466fb6af5b3 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Thu, 3 Feb 2022 18:38:56 -0800 Subject: [PATCH 20/23] Address comment resolution made offline. --- proposed/2021/MachineReadableOutput.md | 833 +++++++++++++------------ 1 file changed, 429 insertions(+), 404 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index 1c964268f7..b7bc1e597c 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -44,7 +44,7 @@ dotnet list [|] package [--config ] [--outdated] [--source ] [-v|--verbosity ] [--vulnerable] [--format ] - + [--output-version ] dotnet list package -h|--help ``` @@ -76,65 +76,68 @@ Project 'MyProjectB' has the following package references { "version": 1, "parameters": "", - "projects": { - "MyProjectA": [ - { - "Path": "src/tool/MyProjectA.csproj", // relative to invocation directory - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ] - } - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ] - }, - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ] + } + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ] + } + ] + } + ] } ``` @@ -175,72 +178,75 @@ Project `MyProjectB` has the following updates to its packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "projects": { - "MyProjectA": [ - { - "Path": "src/tool/MyProjectA.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0", - "latestVersion": "6.0.0", - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0", - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - } - ], - "MyProjectB": [ - { - "Path": "src/tool/MyProjectB.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - }, - { - "Path": "src/tool/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4" - } - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0", + "latestVersion": "6.0.0", + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0", + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4" + } + ] + } + ] + } + ] } ``` @@ -277,59 +283,61 @@ Project `MyProjectB` has the following deprecated packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "projects": { - - "MyProjectA": [ - { - "Path": "src/tool/MyProjectA.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "EntityFramework.MappingAPI", - "requestedVersion": "*", - "resolvedVersion": "6.2.1", - "deprecationReasons": ["Legacy"], - "alternativePackage": { - "id": "Z.EntityFramework.Extensions", - "versionRange": "[0.0.0,)" - } - }, - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - } - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - }, - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"], - } - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "EntityFramework.MappingAPI", + "requestedVersion": "*", + "resolvedVersion": "6.2.1", + "deprecationReasons": ["Legacy"], + "alternativePackage": { + "id": "Z.EntityFramework.Extensions", + "versionRange": "[0.0.0,)" + } + }, + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], + } + ] + } + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"], + } + ] + } + ] + } + ] } ``` @@ -387,78 +395,81 @@ Project `MyProjectB` has the following vulnerable packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "projects": { - "MyProjectA": [ - { - "Path": "src/lib/MyProjectA.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ] - } - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + } + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ] - }, - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "DotNetNuke.Core", - "requestedVersion": "6.0.0", - "resolvedVersion": "6.0.0", - "vulnerabilities" : [ - { - "severity":"High", - "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" - }, + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ { - "severity":"Moderate", - "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" - }, - ... - ] - } - ] - } - ] - } + "id": "DotNetNuke.Core", + "requestedVersion": "6.0.0", + "resolvedVersion": "6.0.0", + "vulnerabilities" : [ + { + "severity":"High", + "advisoryurl":"https://github.com/advisories/GHSA-g8j6-m4p7-5rfq" + }, + { + "severity":"Moderate", + "advisoryurl":"https://github.com/advisories/GHSA-v76m-f5cx-8rg4" + }, + ... + ] + } + ] + } + ] + } + ] } ``` @@ -510,98 +521,101 @@ Project 'MyProjectB' has the following package references { "version": 1, "parameters": "--include-transitive", - "projects": { - "MyProjectA": [ - { - "Path": "src/lib/MyProjectA.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "Microsoft.Extensions.Primitives", - "requestedVersion": "[1.0.0, 5.0.0]", - "resolvedVersion": "1.0.0" - }, - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "[1.1.2, 2.0.0)", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, - ... - ] - } - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "netcoreapp3.1", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, - ... - ] - }, - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278" - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2" - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1" - }, - { - "id": "Microsoft.NETCore.Platforms", - "resolvedVersion": "1.1.0" - }, - ... - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "Microsoft.Extensions.Primitives", + "requestedVersion": "[1.0.0, 5.0.0]", + "resolvedVersion": "1.0.0" + }, + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "[1.1.2, 2.0.0)", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + } + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "netcoreapp3.1", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + }, + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278" + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2" + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1" + }, + { + "id": "Microsoft.NETCore.Platforms", + "resolvedVersion": "1.1.0" + }, + ... + ] + } + ] + } + ] } ``` @@ -634,38 +648,43 @@ Project `MyProjectB` has the following updates to its packages "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "projects": { - "MyProjectA": [ - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Commands", - "requestedVersion": "4.8.0-preview3.5278", - "resolvedVersion": "4.8.0-preview3.5278", - "latestVersion": "6.0.0", - }, - { - "id": "Text2Xml.Lib", - "requestedVersion": "1.1.2", - "resolvedVersion": "1.1.2", - "latestVersion": "1.1.4", - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1", - "latestVersion": "4.7.0", - } - ... - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Commands", + "requestedVersion": "4.8.0-preview3.5278", + "resolvedVersion": "4.8.0-preview3.5278", + "latestVersion": "6.0.0", + }, + { + "id": "Text2Xml.Lib", + "requestedVersion": "1.1.2", + "resolvedVersion": "1.1.2", + "latestVersion": "1.1.4", + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "latestVersion": "4.7.0", + } + ... + ] + } + ] + } + ] } ``` @@ -689,47 +708,53 @@ Project `MyProjectB` has the following deprecated packages ```json { "version": 1, - "parameters": "--include-transitive --deprecated --framework net5.0", + "parameters": "-include-transitive --outdated --framework net5.0", "sources": [ "https://api.nuget.org/v3/index.json", "https://apidev.nugettest.org/v3-index/index.json" ], - "projects": { - "MyProjectA": [ - ], - "MyProjectB": [ - { - "Path": "src/lib/MyProjectB.csproj", - "framework": "net5.0", - "topLevelPackages": [ - { - "id": "NuGet.Core", - "requestedVersion": "2.13.0", - "resolvedVersion": "2.13.0", - "deprecationReasons": ["Legacy"] - } - ], - "transitivePackages": [ - { - "id": "Microsoft.CSharp", - "resolvedVersion": "4.0.1", - "deprecationReasons": ["Legacy"], - "alternativePackage": { - "id": "NuGet.Packaging", - "versionRange": "[0.0.0,)" - } - } - ... - ] - } - ] - } + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + "frameworks": [ + ] + }, + { + "path": "src/lib/MyProjectB.csproj", + "frameworks": [ + { + "framework": "net5.0", + "topLevelPackages": [ + { + "id": "NuGet.Core", + "requestedVersion": "2.13.0", + "resolvedVersion": "2.13.0", + "deprecationReasons": ["Legacy"] + } + ], + "transitivePackages": [ + { + "id": "Microsoft.CSharp", + "resolvedVersion": "4.0.1", + "deprecationReasons": ["Legacy"], + "alternativePackage": { + "id": "NuGet.Packaging", + "versionRange": "[0.0.0,)" + } + } + ... + ] + } + ] + } + ] } ``` ## Compatibility - We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. +We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. +By default `--format json` will output latest schema version of json, but we can set older version of output like `--output-version 1`, intention behind is we don't want to customer CI build script because sdk/nuget version is upgraded and keep it predictable. ## Out-of-scope From 50583f268bda76413103ab31fa26387693caf39b Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Wed, 23 Feb 2022 08:02:23 -0800 Subject: [PATCH 21/23] Address PR comment by Chet. --- proposed/2021/MachineReadableOutput.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index b7bc1e597c..dd17e57f6c 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -622,6 +622,7 @@ Project 'MyProjectB' has the following package references #### `> dotnet list package --include-transitive --outdated --framework net5.0` +```dotnetcli The following sources were used: https://api.nuget.org/v3/index.json https://apidev.nugettest.org/v3-index/index.json @@ -637,6 +638,7 @@ Project `MyProjectB` has the following updates to its packages > Microsoft.CSharp 4.0.1 4.7.0 > Microsoft.NETCore.Platforms 1.1.0 6.0.1 > Microsoft.NETCore.Targets 1.1.0 5.0.0 +``` #### `> dotnet list package --include-transitive --outdated --framework net5.0 --format json` @@ -690,6 +692,7 @@ Project `MyProjectB` has the following updates to its packages #### `> dotnet list package --include-transitive --deprecated --framework net5.0` +```dotnetcli The following sources were used: https://api.nuget.org/v3/index.json https://apidev.nugettest.org/v3-index/index.json @@ -702,6 +705,7 @@ Project `MyProjectB` has the following deprecated packages Transitive Package Resolved Reason(s) Alternative > NuGet.Packaging.Core 4.8.0-preview3.5278 Legacy NuGet.Packaging >= 0.0.0 +``` #### `> dotnet list package --include-transitive --deprecated --framework net5.0 --format json` From 64189aec8c811d0850dfebaf5f8910622760ec6d Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Wed, 23 Feb 2022 08:31:57 -0800 Subject: [PATCH 22/23] Address comment --- proposed/2021/MachineReadableOutput.md | 40 +++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2021/MachineReadableOutput.md index dd17e57f6c..7e2b62d5b2 100644 --- a/proposed/2021/MachineReadableOutput.md +++ b/proposed/2021/MachineReadableOutput.md @@ -34,7 +34,7 @@ Anyone (government/private enterprises, security experts, individual contributor #### `--format` option -Ability to use new `--format` option for all `dotnet list package` commands to ensure formatted(json, text, csv etc) output is emitted to the console. +Ability to use new `--format` option for all `dotnet list package` commands to ensure formatted(json, text) output is emitted to the console. ```dotnetcli dotnet list [|] package [--config ] @@ -755,6 +755,23 @@ Project `MyProjectB` has the following deprecated packages } ``` +#### `> dotnet list package --format json --output-version 1` + +Outputs json for format version 1, if it's not specified then latest version'll be used by default. + +```json +{ + "version": 1, + "parameters": "", + "projects": [ + { + "path": "src/lib/MyProjectA.csproj", + ... + } + ] +} +``` + ## Compatibility We start with `version 1`, as long as we don't remove or rename then it'll be backward compatible. In case [we change version](https://stackoverflow.com/a/13945074) just add new properties, keep old ones even it's not used. @@ -762,10 +779,9 @@ By default `--format json` will output latest schema version of json, but we can ## Out-of-scope -* We won't support saving the machine-readable output to disk as part of this spec. The work-around is for the consumer to read from the console's stdout stream. -* At this point, no other CLI commands (e.g. dotnet list reference) will be within scope for this feature. -"--parsable" option needs separate spec. -* Currently license info is not emitted from any cli command, it could be quite useful, we should consider in the future. +* Saving the output to disk. +* Any other additions, such as --parsable. +* Include license information [#11563)](https://github.com/NuGet/Home/issues/11563). ## Rationale and alternatives Currently, no other `dotnet command` implemented this, this is the 1st time dotnet command implementing `json`(etc) output, so it could become example for others next time they implement. @@ -794,18 +810,16 @@ Please note, except "tab completion" (for dotnet) part all changes would be insi If we address them in plain `dotnet list package` then we'll address in `json output` too. -* Include source info for all options. https://github.com/NuGet/Home/issues/11556 - -* Include hash + source for package, because same package ID+version might have different hash. It can be used to detect [dependency confusion attack](https://github.com/NuGet/Home/pull/11446#discussion_r767030495), tracking issue: https://github.com/NuGet/Home/issues/11552 +* [Include source info for all options](https://github.com/NuGet/Home/issues/11556). -* Include hash for each package, sub issue of above. This's low hanging fruit I can include it. +* [Include hash + source for package](https://github.com/NuGet/Home/issues/11552), because same package ID+version might have different hash. It can be used to detect dependency confusion attack. Please note existing feature `lock files` is more appropriate for this. -* Some outputs include source info. Maybe we should include package source mapping info into sources, tracking issue https://github.com/NuGet/Home/issues/11557 +* [Some outputs include source info](https://github.com/NuGet/Home/issues/11557). Maybe we should include package source mapping info into sources. -* Show resolution tree for transitive dependencies and constraint for dependency [resolved version](https://github.com/NuGet/Home/pull/11446/files#r777233006), tracking issue: https://github.com/NuGet/Home/issues/11553 +* [Show resolution tree for transitive dependencies](https://github.com/NuGet/Home/issues/11553) and constraint for dependency resolved version. -* Include-transitive dependencies by default [r766924390](https://github.com/NuGet/Home/pull/11446#discussion_r766924390), workaround pass `--include-transitive`, tracking issue https://github.com/NuGet/Home/issues/11550 +* [Include-transitive dependencies](https://github.com/NuGet/Home/issues/11550) by default, workaround pass `--include-transitive`. -* `--all` option for dotnet list package [r766860629](https://github.com/NuGet/Home/pull/11446#discussion_r766860629), tracking issue https://github.com/NuGet/Home/issues/11551 +* [--all option](https://github.com/NuGet/Home/issues/11551) for dotnet list package. * Return different exit codes if any vulnerabilities, deprecations, outdated package is [detected](https://github.com/NuGet/Home/blob/dotnet-audit/proposed/2021/DotNetAudit.md#dotnet-audit-exit-codes). \ No newline at end of file From fc6a7376bcaf69a5e69ac1c093ee748dd7bd8864 Mon Sep 17 00:00:00 2001 From: Erick Yondon Date: Wed, 23 Feb 2022 14:50:38 -0800 Subject: [PATCH 23/23] Rename file and move to 2022. --- .../DotnetListPackageMachineReadableJsonOutput.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposed/{2021/MachineReadableOutput.md => 2022/DotnetListPackageMachineReadableJsonOutput.md} (100%) diff --git a/proposed/2021/MachineReadableOutput.md b/proposed/2022/DotnetListPackageMachineReadableJsonOutput.md similarity index 100% rename from proposed/2021/MachineReadableOutput.md rename to proposed/2022/DotnetListPackageMachineReadableJsonOutput.md