The repository uses Central Package Management (CPM) to manage all NuGet package versions from a single Directory.Packages.props file located at the repository root. This provides:
- ✅ Single source of truth for all package versions
- ✅ Consistent versions across all projects
- ✅ Easier dependency updates (change once, applies everywhere)
- ✅ Reduced version conflicts
- ✅ Better security (easier to track and update vulnerable packages)
/home/runner/work/ad-blocking/ad-blocking/
├── Directory.Build.props # Global MSBuild properties
├── Directory.Packages.props # ⭐ CENTRALIZED PACKAGE VERSIONS
└── src/
├── adguard-api-dotnet/
│ └── src/
│ ├── AdGuard.ApiClient/AdGuard.ApiClient.csproj
│ ├── AdGuard.ConsoleUI/AdGuard.ConsoleUI.csproj
│ └── ... (all reference packages without versions)
└── rules-compiler-dotnet/
└── src/
└── ... (all reference packages without versions)
The root-level Directory.Packages.props file defines all package versions:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Polly" Version="8.6.5" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<!-- ... all other packages -->
</ItemGroup>
</Project>Individual projects reference packages without specifying versions:
<ItemGroup>
<!-- ✅ Correct: No Version attribute -->
<PackageReference Include="Polly" />
<PackageReference Include="Microsoft.Extensions.Logging" />
</ItemGroup>DON'T specify versions in project files:
<ItemGroup>
<!-- ❌ Wrong: Version will conflict with CPM -->
<PackageReference Include="Polly" Version="8.6.5" />
</ItemGroup>JsonSubTypes- JSON polymorphic serializationNewtonsoft.Json- JSON serializationPolly- Resilience and transient fault handling
All Microsoft.Extensions packages are standardized to version 10.0.1 (latest for .NET 10):
- Configuration (base, abstractions, JSON, environment variables, user secrets, command line)
- Dependency Injection (base, abstractions)
- Hosting
- Logging (base, abstractions, console)
- Options (base, configuration extensions)
Microsoft.EntityFrameworkCore(base)Microsoft.EntityFrameworkCore.DesignMicrosoft.EntityFrameworkCore.InMemory(testing)Microsoft.EntityFrameworkCore.SqliteMicrosoft.EntityFrameworkCore.SqlServerNpgsql.EntityFrameworkCore.PostgreSQL
Spectre.Console- Console UI framework
YamlDotNet- YAML parsingTomlyn- TOML parsing
PowerShellStandard.Library- PowerShell module development
xunit(v2.9.3) - Test frameworkxunit.runner.visualstudio(v3.1.5) - Test runnerMicrosoft.NET.Test.Sdk(v18.0.1) - Test SDKMoq(v4.20.72) - Mocking frameworkFluentAssertions(v6.12.1) - Assertion librarycoverlet.collector(v6.0.4) - Code coverage
BenchmarkDotNet(v0.15.8)BenchmarkDotNet.Diagnostics.Windows(v0.15.8)Microsoft.VisualStudio.DiagnosticsHub.BenchmarkDotNetDiagnosers(v18.0.36525.3)
-
Add version to
Directory.Packages.props:<PackageVersion Include="NewPackage" Version="1.2.3" />
-
Reference in project file (without version):
<PackageReference Include="NewPackage" />
-
Restore packages:
dotnet restore
-
Update version in
Directory.Packages.propsonly:<!-- Before --> <PackageVersion Include="Polly" Version="8.6.5" /> <!-- After --> <PackageVersion Include="Polly" Version="8.7.0" />
-
All projects automatically use the new version after restore:
dotnet restore
View all centralized package versions:
cat Directory.Packages.propsCheck what version a project is using:
dotnet list packageCause: Package is referenced in a .csproj file but not defined in Directory.Packages.props.
Solution: Add the package version to Directory.Packages.props:
<PackageVersion Include="X" Version="1.0.0" />Cause: Project file has explicit Version attribute on <PackageReference>.
Solution: Remove the Version attribute from the project file:
<!-- Before (wrong) -->
<PackageReference Include="Polly" Version="8.6.5" />
<!-- After (correct) -->
<PackageReference Include="Polly" />-
Clean the solution:
dotnet clean
-
Restore packages:
dotnet restore
-
Build again:
dotnet build
- Microsoft.Extensions packages: All should use the same version (currently 10.0.1)
- Entity Framework Core packages: All should use the same version (currently 9.0.0)
- Test packages: Keep xunit, Moq, and test SDK versions aligned
- Benchmark packages: Keep BenchmarkDotNet packages at the same version
Before: Three separate Directory.Packages.props files:
src/adguard-api-dotnet/src/Directory.Packages.propssrc/adguard-api-dotnet/src/api-client/Directory.Packages.propssrc/rules-compiler-dotnet/Directory.Packages.props
Issues:
- Duplicate definitions
- Version inconsistencies (Microsoft.Extensions: v9.0.0 vs v10.0.1)
- Some projects used explicit versions in
.csprojfiles
After: Single root-level Directory.Packages.props
- All packages centralized
- All versions consistent
- All projects reference packages without versions