From 80734c17baade6bd0d611ed3808e4d383ca6fa97 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:45:46 -0300 Subject: [PATCH 1/3] Use upper-bound version ranges for sibling package dependencies 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 --- Directory.Packages.props | 41 +++++++++++++++---- .../src/Microsoft.Data.SqlClient.csproj | 10 ++++- .../src/Microsoft.Data.SqlClient.nuspec | 30 +++++++------- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a74caf225a..5aece05a0a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,6 +40,31 @@ false + + + + 6.0.2 + [$(SniVersion), $(SniVersion.Split('.')[0]).$([MSBuild]::Add($(SniVersion.Split('.')[1]), 1)).0) + + + + $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0 + $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0 + $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0 + $(SqlClientPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Split('.')[1]), 1)).0 + $(AzurePackageVersion.Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Split('.')[1]), 1)).0 + $(AkvProviderPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Split('.')[1]), 1)).0 + + @@ -47,22 +72,22 @@ + Version="[$(SqlServerPackageVersion), $(SqlServerVersionCeiling))" /> + Version="[$(LoggingPackageVersion), $(LoggingVersionCeiling))" /> + Version="[$(AbstractionsPackageVersion), $(AbstractionsVersionCeiling))" /> + Version="[$(SqlClientPackageVersion), $(SqlClientVersionCeiling))" /> + Version="[$(AzurePackageVersion), $(AzureVersionCeiling))" /> + Version="[$(AkvProviderPackageVersion), $(AkvProviderVersionCeiling))" /> @@ -108,8 +133,8 @@ - - + + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj index e9b3ad2741..108e1b6ab6 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj @@ -207,9 +207,15 @@ - + - <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$SqlServerPackageVersion$','$(SqlServerPackageVersion)')) + + <_AbstractionsVersionRange>[$(AbstractionsPackageVersion), $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0) + <_LoggingVersionRange>[$(LoggingPackageVersion), $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0) + <_SqlServerVersionRange>[$(SqlServerPackageVersion), $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0) + + + <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsVersionRange$','$(_AbstractionsVersionRange)').Replace('$LoggingVersionRange$','$(_LoggingVersionRange)').Replace('$SqlServerVersionRange$','$(_SqlServerVersionRange)').Replace('$SniVersionRange$','$(SniVersionRange)')) - - - + + + @@ -56,38 +56,38 @@ - - - + + + - + - - - + + + - + - - - + + + - + From 4794b4cced7e271fb26d64aa8ad7e5c56c7c08d3 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:36:43 -0300 Subject: [PATCH 2/3] CI: Pass ReferenceType and dependency versions to pack jobs 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. --- eng/pipelines/dotnet-sqlclient-ci-core.yml | 3 + .../jobs/pack-abstractions-package-ci-job.yml | 67 ++++++++++++++++--- .../jobs/pack-azure-package-ci-job.yml | 43 +++++++++--- .../build-abstractions-package-ci-stage.yml | 27 ++++++++ .../stages/build-azure-package-ci-stage.yml | 2 + 5 files changed, 123 insertions(+), 19 deletions(-) diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index f5f2269494..1d766327e8 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -164,6 +164,9 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + loggingArtifactsName: $(loggingArtifactsName) + loggingPackageVersion: $(loggingPackageVersion) + referenceType: ${{ parameters.referenceType }} # When building Abstractions via packages, we must depend on the Logging # package. ${{ if eq(parameters.referenceType, 'Package') }}: diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml index aed7672618..b83ec3d062 100644 --- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml @@ -53,6 +53,30 @@ parameters: - detailed - diagnostic + # The name of the Logging pipeline artifacts to download. + # + # This is used when the referenceType is 'Package'. + - name: loggingArtifactsName + type: string + default: Logging.Artifacts + + # The Logging package version to depend on. + # + # This is used when the referenceType is 'Package'. + - name: loggingPackageVersion + type: string + default: '' + + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + # Reference sibling packages as NuGet packages. + - Package + # Reference sibling packages as C# projects. + - Project + jobs: - job: pack_abstractions_package_job @@ -102,21 +126,46 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' + # For Package reference builds, we must first download the dependency + # package artifacts. + - ${{ if eq(parameters.referenceType, 'Package') }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Logging Package Artifacts + inputs: + artifactName: ${{ parameters.loggingArtifactsName }} + targetPath: $(Build.SourcesDirectory)/packages + # Install the .NET SDK. - template: /eng/pipelines/steps/install-dotnet.yml@self parameters: debug: ${{ parameters.debug }} # Create the NuGet packages. - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} + # + # When referenceType is Package, we must pass ReferenceType and the + # dependency version so that Directory.Packages.props applies version + # ranges to sibling package dependencies. + - ${{ if eq(parameters.referenceType, 'Package') }}: + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} + + - ${{ else }}: + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 3b03dc0adc..8aac9a98cd 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -26,12 +26,19 @@ parameters: type: string default: Logging.Artifacts - # The Abstractions package verion to depend on. + # The Abstractions package version to depend on. # # This is used when the referenceType is 'Package'. - name: abstractionsPackageVersion type: string + # The Logging package version to depend on. + # + # This is used when the referenceType is 'Package'. + - name: loggingPackageVersion + type: string + default: '' + # The name of the pipeline artifacts to publish. - name: azureArtifactsName type: string @@ -151,15 +158,31 @@ jobs: debug: ${{ parameters.debug }} # Create the NuGet packages. - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} + # + # When referenceType is Package, we must pass ReferenceType and the + # dependency versions so that Directory.Packages.props applies version + # ranges to sibling package dependencies. + - ${{ if eq(parameters.referenceType, 'Package') }}: + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} + + - ${{ else }}: + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml index 6aae1703b8..8579b79caf 100644 --- a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml +++ b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml @@ -67,6 +67,30 @@ parameters: - detailed - diagnostic + # The name of the Logging pipeline artifacts to download. + # + # This is used when the referenceType is 'Package'. + - name: loggingArtifactsName + type: string + default: Logging.Artifacts + + # The Logging package version to depend on. + # + # This is used when the referenceType is 'Package'. + - name: loggingPackageVersion + type: string + default: '' + + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + # Reference sibling packages as NuGet packages. + - Package + # Reference sibling packages as C# projects. + - Project + stages: - stage: build_abstractions_package_stage @@ -141,3 +165,6 @@ stages: - test_abstractions_package_job_windows - test_abstractions_package_job_macos dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + loggingArtifactsName: ${{ parameters.loggingArtifactsName }} + loggingPackageVersion: ${{ parameters.loggingPackageVersion }} + referenceType: ${{ parameters.referenceType }} diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml index 1da56a18ef..b3cf9073d5 100644 --- a/eng/pipelines/stages/build-azure-package-ci-stage.yml +++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml @@ -331,4 +331,6 @@ stages: - test_azure_package_job_windows_integration - test_azure_package_job_macos dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + loggingArtifactsName: ${{ parameters.loggingArtifactsName }} + loggingPackageVersion: ${{ parameters.loggingPackageVersion }} referenceType: ${{ parameters.referenceType }} From 5060f1a0195bfa9590d04555f18cb6e74efb4729 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 4 Jun 2026 12:49:23 -0300 Subject: [PATCH 3/3] Trim version properties before Split('.') in range computation 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. --- Directory.Packages.props | 12 ++++++------ .../src/Microsoft.Data.SqlClient.csproj | 9 +++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 5aece05a0a..5c25965af8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -57,12 +57,12 @@ - $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0 - $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0 - $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0 - $(SqlClientPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Split('.')[1]), 1)).0 - $(AzurePackageVersion.Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Split('.')[1]), 1)).0 - $(AkvProviderPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Split('.')[1]), 1)).0 + $(SqlServerPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Trim().Split('.')[1]), 1)).0 + $(LoggingPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Trim().Split('.')[1]), 1)).0 + $(AbstractionsPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Trim().Split('.')[1]), 1)).0 + $(SqlClientPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Trim().Split('.')[1]), 1)).0 + $(AzurePackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Trim().Split('.')[1]), 1)).0 + $(AkvProviderPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Trim().Split('.')[1]), 1)).0 diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj index 108e1b6ab6..0d25d47a9f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj @@ -209,10 +209,11 @@ - - <_AbstractionsVersionRange>[$(AbstractionsPackageVersion), $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0) - <_LoggingVersionRange>[$(LoggingPackageVersion), $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0) - <_SqlServerVersionRange>[$(SqlServerPackageVersion), $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0) + + <_AbstractionsVersionRange>[$(_AbstractionsPackageVersionTrimmed), $(_AbstractionsPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_AbstractionsPackageVersionTrimmed.Split('.')[1]), 1)).0) + <_LoggingVersionRange>[$(_LoggingPackageVersionTrimmed), $(_LoggingPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_LoggingPackageVersionTrimmed.Split('.')[1]), 1)).0) + <_SqlServerVersionRange>[$(_SqlServerPackageVersionTrimmed), $(_SqlServerPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_SqlServerPackageVersionTrimmed.Split('.')[1]), 1)).0) <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsVersionRange$','$(_AbstractionsVersionRange)').Replace('$LoggingVersionRange$','$(_LoggingVersionRange)').Replace('$SqlServerVersionRange$','$(_SqlServerVersionRange)').Replace('$SniVersionRange$','$(SniVersionRange)'))