Issue ID:
Type
Bug
Title:
Add pgutil packages metadata API / command
Created:
10/2/2025 1:20:40 AM by Alana Tripp
Status:
Open
Last pulled:
10/16/2025 6:01:59 AM
Description:
``` $> pgutil packages metadata --feed=myNugetFeed --package=Junk.Package --version=1.2.3 Junk.Package.Extensions.Configuration.EnvironmentVariables 1.2.3 Published : 4/30/2025 9:51:41 PM by j.smith Size : 8,927 KB Downloads : 1000 Status : Local (Deprecated) Compliance : Noncompliant (reason..) License : MIT, Apache-2.0 Vulnerabilities : PG-123456 (High) the vulnerability title of this vulnerability goes here ``` * Status would be - Package State (Local, Cached, Virtual, Remote) - Remote packages aren't supported through this API - Package Status if set (Unlisted, Deprecated, Download Blocked) * Compliance use the same description available in UI, etc One idea is to create `PackageMetadata.cs` that essentially implements `IPackageMetadata` in ProGet to make API serialization simple; we could deprecate [PackageVersionInfo.cs](https://github.com/Inedo/pgutil/blob/thousand/Inedo.ProGet/PackageVersionInfo.cs). The properties on IPackageMetadata are below; I think we'd also need to add: * Licenses Detected (array of objects based on `LicenseMan::LicenseDefinition`) * Vulnerabilities (array of objects based on `VulnerabilityMan::PackageVulnerability`) * Package Analysis (object based on `ComplianceMan::PackageAnalysisReport`) Here's a copy/paste of IPackageMetadata properties (I converted some to strings, and we need to figure out objects for PackageLicenseDeclaration, DependencyGroups, and the TitledItems. /// /// Gets a value indicating whether the allow download override is set in ProGet. /// bool? AllowOverride { get; } /// /// Gets a value indicating whether the package is deprecated. /// bool Deprecated { get; } /// /// Gets a reason the package was deprecated if is true. /// string? DeprecationReason { get; } /// /// Gets a friendly description of the package. /// string? Description { get; } /// /// Gets the number of downloads of the package. /// long? Downloads { get; } /// /// Gets the size of the package. /// long? Size { get; } /// /// Indicates whether a package is Local, Cache, or Remote /// string PackageState { get; } /// /// Gets the license declaration for the package. /// PackageLicenseDeclaration LicenseDeclaration { get; } /// /// Gets a value indicating whether the package is listed by the registry. /// bool Listed { get; } /// /// Gets the name of the package (which should include a group). /// string Name { get; } /// /// Gets the package's origin if it came from a connector. /// string? OriginUrl { get; } /// /// Gets the time when the package was published. /// DateTime? Published { get; } /// /// Gets the name of the publisher. /// string? PublishedBy { get; } /// /// Gets the used to identify the package in ProGet. /// string PUrl { get; } /// /// Gets the MD5 hash of the package if it is available. /// byte[]? MD5 { get; } /// /// Gets the SHA1 hash of the package if it is available. /// byte[]? SHA1 { get; } /// /// Gets the SHA256 hash of the package if it is available. /// byte[]? SHA256 { get; } /// /// Gets the SHA512 hash of the package if it is available. /// byte[]? SHA512 { get; } /// /// Gets the version of the package in a sortable format. /// string Version { get; } /// /// Gets any groupings of dependencies to display in ProGet. /// IReadOnlyCollection DependencyGroups { get; } /// /// Gets additional simple properties to display in ProGet. /// IReadOnlyList> DisplayProperties { get; } /// /// Gets additional block properties to display in ProGet. /// IReadOnlyList> DisplayBlocks { get; } /// /// Gets a default file name for the package if available. /// string? FileName { get; } /// /// Gets the feed-relative ProGet download url for the package. /// string DownloadUrl { get; } /// /// Gets an optional short title/description. /// string? Summary { get; } /// /// Gets an optional icon URL. /// string? IconUrl { get; } /// /// Gets the display name for the package /// /// /// Most package types do not need this; it is mainly used for types like VSIX that /// use a guid as the package name and have a separate display name. /// string DisplayName => this.Name;