Use upper-bound version ranges for sibling package dependencies#4337
Conversation
Compute [floor, ceiling) ranges for sibling packages so NuGet cannot resolve an incompatible newer minor/major version at restore time. - Directory.Packages.props: derive *VersionCeiling from *PackageVersion; apply ranges to sibling PackageVersion items; add SniVersionRange - SqlClient csproj: compute version range properties for nuspec expansion - SqlClient nuspec: replace bare version tokens with range tokens
There was a problem hiding this comment.
Pull request overview
This PR changes how Microsoft.Data.SqlClient expresses dependency versions by computing [floor, ceiling) version ranges (ceiling = next minor) for sibling packages and SNI, and emitting those ranges into the produced .nuspec/.nupkg.
Changes:
- Compute “next-minor” ceilings from existing
*PackageVersion/SniVersionvalues and form[floor, ceiling)ranges. - Apply those ranges in Central Package Management (
Directory.Packages.props) for sibling package dependencies (Package mode) and SNI. - Update the SqlClient pack flow to materialize dependency range tokens into the generated nuspec.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| Directory.Packages.props | Adds MSBuild-derived ceiling/range properties and applies [floor, ceiling) ranges to sibling package PackageVersions and SNI. |
| src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj | Computes version ranges during nuspec materialization and substitutes new range tokens. |
| src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec | Replaces dependency version tokens with range tokens for sibling packages and SNI. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4337 +/- ##
==========================================
- Coverage 66.50% 65.07% -1.44%
==========================================
Files 285 285
Lines 43311 66448 +23137
==========================================
+ Hits 28806 43240 +14434
- Misses 14505 23208 +8703
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The CI/PR pack jobs for Abstractions and Azure extensions were not passing ReferenceType=Package to dotnet pack, causing the projects to use ProjectReference mode for sibling dependencies. NuGet converts ProjectReferences to bare version dependencies (no ranges), which defeats the upper-bound version ranges defined in Directory.Packages.props. Fix: - pack-abstractions-package-ci-job: Add referenceType, loggingArtifactsName, and loggingPackageVersion parameters. When referenceType=Package, download Logging artifacts and pass ReferenceType + LoggingPackageVersion to dotnet pack buildProperties. - pack-azure-package-ci-job: Add loggingPackageVersion parameter. When referenceType=Package, pass ReferenceType + dependency versions to dotnet pack buildProperties. - Wire the new parameters through build-abstractions-package-ci-stage.yml and dotnet-sqlclient-ci-core.yml.
Address Copilot review feedback: guard against whitespace in version
values passed via -p: arguments by trimming before splitting.
- Directory.Packages.props: Add .Trim() before .Split('.') on all
*PackageVersion properties used in ceiling computation.
- Microsoft.Data.SqlClient.csproj: Use the already-computed
_*PackageVersionTrimmed properties as inputs to the range strings
instead of the raw *PackageVersion values.
Per review feedback on PR #4337 (cheenamalhotra + team consensus), upper-bound ceilings for sibling package dependencies now use the next major version instead of the next minor version. Example: Abstractions 1.0.0 → range [1.0.0, 2.0.0) instead of [1.0.0, 1.1.0). This aligns with SemVer semantics (minor releases must not break consumers) and follows the same pattern used by EF Core for tightly-coupled siblings.
|
Looks good. Watching this build to verify the switch to major+1: https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=155786&view=results |
|
That branch in ADO.Net was stale - new non-official run here with the latest changes: https://dev.azure.com/SqlClientDrivers/ADO.Net/_build/results?buildId=155858&view=results |
Compute
[floor, ceiling)ranges for sibling packages so NuGet cannot resolve an incompatible newer major version at restore time.Changes
*VersionCeilingfrom*PackageVersionusing MSBuild property functions; apply[floor, ceiling)ranges to all siblingPackageVersionitems; add centralizedSniVersion/SniVersionRangeproperties.$AbstractionsVersionRange$,$LoggingVersionRange$,$SqlServerVersionRange$,$SniVersionRange$).How it works
The ceiling is the next major version (prerelease suffix stripped) derived from the floor:
This is self-contained — no separate "next version" lookup is needed. The range prevents NuGet from pulling in a newer major version that could be binary-incompatible, while allowing minor/patch updates within the same major version per SemVer semantics.
This follows the same pattern used by EF Core for tightly-coupled sibling packages.
Pipeline Verification
Reviewers should inspect the NuGet package artifacts produced by the above runs to confirm that the sibling dependencies specify the expected version ranges.
Manual Verification
dotnet build(direct, net8.0/net9.0) — Project mode ✓, Package mode ✓build.proj -t:Build— Project mode ✓, Package mode ✓build.proj -t:Pack— Project mode ✓, Package mode ✓.nupkgfiles contain correct[floor, ceiling)dependency ranges for all sibling packages and SNI