PanoramicData.NugetManagement
1.0.160
dotnet add package PanoramicData.NugetManagement --version 1.0.160
NuGet\Install-Package PanoramicData.NugetManagement -Version 1.0.160
<PackageReference Include="PanoramicData.NugetManagement" Version="1.0.160" />
<PackageVersion Include="PanoramicData.NugetManagement" Version="1.0.160" />
<PackageReference Include="PanoramicData.NugetManagement" />
paket add PanoramicData.NugetManagement --version 1.0.160
#r "nuget: PanoramicData.NugetManagement, 1.0.160"
#:package PanoramicData.NugetManagement@1.0.160
#addin nuget:?package=PanoramicData.NugetManagement&version=1.0.160
#tool nuget:?package=PanoramicData.NugetManagement&version=1.0.160
PanoramicData.NugetManagement
Opinionated assessment of NuGet packages in a GitHub organization for best practices compliance.
Overview
PanoramicData.NugetManagement connects to a GitHub organization, examines each repository, and evaluates it against a comprehensive set of opinionated best practice rules covering:
- CI/CD — CI workflow structure, checkout depth, action versions
- Versioning — Nerdbank.GitVersioning, global.json SDK pinning
- Central Package Management — CPM enabled, no inline versions
- NuGet Hygiene — snupkg symbols, GeneratePackageOnBuild, PackageReadmeFile
- Target Framework — Latest .NET version
- Build Quality — TreatWarningsAsErrors, Nullable, ImplicitUsings
- Code Quality — .editorconfig, file-scoped namespaces, Codacy, CodeQL
- Testing — Test project existence, xUnit v3, Microsoft.Testing.Platform test runner, code coverage
- Serialization — System.Text.Json preferred over Newtonsoft
- HTTP Clients — Refit preferred
- Licensing — MIT LICENSE, PackageLicenseExpression, Copyright
- README & Badges — Codacy, NuGet, License badges
- Repository Hygiene — .gitignore, NeutralResourcesLanguage
- Project Metadata — PackageId, RepositoryUrl, Authors, PackageIcon
- Community Health — SECURITY.md, CONTRIBUTING.md
- Dependency Automation — Dependabot or Renovate
Installation
dotnet add package PanoramicData.NugetManagement
Quick Start
using Octokit;
using Microsoft.Extensions.Logging;
using PanoramicData.NugetManagement.Models;
using PanoramicData.NugetManagement.Services;
// Create an authenticated GitHub client
var github = new GitHubClient(new ProductHeaderValue("MyApp"))
{
Credentials = new Credentials("your-github-token")
};
// Configure assessment options
var options = new AssessmentOptions
{
OrganizationName = "your-org",
RepositoryOptions = new Dictionary<string, RepoOptions>
{
["legacy-repo"] = new() { Exclude = true },
["web-app"] = new() { IsPackable = false }
}
};
// Run the assessment
using var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
var assessor = new OrganizationAssessor(
github,
loggerFactory.CreateLogger<OrganizationAssessor>(),
loggerFactory.CreateLogger<RepositoryContextBuilder>());
var result = await assessor.AssessAsync(options);
// Report results
Console.WriteLine($"Organization: {result.OrganizationName}");
Console.WriteLine($"Repositories: {result.RepositoryCount}");
Console.WriteLine($"Compliant: {result.CompliantCount}");
Console.WriteLine($"Non-compliant: {result.NonCompliantCount}");
foreach (var repo in result.RepositoryAssessments)
{
Console.WriteLine($"\n{repo.RepositoryFullName}: {repo.PassedCount}/{repo.RuleResults.Count} passed");
foreach (var failure in repo.RuleResults.Where(r => !r.Passed))
{
Console.WriteLine($" [{failure.Severity}] {failure.RuleId}: {failure.Message}");
if (failure.Remediation is not null)
{
Console.WriteLine($" Fix: {failure.Remediation}");
}
}
}
Running the web dashboard locally
The repository also contains PanoramicData.NugetManagement.Web, a Blazor dashboard for
assessing and remediating an organisation's repositories. It needs configuration before it will
start usefully: appsettings.json ships with empty values, and nothing below has a default that
works out of the box.
Settings are read from configuration, so supply them however you prefer. For local development use user secrets — they live outside the repository, so they cannot be committed by accident. All commands below are run from the repository root:
dotnet user-secrets set "AppSettings:GitHubOrganization" "your-github-org" --project PanoramicData.NugetManagement.Web
dotnet user-secrets set "AppSettings:NuGetOrganization" "your-nuget-org" --project PanoramicData.NugetManagement.Web
Signing in
The dashboard authenticates with GitHub OAuth, so it needs an OAuth app. Register one at
Settings → Developer settings → OAuth Apps on GitHub. The default launch profile serves
http://localhost:5023, so the callback URL is http://localhost:5023/signin-github. Sign-in
requests the repo and read:org scopes. Then:
dotnet user-secrets set "AppSettings:GitHubClientId" "..." --project PanoramicData.NugetManagement.Web
dotnet user-secrets set "AppSettings:GitHubClientSecret" "..." --project PanoramicData.NugetManagement.Web
If you would rather not register an OAuth app, development can bypass sign-in entirely. This is
double-gated — it only takes effect when the environment is Development and the setting is
on, so it can never apply in production:
dotnet user-secrets set "AppSettings:DevAuthBypass" "true" --project PanoramicData.NugetManagement.Web
# optional, defaults to "dev"
dotnet user-secrets set "AppSettings:DevAuthUser" "your-github-username" --project PanoramicData.NugetManagement.Web
Recommended settings
| Setting | Why you want it |
|---|---|
AppSettings:GitHubPat |
A personal access token covering the same ground as the OAuth scopes above (repo, read:org). Without one, assessing more than a handful of repositories exhausts GitHub's unauthenticated rate limit. When DevAuthBypass is on, this is also used as the access token, so the dashboard can reach GitHub without signing in. |
AppSettings:LocalReposRoot |
The folder your repositories are cloned into. Required before the dashboard can clone, build, test, auto-fix or publish anything — without it only read-only assessment works. This one can also be set from the dashboard's own settings page, which overrides the configured value. |
AppSettings:CodacyApiToken |
Enables the Codacy issue rule (CQ-05). Without it that rule reports as not applicable. |
Then run it:
dotnet run --project PanoramicData.NugetManagement.Web
Running the tests
Most tests need nothing, but the live GitHub integration tests need a token. Without one they skip
with an explanatory message — and because this project sets failSkips: true (skipped tests are
treated as failures, so nothing can hide behind a Skip), a token is required for a green
suite:
dotnet user-secrets set "GitHub:Token" (Read-Host) --project PanoramicData.NugetManagement.Test
That is PowerShell: typing the value at the Read-Host prompt keeps it out of your shell history,
which is worth doing since history files are stored in plain text. In other shells, pass the token
as the final argument instead.
Alternatively set the GitHub__Token environment variable, which takes precedence over user
secrets. That is how to supply it in CI, since build agents have no user secrets.
These tests spend your GitHub API budget
The integration tests call the live GitHub API, so they draw on the same hourly rate limit (5,000 requests for an authenticated user) as everything else that token does. Two consequences are worth knowing before they catch you out:
- Reusing one token for the dashboard and the tests makes them compete. The limit is per token, not per application, so assessing the organisation in the dashboard and running the suite eat from the same allowance. Repeated full runs of both in one hour can exhaust it. Giving the tests their own token keeps the two budgets separate.
- Exhausting it looks like broken tests, not a spent budget. The failure surfaces as
Octokit.RateLimitExceededException, and becausefailSkips: truetreats skips as failures, there is no gentle degradation — the suite simply goes red. If integration tests fail while everything else passes, check the exception before hunting for a regression: it resolves itself when the window resets, on the hour from your first request.
The dashboard shows the remaining budget in its breadcrumb bar and warns before an action that would consume a large share of it, but that reflects the token the application uses — the test token's budget is separate and not shown there.
For scale: assessing one repository costs about two API requests. File contents are fetched from
raw.githubusercontent.com, which is a CDN and does not count against the limit, and repositories
already cloned locally are assessed from disk at no API cost at all.
Per-Repository Options
var repoOptions = new RepoOptions
{
Exclude = false, // Set true to skip entirely
IsPackable = true, // Set false for apps/tools (skips NuGet rules)
EnforceRequiredProperties = true, // Configurable 'required' keyword enforcement
SuppressedRules = ["HTTP-01"] // Suppress specific rules by ID
};
Available Rules
Use RuleRegistry.Rules to enumerate all discovered rules at runtime.
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Codacy.Api (>= 3.0.35)
- Microsoft.Extensions.Configuration (>= 10.0.11)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.11)
- Microsoft.Extensions.DependencyInjection (>= 10.0.11)
- Microsoft.Extensions.Logging (>= 10.0.11)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.11)
- Microsoft.Extensions.Options (>= 10.0.11)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.11)
- Newtonsoft.Json (>= 13.0.4)
- NuGet.Protocol (>= 7.9.0)
- Octokit (>= 14.0.0)
- Refit (>= 15.2.0)
- Refit.HttpClientFactory (>= 15.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.160 | 200 | 8/28/2026 |
| 1.0.60 | 240 | 4/17/2026 |
| 1.0.59 | 109 | 4/17/2026 |
| 1.0.58 | 149 | 4/16/2026 |
| 1.0.55 | 129 | 4/16/2026 |
| 1.0.54 | 120 | 4/16/2026 |
| 1.0.40 | 127 | 4/9/2026 |
| 1.0.23 | 140 | 4/3/2026 |
| 1.0.12 | 127 | 4/3/2026 |
| 1.0.9 | 122 | 4/3/2026 |
| 1.0.8 | 127 | 4/2/2026 |
| 1.0.7 | 126 | 3/31/2026 |
| 1.0.6-gac22da8522 | 118 | 3/31/2026 |