From 5e42a9d1d24637f477d4f11b4c84f2e2858f04a4 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 4 May 2026 10:44:46 -0300
Subject: [PATCH 01/15] Migrate SqlClient packaging to dotnet pack
Replace nuget.exe invocation in build.proj with dotnet pack.
Add PrepareSqlClientPackNuspec target in the SqlClient csproj to
materialize dependency version tokens into an intermediate nuspec
before pack runs, working around SDK token-substitution limitations
in dependency version fields (dotnet/sdk#15482).
Pack design notes and known SDK behavior documented in
src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md.
---
build.proj | 67 ++++++++-------
.../src/Microsoft.Data.SqlClient.csproj | 35 ++++++++
.../src/sqlclient-dotnet-pack.md | 86 +++++++++++++++++++
3 files changed, 156 insertions(+), 32 deletions(-)
create mode 100644 src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
diff --git a/build.proj b/build.proj
index a0ef562934..f420613875 100644
--- a/build.proj
+++ b/build.proj
@@ -69,16 +69,6 @@
-->
-
- nuget
-
BuildSqlClient
@@ -394,7 +382,6 @@
$(SqlClientSrcRoot)tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj
- $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
$(RepoRoot)tools/GenAPI/Microsoft.DotNet.GenAPI/
$(GenApiPath)Microsoft.DotNet.GenAPI.csproj
@@ -531,10 +518,9 @@
@@ -549,10 +535,10 @@
-
+
- "$(DotnetPath)dotnet" msbuild "$(SqlClientProjectPath)"
+ "$(DotnetPath)dotnet" build "$(SqlClientProjectPath)"
-nologo
-verbosity:quiet
-getProperty:SqlClientPackageVersion
@@ -571,6 +557,10 @@
+
+
@@ -619,19 +609,32 @@
$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionAbstractions), "\s", ""))
$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionLogging), "\s", ""))
$([System.Text.RegularExpressions.Regex]::Replace($(CommitId), "\s", ""))
-
- "$(NugetPath)" pack "$(SqlClientNuspecPath)"
- -Symbols
- -SymbolPackageFormat snupkg
- -Version "$(_EvaluatedSqlClientPackageVersion)"
- -OutputDirectory "$(SqlClientArtifactRoot)/$(ReferenceType)-$(Configuration)"
- -properties "COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType);AbstractionsPackageVersion=$(PackageVersionAbstractions);LoggingPackageVersion=$(PackageVersionLogging)"
-
+
+ "$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)"
+ -p:Configuration=$(Configuration)
+ $(PackBuildArgument)
+ $(SigningKeyPathArgument)
+
+
+ $(BuildNumberArgument)
+ $(BuildSuffixArgument)
+ $(PackageVersionSqlClientArgument)
+
+
+ $(ReferenceTypeArgument)
+ $(PackageVersionAbstractionsArgument)
+ $(PackageVersionLoggingArgument)
+
+
+ -p:CommitId="$(CommitId)"
+ -p:NuspecVersion="$(_EvaluatedSqlClientPackageVersion)"
+ -p:PackageOutputPath="$(SqlClientArtifactRoot)/$(ReferenceType)-$(Configuration)"
+
- $([System.Text.RegularExpressions.Regex]::Replace($(NuGetCommand), "\s+", " "))
+ $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " "))
-
-
+
+
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index cffc9fe96f..040633d95d 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -76,6 +76,41 @@
$(ArtifactPath)$(AssemblyName)/$(ReferenceType)-$(Configuration)/$(NormalizedTargetOs)/
+
+
+
+ $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
+ $(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
+
+ $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
+ $([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
+ true
+ snupkg
+ true
+
+ COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
+
+
+
+
+
+ <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('1.0.0','$(NuspecVersion)'))
+
+
+
+
+
+ $(SqlClientPackNuspecGeneratedPath)
+
+
+
diff --git a/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
new file mode 100644
index 0000000000..1f33dec11c
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
@@ -0,0 +1,86 @@
+# SqlClient Dotnet Pack Flow
+
+This document describes how the SqlClient package is produced with dotnet pack in this branch.
+
+## Scope
+
+- Package: `Microsoft.Data.SqlClient`
+- Entry target: `PackSqlClient` in `build.proj`
+- Pack engine: `dotnet pack` (no `nuget.exe`)
+
+## How to run
+
+Run from repo root:
+
+```bash
+dotnet build build.proj -t:PackSqlClient -p:Configuration=Release -p:ReferenceType=Project -p:PackBuild=false -p:PackageVersionAbstractions= -p:PackageVersionLogging=
+```
+
+Required pack inputs:
+
+- `PackageVersionAbstractions`
+- `PackageVersionLogging`
+
+These are required because dependency versions are injected into the SqlClient nuspec at pack time.
+
+## Why a generated nuspec is used
+
+SqlClient packaging still relies on `tools/specs/Microsoft.Data.SqlClient.nuspec` for file mapping and dependency groups (`lib/*`, `ref/*`, `runtimes/*`, resources, metadata).
+
+In this flow, SDK pack token substitution is reliable for general nuspec properties, but dependency version token replacement in the nuspec dependency section can fail. To avoid that, the project generates an intermediate nuspec before `GenerateNuspec`:
+
+- Template nuspec: `tools/specs/Microsoft.Data.SqlClient.nuspec`
+- Generated nuspec: `obj/Microsoft.Data.SqlClient.pack.nuspec`
+- Replacements applied:
+ - `$AbstractionsPackageVersion$` -> `$(AbstractionsPackageVersion)`
+ - `$LoggingPackageVersion$` -> `$(LoggingPackageVersion)`
+ - `1.0.0` -> `$(NuspecVersion)`
+
+This keeps layout parity with the existing nuspec while using `dotnet pack` end-to-end.
+
+## Known SDK behavior and repro
+
+Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK `10.0.107`:
+
+```bash
+dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:NuspecFile=/tools/specs/Microsoft.Data.SqlClient.nuspec -p:NuspecBasePath=/tools/specs -p:NuspecProperties="COMMITID=abc;Configuration=Debug;ReferenceType=Project;AbstractionsPackageVersion=1.0.0-dev;LoggingPackageVersion=1.0.0-dev" -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
+```
+
+Observed error:
+
+- `An error occured while trying to parse the value '' of property 'dependencies' in the manifest file.`
+- `'' is not a valid version string.`
+
+The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by `PrepareSqlClientPackNuspec`.
+
+## Related upstream issues
+
+The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec files with `dotnet pack`:
+
+- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties` values, only first substituted and others become empty.
+- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom on SDK 6.0.404.
+- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec not filling tokens like `$version$`.
+- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty when packing with nuspec.
+- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path behavior inconsistencies with `dotnet pack`.
+
+These links do not prove this exact dependency-token timing path is identical, but they strongly indicate related substitution behavior in the same pack surface area.
+
+## Where pack properties are defined
+
+SqlClient-specific pack defaults are set in:
+
+- `src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj`
+
+The `build.proj` target passes dynamic values only:
+
+- `CommitId`
+- `NuspecVersion`
+- `PackageOutputPath`
+- plus standard version/reference-type arguments
+
+## Outputs
+
+Expected artifacts:
+
+- `artifacts/Microsoft.Data.SqlClient/-/Microsoft.Data.SqlClient..nupkg`
+- `artifacts/Microsoft.Data.SqlClient/-/Microsoft.Data.SqlClient..snupkg`
From e66ee77942fd3f6a80ad78bd8a511080e20ba1df Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 4 May 2026 11:30:44 -0300
Subject: [PATCH 02/15] Simplify SqlClient pack version flow
---
build.proj | 34 ++++---------------
.../src/Microsoft.Data.SqlClient.csproj | 1 +
2 files changed, 8 insertions(+), 27 deletions(-)
diff --git a/build.proj b/build.proj
index f420613875..66171af6ab 100644
--- a/build.proj
+++ b/build.proj
@@ -535,32 +535,10 @@
-
-
-
- "$(DotnetPath)dotnet" build "$(SqlClientProjectPath)"
- -nologo
- -verbosity:quiet
- -getProperty:SqlClientPackageVersion
-
-
- $(BuildNumberArgument)
- $(BuildSuffixArgument)
- $(PackageVersionSqlClientArgument)
-
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GetSqlClientPackageVersionCommand), "\s+", " "))
-
-
-
-
-
-
-
-
+
+
@@ -605,9 +583,12 @@
Condition="'$(PackageVersionLogging)' == ''" />
+<<<<<<< HEAD
<_EvaluatedSqlClientPackageVersion>$([System.Text.RegularExpressions.Regex]::Replace($(_EvaluatedSqlClientPackageVersion), "\s", ""))
$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionAbstractions), "\s", ""))
$([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionLogging), "\s", ""))
+=======
+>>>>>>> a31e7e8fc (Simplify SqlClient pack version flow)
$([System.Text.RegularExpressions.Regex]::Replace($(CommitId), "\s", ""))
"$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)"
@@ -627,7 +608,6 @@
-p:CommitId="$(CommitId)"
- -p:NuspecVersion="$(_EvaluatedSqlClientPackageVersion)"
-p:PackageOutputPath="$(SqlClientArtifactRoot)/$(ReferenceType)-$(Configuration)"
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 040633d95d..76b5d7b51c 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -82,6 +82,7 @@
$(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
$(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
+ $(Version)
$(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
$([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
true
From 7b6ad6ef4600c1137207c25d1c7e222438844d39 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 4 May 2026 14:30:48 -0300
Subject: [PATCH 03/15] Align pack docs with dotnet build and harden SqlClient
nuspec prep
---
BUILDGUIDE.md | 64 ++++++++++---------
TESTGUIDE.md | 44 ++++++-------
.../src/Microsoft.Data.SqlClient.csproj | 9 ++-
3 files changed, 61 insertions(+), 56 deletions(-)
diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index 715923d1b3..76aaf5d28f 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -20,9 +20,8 @@ on operating systems that do not support .NET Framework. As such, it is not nece
no action is required. On Linux and macOS systems, the `pwsh` command is required to be in the `$PATH` environment
variable. For specific instructions see: [Install PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/install-powershell)
-The **NuGet** binary is required to package the Microsoft.Data.SqlClient project. For convenience, this can be done
-via the PowerShell script [tools/scripts/downloadLatestNuget.ps1](tools/scripts/downloadLatestNuget.ps1), however, any
-`nuget.exe` binary can be used.
+The **NuGet** binary is optional for inspection and feed-management workflows, but build and packaging flows in this
+repository are run through `dotnet build` against `build.proj`.
## Developer Workflow
@@ -35,9 +34,7 @@ package the project. The `build.proj` file provides convenient targets to accomp
> is recommended that `build.proj` is used for local development, as well.
> [!TIP]
-> `build.proj` was written with the intention of being called from `msbuild`. As such, the examples below
-> use `msbuild`. On systems where `msbuild` is not available, simply replace `msbuild` with `dotnet msbuild` to get the
-> same behavior.
+> Use `dotnet build` with `build.proj` for local and CI workflows in this repository.
> [!TIP]
> This section is not exhaustive of all targets or parameters to `build.proj`. Complete documentation is available in
@@ -45,10 +42,10 @@ package the project. The `build.proj` file provides convenient targets to accomp
### Building Projects
-From the root of your repository, run `msbuild` against `build.proj` with a build target, following this pattern:
+From the root of your repository, run `dotnet build` against `build.proj` with a build target, following this pattern:
```bash
-msbuild build.proj -t: [optional_parameters]
+dotnet build build.proj -t: [optional_parameters]
```
The following build targets can be used to build the following projects. All targets will implicitly build any other
@@ -86,18 +83,21 @@ placed in `artifacts/Microsoft.Data.SqlClient.ref/Project-/`
#### Examples
Build all projects:
+
```bash
-msbuild build.proj -t:Build
+dotnet build build.proj -t:Build
```
Build Microsoft.Data.SqlClient in Release configuration:
+
```bash
-msbuild build.proj -t:BuildSqlClient -p:Configuration=Release
+dotnet build build.proj -t:BuildSqlClient -p:Configuration=Release
```
Build v1.2.3 of Microsoft.Data.SqlClient.Extensions.Abstractions:
+
```bash
-msbuild build.proj -t:BuildAbstractions -p:PackageVersionAbstractions=1.2.3
+dotnet build build.proj -t:BuildAbstractions -p:PackageVersionAbstractions=1.2.3
```
### Testing Projects
@@ -105,10 +105,10 @@ msbuild build.proj -t:BuildAbstractions -p:PackageVersionAbstractions=1.2.3
This section provides a summary and brief example of how to execute tests for projects in this repository. **For more
information about test procedures, including config file setup, see [TESTGUIDE.md](TESTGUIDE.md).**
-From the root of your repository, run `msbuild` against `build.proj` with a test target, following this pattern:
+From the root of your repository, run `dotnet build` against `build.proj` with a test target, following this pattern:
```bash
-msbuild build.proj -t: [optional_parameters]
+dotnet build build.proj -t: [optional_parameters]
```
| `` | Description |
@@ -140,37 +140,37 @@ A selection of parameters for test targets in `build.proj` relevant to common de
Run Microsoft.Data.SqlClient unit tests:
```bash
-msbuild build.proj -t:TestSqlClientUnit
+dotnet build build.proj -t:TestSqlClientUnit
```
Run Microsoft.Data.SqlClient manual test set 2:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestSet=2
+dotnet build build.proj -t:TestSqlClientManual -p:TestSet=2
```
Run Microsoft.Data.SqlClient functional tests against x86 dotnet:
```bash
-msbuild build.proj -t:TestSqlClientFunctional -p:DotnetPath='C:\path\to\dotnet\x86\'
+dotnet build build.proj -t:TestSqlClientFunctional -p:DotnetPath='C:\path\to\dotnet\x86\'
```
Run all Microsoft.Data.SqlClient.Extensions.Azure unit tests, including interactive, but excluding failing tests:
```bash
-msbuild build.proj -t:TestAzure -p:TestFilters=category!=failing
+dotnet build build.proj -t:TestAzure -p:TestFilters=category!=failing
```
Run Microsoft.Data.SqlClient functional tests against net8.0 runtime:
```bash
-msbuild build.proj -t:TestSqlClientFunctional -p:TestFramework=net8.0
+dotnet build build.proj -t:TestSqlClientFunctional -p:TestFramework=net8.0
```
### Packaging Projects
Just like building and testing the various projects in this repository, packaging the projects into NuGet packages is
-also handled by `build.proj`. From the root of your repository, run `msbuild` against `build.proj` with a pack target,
+also handle by `build.proj`. From the root of your repository, run `dotnet build` against `build.proj` with a pack target,
following this pattern:
```bash
-msbuild build.proj -t: [optional_parameters]
+dotnet build build.proj -t: [optional_parameters]
```
| `` | Description |
@@ -191,30 +191,34 @@ A selection of parameters for pack targets in `build.proj` relevant to common de
| `[optional_parameter]` | Default Value | Allowed Values | Description |
|------------------------------------|---------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-p:Configuration=` | `Debug` | `Debug`, `Release` | Build configuration. Only applies if project and dependencies are being built. |
-| `-p:NugetPath=` | `[blank]` | eg. `C:\my\nuget.exe` | _Only applies to `PackSqlClient`._ Path to `nuget.exe` to use. If not provided, defaults to `nuget.exe` in the PATH. |
| `-p:PackBuild=` | `true` | `true`, `false` | Whether or not to build the project before packing. If `false`, project must be built using the same parameters. |
| `-p:PackageVersion=` | `[blank]` | eg. `1.2.3-dev123` | Version to assign to the package, where `` can be one of: `['Abstractions', 'Azure', 'AkvProvider', 'Logging', 'SqlClient', 'SqlServer']`. If `PackBuild` is `true`, the assembly and file versions will be derived from this version. See Versioning for more details. |
+For `PackSqlClient`, these additional parameters are required because dependency versions are injected into the SqlClient nuspec during pack:
+
+- `-p:PackageVersionAbstractions=`
+- `-p:PackageVersionLogging=`
+
#### Examples
Package Microsoft.Data.SqlClient.Internal.Logging into a NuGet package:
```bash
-msbuild build.proj -t:PackLogging
+dotnet build build.proj -t:PackLogging
```
-Package Microsoft.Data.SqlClient if `nuget.exe` is not in the `$PATH` environment variable:
+Package Microsoft.Data.SqlClient:
```bash
-msbuild build.proj -t:PackSqlClient -p:NugetPath="C:\my\nuget.exe"
+dotnet build build.proj -t:PackSqlClient -p:PackageVersionAbstractions= -p:PackageVersionLogging=
```
Package version 1.2.3 of Microsoft.Data.SqlClient.Extensions.Abstractions:
```bash
-msbuild build.proj -t:PackAbstractions -p:PackageVersionAbstractions=1.2.3
+dotnet build build.proj -t:PackAbstractions -p:PackageVersionAbstractions=1.2.3
```
Package Microsoft.Data.SqlClient.Extensions.Azure without building it beforehand:
```bash
-msbuild build.proj -t:PackAzure -p:PackBuild=false
+dotnet build build.proj -t:PackAzure -p:PackBuild=false
```
## Versioning
@@ -276,20 +280,20 @@ and Microsoft.Data.SqlClient.Internal.Logging v2.2.2.
```bash
# Build v2.2.2 of Logging and copy to packages
-msbuild build.proj -t:PackLogging \
+dotnet build build.proj -t:PackLogging \
-p:ReferenceType=Package \
-p:PackageVersionLogging=2.2.2
cp artifacts/Microsoft.Data.SqlClient.Internal.Logging/Debug/*.*pkg packages/
# Build v1.0.1 of Abstractions that depends on v2.2.2 of Logging
-msbuild build.proj -t:PackAbstractions \
+dotnet build build.proj -t:PackAbstractions \
-p:ReferenceType=Package \
-p:PackageVersionAbstractions=1.0.1 \
-p:PackageVersionLogging=2.2.2 \
cp artifacts/Microsoft.Data.SqlClient.Extensions.Abstractions/Package-Debug/*.*pkg packages/
# Build SqlClient
-msbuild -t:PackSqlClient \
+dotnet build build.proj -t:PackSqlClient \
-p:ReferenceType=Package \
-p:PackageVersionSqlClient=7.1.1 \
-p:PackageVersionAbstractions=1.0.1 \
@@ -299,7 +303,7 @@ cp artifacts/Microsoft.Data.SqlClient/Package-Debug/*.*pkg packages/
Run Microsoft.Data.SqlClient functional tests against the versions built above:
```bash
-msbuild build.proj -t:TestSqlClientFunctional \
+dotnet build build.proj -t:TestSqlClientFunctional \
-p:ReferenceType=Package \
-p:PackageVersionSqlClient=7.1.1 \
-p:PackageVersionAbstractions=1.0.1 \
diff --git a/TESTGUIDE.md b/TESTGUIDE.md
index fdcb8749ec..349674deee 100644
--- a/TESTGUIDE.md
+++ b/TESTGUIDE.md
@@ -23,13 +23,7 @@ These projects target `net8.0`, `net9.0`, and `net10.0` on all platforms. On Win
Use [build.proj](build.proj) from the repository root:
```bash
-msbuild build.proj -t: [optional_parameters]
-```
-
-If `msbuild` is not available, use `dotnet msbuild`:
-
-```bash
-dotnet msbuild build.proj -t: [optional_parameters]
+dotnet build build.proj -t: [optional_parameters]
```
Test targets build the projects they depend on, so a separate build step is not required for normal test runs.
@@ -51,55 +45,55 @@ Test targets build the projects they depend on, so a separate build step is not
Run the SqlClient unit tests:
```bash
-msbuild build.proj -t:TestSqlClientUnit
+dotnet build build.proj -t:TestSqlClientUnit
```
Run the SqlClient functional tests:
```bash
-msbuild build.proj -t:TestSqlClientFunctional
+dotnet build build.proj -t:TestSqlClientFunctional
```
Run the SqlClient manual tests:
```bash
-msbuild build.proj -t:TestSqlClientManual
+dotnet build build.proj -t:TestSqlClientManual
```
Run only manual test set 2:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestSet=2
+dotnet build build.proj -t:TestSqlClientManual -p:TestSet=2
```
Run manual test sets 1 and 3:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestSet=13
+dotnet build build.proj -t:TestSqlClientManual -p:TestSet=13
```
Run Always Encrypted manual tests:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestSet=AE
+dotnet build build.proj -t:TestSqlClientManual -p:TestSet=AE
```
Run a specific target framework:
```bash
-msbuild build.proj -t:TestSqlClientFunctional -p:TestFramework=net8.0
+dotnet build build.proj -t:TestSqlClientFunctional -p:TestFramework=net8.0
```
Run functional tests against an x86 `dotnet` installation:
```bash
-msbuild build.proj -t:TestSqlClientFunctional -p:DotnetPath='C:\path\to\dotnet\x86\'
+dotnet build build.proj -t:TestSqlClientFunctional -p:DotnetPath='C:\path\to\dotnet\x86\'
```
Run all Azure extension tests, including `interactive` tests, while still excluding tests marked `failing` or `flaky`:
```bash
-msbuild build.proj -t:TestAzure -p:TestFilters=category!=failing
+dotnet build build.proj -t:TestAzure -p:TestFilters=category!=failing
```
## Test Parameters
@@ -132,13 +126,13 @@ Examples:
```bash
# Run a single test by fully-qualified name.
-msbuild build.proj -t:TestSqlClientUnit -p:TestFilters=FullyQualifiedName=Namespace.ClassName.MethodName
+dotnet build build.proj -t:TestSqlClientUnit -p:TestFilters=FullyQualifiedName=Namespace.ClassName.MethodName
# Run only flaky tests while investigating quarantine failures.
-msbuild build.proj -t:TestSqlClientManual -p:TestFilters=category=flaky
+dotnet build build.proj -t:TestSqlClientManual -p:TestFilters=category=flaky
# Disable the default filter.
-msbuild build.proj -t:TestSqlClientFunctional -p:TestFilters=none
+dotnet build build.proj -t:TestSqlClientFunctional -p:TestFilters=none
```
When passing filter expressions that contain shell-sensitive characters such as `&`, quote or escape the value as
@@ -222,14 +216,14 @@ For SQL Server in a Linux container, WSL, or another host where SQL authenticati
You can override the config file path with the `MDS_TEST_CONFIG` environment variable:
```bash
-MDS_TEST_CONFIG=/path/to/config.json msbuild build.proj -t:TestSqlClientManual -p:TestSet=2
+MDS_TEST_CONFIG=/path/to/config.json dotnet build build.proj -t:TestSqlClientManual -p:TestSet=2
```
On PowerShell:
```powershell
$env:MDS_TEST_CONFIG = "C:\path\to\config.json"
-msbuild build.proj -t:TestSqlClientManual -p:TestSet=2
+dotnet build build.proj -t:TestSqlClientManual -p:TestSet=2
```
## Configuration Properties
@@ -289,23 +283,23 @@ If `TestSet` is omitted, all sets are compiled and run. You can combine sets by
Test results are written to `test_results` by default. Override the location with `TestResultsFolderPath`:
```bash
-msbuild build.proj -t:TestSqlClientUnit -p:TestResultsFolderPath=/tmp/sqlclient-test-results
+dotnet build build.proj -t:TestSqlClientUnit -p:TestResultsFolderPath=/tmp/sqlclient-test-results
```
Hang blame collection is enabled by default with a `10m` timeout. To increase the timeout:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestBlameTimeout=30m
+dotnet build build.proj -t:TestSqlClientManual -p:TestBlameTimeout=30m
```
To disable hang blame collection:
```bash
-msbuild build.proj -t:TestSqlClientManual -p:TestBlameTimeout=0
+dotnet build build.proj -t:TestSqlClientManual -p:TestBlameTimeout=0
```
Code coverage is enabled by default. To disable it for a faster local run:
```bash
-msbuild build.proj -t:TestSqlClientUnit -p:TestCodeCoverage=false
+dotnet build build.proj -t:TestSqlClientUnit -p:TestCodeCoverage=false
```
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 76b5d7b51c..0111c54a33 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -83,7 +83,7 @@
$(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
$(Version)
- $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
+ $(SqlClientPackNuspecTemplatePath)
$([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
true
snupkg
@@ -99,6 +99,13 @@
+
+
+
+
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('1.0.0','$(NuspecVersion)'))
From f0148e6670a95423464563b51282816feb123bad Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 4 May 2026 14:35:21 -0300
Subject: [PATCH 04/15] Document terminal reliability and no-set-e guidance
---
.github/copilot-instructions.md | 8 ++++++++
AGENTS.md | 11 +++++++++++
2 files changed, 19 insertions(+)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 0c78f461cb..51ce83bb10 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -150,6 +150,14 @@ When a new issue is created, follow these steps:
- Do not modify `CHANGELOG.md` unless executing a release workflow (see `release-notes` prompt).
- Do not close issues without a fix or without providing a clear reason.
+## Terminal Execution Safety
+- Treat any non-zero shell exit code as a failed step that requires correction before proceeding.
+- If a bash process exits, do not wait for more output from that process; rerun the command in a fresh terminal session.
+- Validate that expected command output was produced before using it as evidence for conclusions.
+- When terminal execution fails, surface the failure immediately and retry with a corrected command.
+- Avoid `set -e` in this automation workflow; use focused commands and verify each result explicitly so shell exits are observable and attributable.
+- Prefer short, single-purpose terminal commands over long chained scripts when debugging or gathering state.
+
## 📝 Notes
- Update policies and guidelines in the `policy/` directory as needed based on trending practices and team feedback.
- Regularly review and update the `doc/` directory to ensure it reflects the current state of the project.
diff --git a/AGENTS.md b/AGENTS.md
index 690e9c9c8d..42f3a39399 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -54,6 +54,17 @@ This repository provides reusable prompts in `.github/prompts/` for common maint
6. **Performance Optimization**: Use pooling, async, efficient allocations
7. **Observability**: EventSource tracing, meaningful errors
+## Terminal Reliability Rules
+
+When using shell/terminal tools, follow these rules strictly:
+
+1. Treat non-zero terminal exit codes as immediate failures to investigate; do not continue as if the command succeeded.
+2. If a bash session exits, assume it is dead and start a new command/session; do not wait for additional output from that session.
+3. After any command expected to gather data, verify output was actually returned before proceeding.
+4. If command execution failed, report the failure clearly and retry with a corrected command instead of waiting.
+5. Avoid `set -e` in this automation context; prefer single-purpose commands with explicit follow-up checks so failures are visible without killing the shell unexpectedly.
+6. Prefer shorter command batches over long chained scripts when collecting evidence; this makes bash exits easier to detect and recover from.
+
## Branch Naming
All branches created by AI agents **must** live under the `dev/automation/` prefix. Use a descriptive suffix, for example:
From f555b3990e0720cf144efde75a0329072646dc9c Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Mon, 4 May 2026 15:49:40 -0300
Subject: [PATCH 05/15] Fix 5 Copilot comments: template token brittleness,
repro docs, typos, and NuspecVersion clarity
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Replace hardcoded version XML with $NuspecVersion$ token in nuspec template (fixes brittle string replacement)
- Update csproj to replace the dedicated token instead of hardcoded XML string (resilient to formatting changes)
- Add clarifying text to repro command explaining PrepareSqlClientPackNuspec requirements
- Fix spelling: 'occured' → 'occurred' in error message
- Fix grammar/spelling in BUILDGUIDE.md: 'bulding' → 'building', 'also handle by' → 'also handled by'
- Clarify NuspecVersion derives from $(Version) by SDK defaults and doesn't need explicit passing
---
BUILDGUIDE.md | 2 +-
.../src/Microsoft.Data.SqlClient.csproj | 2 +-
.../src/sqlclient-dotnet-pack.md | 15 ++++++++++++---
tools/specs/Microsoft.Data.SqlClient.nuspec | 2 +-
4 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index 76aaf5d28f..ccdbd353aa 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -166,7 +166,7 @@ dotnet build build.proj -t:TestSqlClientFunctional -p:TestFramework=net8.0
### Packaging Projects
Just like building and testing the various projects in this repository, packaging the projects into NuGet packages is
-also handle by `build.proj`. From the root of your repository, run `dotnet build` against `build.proj` with a pack target,
+also handled by `build.proj`. From the root of your repository, run `dotnet build` against `build.proj` with a pack target,
following this pattern:
```bash
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 0111c54a33..8580b1db2a 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -107,7 +107,7 @@
Condition="'$(NuspecVersion)' == ''" />
- <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('1.0.0','$(NuspecVersion)'))
+ <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$NuspecVersion$','$(NuspecVersion)'))
/tools/specs/Microsoft.Data.SqlClient.nuspec -p:NuspecBasePath=/tools/specs -p:NuspecProperties="COMMITID=abc;Configuration=Debug;ReferenceType=Project;AbstractionsPackageVersion=1.0.0-dev;LoggingPackageVersion=1.0.0-dev" -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
```
-Observed error:
+To reproduce this failure in the current branch and exercise the workaround, also pass the required MSBuild properties:
-- `An error occured while trying to parse the value '' of property 'dependencies' in the manifest file.`
+```bash
+dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:PackageVersionAbstractions=1.0.0-dev -p:PackageVersionLogging=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
+```
+
+The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec, bypassing the SDK's substitution bug.
+
+Observed error (without workaround):
+
+- `An error occurred while trying to parse the value '' of property 'dependencies' in the manifest file.`
- `'' is not a valid version string.`
The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by `PrepareSqlClientPackNuspec`.
@@ -74,10 +82,11 @@ SqlClient-specific pack defaults are set in:
The `build.proj` target passes dynamic values only:
- `CommitId`
-- `NuspecVersion`
- `PackageOutputPath`
- plus standard version/reference-type arguments
+Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be explicitly passed.
+
## Outputs
Expected artifacts:
diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec
index 75aa9e786d..1c578d129e 100644
--- a/tools/specs/Microsoft.Data.SqlClient.nuspec
+++ b/tools/specs/Microsoft.Data.SqlClient.nuspec
@@ -2,7 +2,7 @@
Microsoft.Data.SqlClient
- 1.0.0
+ $NuspecVersion$
Microsoft.Data.SqlClient
Microsoft
true
From d334db7a0da5dc44286a9c2e5399d862f2b40da5 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 5 May 2026 08:59:36 -0300
Subject: [PATCH 06/15] Fix Copilot follow-ups for dotnet pack property
contracts
- Align PrepareSqlClientPackNuspec error guidance with direct dotnet pack properties and build.proj aliases
- Update sqlclient-dotnet-pack.md replacement list to use $NuspecVersion$ token
- Correct direct repro command to pass AbstractionsPackageVersion/LoggingPackageVersion and clarify entrypoint property translation
---
.../src/Microsoft.Data.SqlClient.csproj | 4 ++--
src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md | 6 ++++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 8580b1db2a..5b925e23fd 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -99,9 +99,9 @@
-
-
diff --git a/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
index 47199b5463..129446905c 100644
--- a/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
+++ b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
@@ -34,7 +34,7 @@ In this flow, SDK pack token substitution is reliable for general nuspec propert
- Replacements applied:
- `$AbstractionsPackageVersion$` -> `$(AbstractionsPackageVersion)`
- `$LoggingPackageVersion$` -> `$(LoggingPackageVersion)`
- - `1.0.0` -> `$(NuspecVersion)`
+ - `$NuspecVersion$` -> `$(NuspecVersion)`
This keeps layout parity with the existing nuspec while using `dotnet pack` end-to-end.
@@ -49,9 +49,11 @@ dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --n
To reproduce this failure in the current branch and exercise the workaround, also pass the required MSBuild properties:
```bash
-dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:PackageVersionAbstractions=1.0.0-dev -p:PackageVersionLogging=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
+dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:AbstractionsPackageVersion=1.0.0-dev -p:LoggingPackageVersion=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
```
+Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint properties and are translated to `AbstractionsPackageVersion` and `LoggingPackageVersion` for direct project pack.
+
The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec, bypassing the SDK's substitution bug.
Observed error (without workaround):
From 775fa1121f38b918b2600f282ddba87175a540f9 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 5 May 2026 09:51:59 -0300
Subject: [PATCH 07/15] Refine SqlClient pack fallback and nuspec version flow
- Move Abstractions/Logging version fallback into SqlClient pack target
- Reuse shared sibling project paths and DOTNET_HOST_PATH
- Document intermediate nuspec generation and sibling version evaluation
- Pass NuspecVersion through shared nuget pack pipeline properties
---
build.proj | 53 --------------
.../steps/generate-nuget-package-step.yml | 4 +-
.../src/Microsoft.Data.SqlClient.csproj | 73 ++++++++++++++++---
.../src/sqlclient-dotnet-pack.md | 56 +++++++++-----
4 files changed, 101 insertions(+), 85 deletions(-)
diff --git a/build.proj b/build.proj
index 66171af6ab..d5492fc15a 100644
--- a/build.proj
+++ b/build.proj
@@ -535,60 +535,7 @@
-
-
-
-
-
-
- "$(DotnetPath)dotnet" msbuild "$(AbstractionsProjectPath)"
- -nologo
- -verbosity:quiet
- -getProperty:AbstractionsPackageVersion
- $(BuildNumberArgument)
- $(BuildSuffixArgument)
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GetAbstractionsPackageVersionCommand), "\s+", " "))
-
-
-
-
-
-
-
-
-
-
- "$(DotnetPath)dotnet" msbuild "$(LoggingProjectPath)"
- -nologo
- -verbosity:quiet
- -getProperty:LoggingPackageVersion
- $(BuildNumberArgument)
- $(BuildSuffixArgument)
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GetLoggingPackageVersionCommand), "\s+", " "))
-
-
-
-
-
-
-
-<<<<<<< HEAD
- <_EvaluatedSqlClientPackageVersion>$([System.Text.RegularExpressions.Regex]::Replace($(_EvaluatedSqlClientPackageVersion), "\s", ""))
- $([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionAbstractions), "\s", ""))
- $([System.Text.RegularExpressions.Regex]::Replace($(PackageVersionLogging), "\s", ""))
-=======
->>>>>>> a31e7e8fc (Simplify SqlClient pack version flow)
$([System.Text.RegularExpressions.Regex]::Replace($(CommitId), "\s", ""))
"$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)"
diff --git a/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml b/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
index 46c5c61492..b6dbb07790 100644
--- a/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
+++ b/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
@@ -70,11 +70,11 @@ steps:
${{parameters.nuspecPath}}
-Version ${{parameters.packageVersion}}
-OutputDirectory ${{parameters.outputDirectory}}
- -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};${{parameters.properties}}"
+ -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"
${{else }}:
arguments: >-
pack
${{parameters.nuspecPath}}
-Version ${{parameters.packageVersion}}
-OutputDirectory ${{parameters.outputDirectory}}
- -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};${{parameters.properties}}"
+ -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 5b925e23fd..f9a1b996f9 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -79,41 +79,90 @@
+
+
$(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
$(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
+ $(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj
+ $(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj
- $(Version)
+
$(SqlClientPackNuspecTemplatePath)
$([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
+ $(Version)
+ COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
true
snupkg
true
-
- COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
-
-
-
+
+
+
+ "$(DOTNET_HOST_PATH)" msbuild "$(AbstractionsProjectPath)"
+ -nologo
+ -verbosity:quiet
+ -getProperty:AbstractionsPackageVersion
+ -p:BuildNumber=$(BuildNumber)
+ -p:BuildSuffix=$(BuildSuffix)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(GetAbstractionsPackageVersionCommand), "\s+", " "))
+
+
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AbstractionsPackageVersion), "\s", ""))
+
+
+
+
+
+ "$(DOTNET_HOST_PATH)" msbuild "$(LoggingProjectPath)"
+ -nologo
+ -verbosity:quiet
+ -getProperty:LoggingPackageVersion
+ -p:BuildNumber=$(BuildNumber)
+ -p:BuildSuffix=$(BuildSuffix)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(GetLoggingPackageVersionCommand), "\s+", " "))
+
+
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(LoggingPackageVersion), "\s", ""))
+
+
+
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$NuspecVersion$','$(NuspecVersion)'))
-
+
$(SqlClientPackNuspecGeneratedPath)
@@ -158,7 +207,7 @@
-
@@ -166,7 +215,7 @@
-
diff --git a/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
index 129446905c..ba33225106 100644
--- a/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
+++ b/src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
@@ -13,21 +13,27 @@ This document describes how the SqlClient package is produced with dotnet pack i
Run from repo root:
```bash
-dotnet build build.proj -t:PackSqlClient -p:Configuration=Release -p:ReferenceType=Project -p:PackBuild=false -p:PackageVersionAbstractions= -p:PackageVersionLogging=
+dotnet build -t:PackSqlClient -p:Configuration=Release -p:ReferenceType=Project -p:PackBuild=false
```
-Required pack inputs:
+Optional version override inputs:
- `PackageVersionAbstractions`
- `PackageVersionLogging`
-These are required because dependency versions are injected into the SqlClient nuspec at pack time.
+These can still be passed to override sibling package versions, but they are no longer required. If
+omitted, `PrepareSqlClientPackNuspec` evaluates the computed `AbstractionsPackageVersion` and
+`LoggingPackageVersion` from the sibling projects using the current `BuildNumber` and `BuildSuffix`
+context.
## Why a generated nuspec is used
-SqlClient packaging still relies on `tools/specs/Microsoft.Data.SqlClient.nuspec` for file mapping and dependency groups (`lib/*`, `ref/*`, `runtimes/*`, resources, metadata).
+SqlClient packaging still relies on `tools/specs/Microsoft.Data.SqlClient.nuspec` for file mapping
+and dependency groups (`lib/*`, `ref/*`, `runtimes/*`, resources, metadata).
-In this flow, SDK pack token substitution is reliable for general nuspec properties, but dependency version token replacement in the nuspec dependency section can fail. To avoid that, the project generates an intermediate nuspec before `GenerateNuspec`:
+In this flow, SDK pack token substitution is reliable for general nuspec properties, but dependency
+version token replacement in the nuspec dependency section can fail. To avoid that, the project
+generates an intermediate nuspec before `GenerateNuspec`:
- Template nuspec: `tools/specs/Microsoft.Data.SqlClient.nuspec`
- Generated nuspec: `obj/Microsoft.Data.SqlClient.pack.nuspec`
@@ -40,40 +46,53 @@ This keeps layout parity with the existing nuspec while using `dotnet pack` end-
## Known SDK behavior and repro
-Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK `10.0.107`:
+Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK
+`10.0.107`:
```bash
dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:NuspecFile=/tools/specs/Microsoft.Data.SqlClient.nuspec -p:NuspecBasePath=/tools/specs -p:NuspecProperties="COMMITID=abc;Configuration=Debug;ReferenceType=Project;AbstractionsPackageVersion=1.0.0-dev;LoggingPackageVersion=1.0.0-dev" -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
```
-To reproduce this failure in the current branch and exercise the workaround, also pass the required MSBuild properties:
+To reproduce this failure in the current branch and exercise the workaround, you can still pass the
+direct project properties explicitly:
```bash
dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:AbstractionsPackageVersion=1.0.0-dev -p:LoggingPackageVersion=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
```
-Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint properties and are translated to `AbstractionsPackageVersion` and `LoggingPackageVersion` for direct project pack.
+Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint
+properties. Direct project pack can instead pass `AbstractionsPackageVersion` and
+`LoggingPackageVersion`, or omit them and let the project evaluate sibling defaults.
-The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec, bypassing the SDK's substitution bug.
+The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec,
+bypassing the SDK's substitution bug.
Observed error (without workaround):
- `An error occurred while trying to parse the value '' of property 'dependencies' in the manifest file.`
- `'' is not a valid version string.`
-The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by `PrepareSqlClientPackNuspec`.
+The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by
+`PrepareSqlClientPackNuspec`.
## Related upstream issues
-The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec files with `dotnet pack`:
+The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec
+files with `dotnet pack`:
-- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties` values, only first substituted and others become empty.
-- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom on SDK 6.0.404.
-- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec not filling tokens like `$version$`.
-- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty when packing with nuspec.
-- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path behavior inconsistencies with `dotnet pack`.
+- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties`
+ values, only first substituted and others become empty.
+- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom
+ on SDK 6.0.404.
+- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec
+ not filling tokens like `$version$`.
+- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty
+ when packing with nuspec.
+- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path
+ behavior inconsistencies with `dotnet pack`.
-These links do not prove this exact dependency-token timing path is identical, but they strongly indicate related substitution behavior in the same pack surface area.
+These links do not prove this exact dependency-token timing path is identical, but they strongly
+indicate related substitution behavior in the same pack surface area.
## Where pack properties are defined
@@ -87,7 +106,8 @@ The `build.proj` target passes dynamic values only:
- `PackageOutputPath`
- plus standard version/reference-type arguments
-Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be explicitly passed.
+Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be
+explicitly passed.
## Outputs
From a79c2c746c9efc36dd8f118a4cf1f4416dfcc6f8 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 5 May 2026 16:26:52 -0300
Subject: [PATCH 08/15] Migrate SqlClient packaging from nuget.exe to dotnet
pack
- Replace NuspecVersion token with Version via NuspecProperties so
SDK PackTask substitutes it directly; remove NuspecVersion property
- Add PrepareSqlClientPackNuspec target to pre-expand
$AbstractionsPackageVersion$ and $LoggingPackageVersion$ tokens
in dependency version attributes (SDK PackTask does not substitute
these in nuspec dependency elements)
- Replace generate-nuget-package-step.yml (NuGetCommand@2/nuget.exe)
with DotNetCoreCLI@2 build of build.proj -t:PackSqlClient in
ci-build-nugets-job.yml; add CopyFiles step to move output to
$(packagePath) for downstream steps
- Delete generate-nuget-package-step.yml (no remaining callers)
- Delete sqlclient-dotnet-pack.md; migrate design notes to csproj
- Update BUILDGUIDE.md: PackageVersionAbstractions/Logging are
optional overrides, not required; simplify example command
---
BUILDGUIDE.md | 6 +-
.../templates/jobs/ci-build-nugets-job.yml | 33 +++--
.../steps/generate-nuget-package-step.yml | 80 ------------
.../src/Microsoft.Data.SqlClient.csproj | 73 ++++++++---
.../src/sqlclient-dotnet-pack.md | 117 ------------------
tools/specs/Microsoft.Data.SqlClient.nuspec | 3 +-
6 files changed, 87 insertions(+), 225 deletions(-)
delete mode 100644 eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
delete mode 100644 src/Microsoft.Data.SqlClient/src/sqlclient-dotnet-pack.md
diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index ccdbd353aa..8ff965d65b 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -194,11 +194,13 @@ A selection of parameters for pack targets in `build.proj` relevant to common de
| `-p:PackBuild=` | `true` | `true`, `false` | Whether or not to build the project before packing. If `false`, project must be built using the same parameters. |
| `-p:PackageVersion=` | `[blank]` | eg. `1.2.3-dev123` | Version to assign to the package, where `` can be one of: `['Abstractions', 'Azure', 'AkvProvider', 'Logging', 'SqlClient', 'SqlServer']`. If `PackBuild` is `true`, the assembly and file versions will be derived from this version. See Versioning for more details. |
-For `PackSqlClient`, these additional parameters are required because dependency versions are injected into the SqlClient nuspec during pack:
+For `PackSqlClient`, these additional parameters are optional overrides for dependency versions injected into the SqlClient nuspec during pack:
- `-p:PackageVersionAbstractions=`
- `-p:PackageVersionLogging=`
+If omitted, `PackSqlClient` computes `AbstractionsPackageVersion` and `LoggingPackageVersion` from sibling projects using the current `BuildNumber` and `BuildSuffix` context.
+
#### Examples
Package Microsoft.Data.SqlClient.Internal.Logging into a NuGet package:
@@ -208,7 +210,7 @@ dotnet build build.proj -t:PackLogging
Package Microsoft.Data.SqlClient:
```bash
-dotnet build build.proj -t:PackSqlClient -p:PackageVersionAbstractions= -p:PackageVersionLogging=
+dotnet build build.proj -t:PackSqlClient
```
Package version 1.2.3 of Microsoft.Data.SqlClient.Extensions.Abstractions:
diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml
index afb20ac80e..31bf8be63b 100644
--- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml
+++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml
@@ -143,16 +143,29 @@ jobs:
abstractionsPackageVersion: ${{parameters.abstractionsPackageVersion}}
loggingPackageVersion: ${{ parameters.loggingPackageVersion }}
- - template: /eng/pipelines/common/templates/steps/generate-nuget-package-step.yml@self
- parameters:
- buildConfiguration: ${{ parameters.buildConfiguration }}
- displayName: 'Create MDS NuGet Package'
- generateSymbolsPackage: true
- nuspecPath: 'tools/specs/Microsoft.Data.SqlClient.nuspec'
- outputDirectory: $(packagePath)
- packageVersion: ${{ parameters.mdsPackageVersion }}
- properties: 'AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};LoggingPackageVersion=${{ parameters.loggingPackageVersion }}'
- referenceType: ${{ parameters.referenceType }}
+ - task: DotNetCoreCLI@2
+ displayName: 'Create MDS NuGet Package'
+ inputs:
+ command: build
+ projects: build.proj
+ arguments: >-
+ -t:PackSqlClient
+ -p:PackBuild=false
+ -p:Configuration=${{ parameters.buildConfiguration }}
+ -p:ReferenceType=${{ parameters.referenceType }}
+ -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }}
+ -p:PackageVersionAbstractions=${{ parameters.abstractionsPackageVersion }}
+ -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }}
+
+ # PackSqlClient outputs to artifacts/Microsoft.Data.SqlClient/-/.
+ # Downstream steps (local feed copy, AKV pack, artifact publish) all expect packages at
+ # $(packagePath), so copy them there.
+ - task: CopyFiles@2
+ displayName: Copy MDS Package to Output Directory
+ inputs:
+ sourceFolder: $(Build.SourcesDirectory)/artifacts/Microsoft.Data.SqlClient/${{ parameters.referenceType }}-${{ parameters.buildConfiguration }}
+ contents: 'Microsoft.Data.SqlClient.*'
+ targetFolder: $(packagePath)
# When building in Package mode, the AKV Provider restore needs to find the MDS package
# we just built. Copy it to the local NuGet feed so NuGet.config can resolve it.
diff --git a/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml b/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
deleted file mode 100644
index b6dbb07790..0000000000
--- a/eng/pipelines/common/templates/steps/generate-nuget-package-step.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-#################################################################################
-# Licensed to the .NET Foundation under one or more agreements. #
-# The .NET Foundation licenses this file to you under the MIT license. #
-# See the LICENSE file in the project root for more information. #
-#################################################################################
-parameters:
- - name: nuspecPath
- type: string
-
- - name: packageVersion
- type: string
-
- - name: outputDirectory
- type: string
- default: '$(Build.SourcesDirectory)/output'
-
- # The C# build configuration (e.g. Debug or Release) to use when building the NuGet package.
- - name: buildConfiguration
- type: string
- default: Debug
- values:
- - Debug
- - Release
-
- - name: generateSymbolsPackage
- type: boolean
-
- - name: displayName
- type: string
-
- - name: installNuget
- type: boolean
- default: true
-
- # The C# project reference type to use when building and packing the packages.
- - name: referenceType
- type: string
- values:
- # Reference sibling packages as NuGet packages.
- - Package
- # Reference sibling packages as C# projects.
- - Project
-
- # Semi-colon separated properties to pass to nuget pack via the -properties argument.
- - name: properties
- type: string
- default: ''
-
-steps:
-- ${{ if parameters.installNuget }}:
- - task: NuGetToolInstaller@1
- displayName: 'Install Latest Nuget'
- inputs:
- checkLatest: true
-
-- powershell: |
- $Commit=git rev-parse HEAD
- Write-Host "##vso[task.setvariable variable=CommitHead;]$Commit"
- displayName: CommitHead
-
-- task: NuGetCommand@2
- displayName: ${{parameters.displayName }}
- inputs:
- command: custom
- ${{ if parameters.generateSymbolsPackage }}:
- arguments: >-
- pack
- -Symbols
- -SymbolPackageFormat snupkg
- ${{parameters.nuspecPath}}
- -Version ${{parameters.packageVersion}}
- -OutputDirectory ${{parameters.outputDirectory}}
- -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"
- ${{else }}:
- arguments: >-
- pack
- ${{parameters.nuspecPath}}
- -Version ${{parameters.packageVersion}}
- -OutputDirectory ${{parameters.outputDirectory}}
- -properties "COMMITID=$(CommitHead);Configuration=${{parameters.buildConfiguration}};ReferenceType=${{parameters.referenceType}};NuspecVersion=${{parameters.packageVersion}};${{parameters.properties}}"
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index f9a1b996f9..21fb818e87 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -77,23 +77,54 @@
-
- $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
- $(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
+ $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
+ $(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
+
$(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj
$(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj
-
- $(SqlClientPackNuspecTemplatePath)
- $([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
- $(Version)
- COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
- true
- snupkg
- true
+
+
+
+ $(SqlClientPackNuspecTemplatePath)
+
+
+ $([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
+
+
+ Version=$(Version);COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
+
+
+ true
+
+
+ snupkg
+
+
+ true
+
-
+
@@ -156,7 +199,7 @@
- <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$NuspecVersion$','$(NuspecVersion)'))
+ <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)'))
`$(AbstractionsPackageVersion)`
- - `$LoggingPackageVersion$` -> `$(LoggingPackageVersion)`
- - `$NuspecVersion$` -> `$(NuspecVersion)`
-
-This keeps layout parity with the existing nuspec while using `dotnet pack` end-to-end.
-
-## Known SDK behavior and repro
-
-Passing all tokens through `NuspecProperties` looks correct, but this command fails on SDK
-`10.0.107`:
-
-```bash
-dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:NuspecFile=/tools/specs/Microsoft.Data.SqlClient.nuspec -p:NuspecBasePath=/tools/specs -p:NuspecProperties="COMMITID=abc;Configuration=Debug;ReferenceType=Project;AbstractionsPackageVersion=1.0.0-dev;LoggingPackageVersion=1.0.0-dev" -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
-```
-
-To reproduce this failure in the current branch and exercise the workaround, you can still pass the
-direct project properties explicitly:
-
-```bash
-dotnet pack src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj --no-build -p:Configuration=Debug -p:ReferenceType=Project -p:AbstractionsPackageVersion=1.0.0-dev -p:LoggingPackageVersion=1.0.0-dev -p:NuspecVersion=7.1.0-preview1-dev -p:PackageOutputPath=/artifacts/tmp -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg
-```
-
-Note: `PackageVersionAbstractions` and `PackageVersionLogging` are `build.proj` entrypoint
-properties. Direct project pack can instead pass `AbstractionsPackageVersion` and
-`LoggingPackageVersion`, or omit them and let the project evaluate sibling defaults.
-
-The `PrepareSqlClientPackNuspec` target will materialize the tokens into an intermediate nuspec,
-bypassing the SDK's substitution bug.
-
-Observed error (without workaround):
-
-- `An error occurred while trying to parse the value '' of property 'dependencies' in the manifest file.`
-- `'' is not a valid version string.`
-
-The same flow succeeds when dependency tokens are pre-materialized into the intermediate nuspec by
-`PrepareSqlClientPackNuspec`.
-
-## Related upstream issues
-
-The behavior appears related to long-standing SDK/NuGet pack substitution issues when using nuspec
-files with `dotnet pack`:
-
-- [dotnet/sdk#15482](https://github.com/dotnet/sdk/issues/15482) (open): multiple `NuspecProperties`
- values, only first substituted and others become empty.
-- [dotnet/sdk#29661](https://github.com/dotnet/sdk/issues/29661) (closed as duplicate): same symptom
- on SDK 6.0.404.
-- [dotnet/sdk#10516](https://github.com/dotnet/sdk/issues/10516) (closed): `dotnet pack` with nuspec
- not filling tokens like `$version$`.
-- [dotnet/sdk#15407](https://github.com/dotnet/sdk/issues/15407) (closed): `$configuration$` empty
- when packing with nuspec.
-- [dotnet/sdk#16816](https://github.com/dotnet/sdk/issues/16816) (closed): nuspec token/path
- behavior inconsistencies with `dotnet pack`.
-
-These links do not prove this exact dependency-token timing path is identical, but they strongly
-indicate related substitution behavior in the same pack surface area.
-
-## Where pack properties are defined
-
-SqlClient-specific pack defaults are set in:
-
-- `src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj`
-
-The `build.proj` target passes dynamic values only:
-
-- `CommitId`
-- `PackageOutputPath`
-- plus standard version/reference-type arguments
-
-Note: `NuspecVersion` is derived from `$(Version)` by SDK defaults and does not need to be
-explicitly passed.
-
-## Outputs
-
-Expected artifacts:
-
-- `artifacts/Microsoft.Data.SqlClient/-/Microsoft.Data.SqlClient..nupkg`
-- `artifacts/Microsoft.Data.SqlClient/-/Microsoft.Data.SqlClient..snupkg`
diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec
index 1c578d129e..45132d4d55 100644
--- a/tools/specs/Microsoft.Data.SqlClient.nuspec
+++ b/tools/specs/Microsoft.Data.SqlClient.nuspec
@@ -2,7 +2,7 @@
Microsoft.Data.SqlClient
- $NuspecVersion$
+ $Version$
Microsoft.Data.SqlClient
Microsoft
true
@@ -92,6 +92,7 @@
+
From 7844808d818877d1d8f6ebbd06f19ad667b48971 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 08:48:36 -0300
Subject: [PATCH 09/15] Move SqlClient nuspec beside csproj and rebase pack
paths
---
.../template/release-notes-template.md | 2 +-
.../src/Microsoft.Data.SqlClient.csproj | 9 +-
.../src/Microsoft.Data.SqlClient.nuspec | 235 ++++++++++++++++++
tools/specs/Microsoft.Data.SqlClient.nuspec | 235 ------------------
4 files changed, 240 insertions(+), 241 deletions(-)
create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec
delete mode 100644 tools/specs/Microsoft.Data.SqlClient.nuspec
diff --git a/release-notes/template/release-notes-template.md b/release-notes/template/release-notes-template.md
index 4e3ebcb0c0..9df5a11e7f 100644
--- a/release-notes/template/release-notes-template.md
+++ b/release-notes/template/release-notes-template.md
@@ -87,7 +87,7 @@ We thank the following public contributors. Their efforts toward this project ar
### Dependencies
-(Use the dependencies listed in the package's NuGet spec under tools/specs/ or the project file.)
+(Use the dependencies listed in the package's NuGet spec beside the SqlClient project file, or in the project file.)
#### [Target Framework Version]
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 21fb818e87..156c52490f 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -80,7 +80,7 @@
- $(RepoRoot)tools/specs/Microsoft.Data.SqlClient.nuspec
+ $(MSBuildProjectDirectory)/Microsoft.Data.SqlClient.nuspec
$(BaseIntermediateOutputPath)Microsoft.Data.SqlClient.pack.nuspec
$(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj
@@ -98,11 +98,10 @@
- $([System.IO.Path]::GetDirectoryName('$(SqlClientPackNuspecTemplatePath)'))
+ $(RepoRoot)artifacts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec
deleted file mode 100644
index 45132d4d55..0000000000
--- a/tools/specs/Microsoft.Data.SqlClient.nuspec
+++ /dev/null
@@ -1,235 +0,0 @@
-
-
-
- Microsoft.Data.SqlClient
- $Version$
- Microsoft.Data.SqlClient
- Microsoft
- true
- MIT
- https://aka.ms/sqlclientproject
- dotnet.png
- README.md
-
- The current data provider for SQL Server and Azure SQL databases. This has replaced System.Data.SqlClient. These classes provide access to SQL and encapsulate database-specific protocols, including tabular data stream (TDS).
-
- Commonly Used Types:
- Microsoft.Data.SqlClient.SqlConnection
- Microsoft.Data.SqlClient.SqlException
- Microsoft.Data.SqlClient.SqlParameter
- Microsoft.Data.SqlClient.SqlDataReader
- Microsoft.Data.SqlClient.SqlCommand
- Microsoft.Data.SqlClient.SqlTransaction
- Microsoft.Data.SqlClient.SqlParameterCollection
- Microsoft.Data.SqlClient.SqlClientFactory
-
- When using NuGet 3.x this package requires at least version 3.4.
- https://go.microsoft.com/fwlink/?linkid=2090501
- © Microsoft Corporation. All rights reserved.
- sqlclient microsoft.data.sqlclient
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
From 6bfe23d937b280cc45280cb8162caddd65bb6eee Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 09:31:40 -0300
Subject: [PATCH 10/15] Simplify version fallback and import sibling version
props
---
.../src/Versions.props | 4 +-
.../Abstractions/src/Versions.props | 4 +-
.../Azure/src/Versions.props | 4 +-
.../Logging/src/Versions.props | 4 +-
src/Microsoft.Data.SqlClient/Versions.props | 4 +-
.../src/Microsoft.Data.SqlClient.csproj | 55 +++++--------------
src/Microsoft.SqlServer.Server/Versions.props | 4 +-
7 files changed, 19 insertions(+), 60 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Versions.props b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Versions.props
index 25e3ff90ff..31f85b7da4 100644
--- a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Versions.props
+++ b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Versions.props
@@ -66,9 +66,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(AkvProviderVersionDefault)-$(BuildSuffix)
+ $(AkvProviderVersionDefault)-dev
$(AkvProviderVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Versions.props b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Versions.props
index 32330ad3a6..14daeda570 100644
--- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Versions.props
+++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Versions.props
@@ -67,9 +67,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(AbstractionsVersionDefault)-$(BuildSuffix)
+ $(AbstractionsVersionDefault)-dev
$(AbstractionsVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Versions.props b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Versions.props
index 1876c965eb..3c4bb9dfac 100644
--- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Versions.props
+++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Versions.props
@@ -66,9 +66,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(AzureVersionDefault)-$(BuildSuffix)
+ $(AzureVersionDefault)-dev
$(AzureVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Versions.props b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Versions.props
index 3278bdc2e9..eeb25b93ca 100644
--- a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Versions.props
+++ b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Versions.props
@@ -67,9 +67,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(LoggingVersionDefault)-$(BuildSuffix)
+ $(LoggingVersionDefault)-dev
$(LoggingVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
diff --git a/src/Microsoft.Data.SqlClient/Versions.props b/src/Microsoft.Data.SqlClient/Versions.props
index 5ec3b8b9ac..2a915285b0 100644
--- a/src/Microsoft.Data.SqlClient/Versions.props
+++ b/src/Microsoft.Data.SqlClient/Versions.props
@@ -66,9 +66,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(SqlClientVersionDefault)-$(BuildSuffix)
+ $(SqlClientVersionDefault)-dev
$(SqlClientVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 156c52490f..75ddd248d5 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -85,6 +85,8 @@
$(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj
$(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj
+ $(RepoRoot)/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Versions.props
+ $(RepoRoot)/src/Microsoft.Data.SqlClient.Internal/Logging/src/Versions.props
@@ -126,6 +128,15 @@
+
+
+
+
-
-
-
- "$(DOTNET_HOST_PATH)" msbuild "$(AbstractionsProjectPath)"
- -nologo
- -verbosity:quiet
- -getProperty:AbstractionsPackageVersion
- -p:BuildNumber=$(BuildNumber)
- -p:BuildSuffix=$(BuildSuffix)
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GetAbstractionsPackageVersionCommand), "\s+", " "))
-
-
-
-
-
- $([System.Text.RegularExpressions.Regex]::Replace($(AbstractionsPackageVersion), "\s", ""))
-
-
-
-
-
- "$(DOTNET_HOST_PATH)" msbuild "$(LoggingProjectPath)"
- -nologo
- -verbosity:quiet
- -getProperty:LoggingPackageVersion
- -p:BuildNumber=$(BuildNumber)
- -p:BuildSuffix=$(BuildSuffix)
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GetLoggingPackageVersionCommand), "\s+", " "))
-
-
-
-
-
- $([System.Text.RegularExpressions.Regex]::Replace($(LoggingPackageVersion), "\s", ""))
-
-
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)'))
diff --git a/src/Microsoft.SqlServer.Server/Versions.props b/src/Microsoft.SqlServer.Server/Versions.props
index ec959cafbf..0a342f9426 100644
--- a/src/Microsoft.SqlServer.Server/Versions.props
+++ b/src/Microsoft.SqlServer.Server/Versions.props
@@ -67,9 +67,7 @@
want a quick build without supplying any parameters.
-->
- dev
-
- $(SqlServerVersionDefault)-$(BuildSuffix)
+ $(SqlServerVersionDefault)-dev
$(SqlServerVersionDefault.Split('-')[0]).$(FileVersionBuildNumber)
From 412d8efa921a6fa7a6aec314b2dd920de6e957fb Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 09:34:14 -0300
Subject: [PATCH 11/15] Remove unused nuget downloader script
---
tools/scripts/downloadLatestNuget.ps1 | 27 ---------------------------
1 file changed, 27 deletions(-)
delete mode 100644 tools/scripts/downloadLatestNuget.ps1
diff --git a/tools/scripts/downloadLatestNuget.ps1 b/tools/scripts/downloadLatestNuget.ps1
deleted file mode 100644
index faddf3bb09..0000000000
--- a/tools/scripts/downloadLatestNuget.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the .NET Foundation under one or more agreements.
-# The .NET Foundation licenses this file to you under the MIT license.
-# See the LICENSE file in the project root for more information.
-# Script: downloadLatestNuget.ps1
-# Author: Keerat Singh
-# Date: 07-Dec-2018
-# Comments: This script downloads the latest NuGet Binary.
-#
-param(
- [string]$nugetDestPath,
- [string]$nugetSrcPath="https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
-)
-Function DownloadLatestNuget()
-{
- if(!$nugetDestPath)
- {
- $nugetDestPath = (Get-location).ToString() +'\.nuget\'
- }
- if (!(Test-Path $nugetDestPath))
- {
- New-Item -ItemType Directory -Path $nugetDestPath
- }
- Write-Output "Source: $nugetSrcPath"
- Write-Output "Destination: $nugetDestPath"
- Start-BitsTransfer -Source $nugetSrcPath -Destination $nugetDestPath\nuget.exe
-}
-DownloadLatestNuget
\ No newline at end of file
From 1a41212492ef002549d3adbc81e97e663000aeab Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 10:03:39 -0300
Subject: [PATCH 12/15] Use SDK source revision for SqlClient package commit
metadata
---
build.proj | 30 +++++++------------
.../src/Microsoft.Data.SqlClient.csproj | 12 ++++++--
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/build.proj b/build.proj
index d5492fc15a..14db6015ba 100644
--- a/build.proj
+++ b/build.proj
@@ -86,11 +86,6 @@
--no-build
-
- BuildSqlClient
+
+
+ BuildSqlClient
+
+
-
- git rev-parse HEAD
-
-
- $([System.Text.RegularExpressions.Regex]::Replace($(GitCommand), "\s+", " "))
-
-
-
-
-
-
-
- $([System.Text.RegularExpressions.Regex]::Replace($(CommitId), "\s", ""))
"$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)"
-p:Configuration=$(Configuration)
@@ -554,7 +547,6 @@
$(PackageVersionLoggingArgument)
- -p:CommitId="$(CommitId)"
-p:PackageOutputPath="$(SqlClientArtifactRoot)/$(ReferenceType)-$(Configuration)"
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 75ddd248d5..4f9306d9af 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -111,7 +111,7 @@
version attribute tokens are not reliably substituted and are pre-expanded in
PrepareSqlClientPackNuspec.
-->
- Version=$(Version);COMMITID=$(CommitId);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
+ Version=$(Version);Configuration=$(Configuration);ReferenceType=$(ReferenceType)
true
@@ -165,7 +165,15 @@
* dotnet/sdk#15407
* dotnet/sdk#16816
-->
-
+
+
+
+
+ $(SourceRevisionId)
+ $(NuspecProperties);COMMITID=$(CommitId)
+
From 13f13918bf8e22bd9984a7d2f1a5e9d0e22cef76 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 10:05:29 -0300
Subject: [PATCH 13/15] Removed unnecesary tip section.
---
BUILDGUIDE.md | 3 ---
1 file changed, 3 deletions(-)
diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md
index 8ff965d65b..16aa709fe5 100644
--- a/BUILDGUIDE.md
+++ b/BUILDGUIDE.md
@@ -33,9 +33,6 @@ package the project. The `build.proj` file provides convenient targets to accomp
> may be noticed, possibly severe. All official build and test infrastructure uses the `build.proj` entrypoint, and it
> is recommended that `build.proj` is used for local development, as well.
-> [!TIP]
-> Use `dotnet build` with `build.proj` for local and CI workflows in this repository.
-
> [!TIP]
> This section is not exhaustive of all targets or parameters to `build.proj`. Complete documentation is available in
> [`build.proj`](build.proj).
From c695e0f62b00399cbb1c0ede17e7948edf5a7025 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 10:18:16 -0300
Subject: [PATCH 14/15] Add pack fail-fast checks and align NuspecFile comments
---
.../src/Microsoft.Data.SqlClient.csproj | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 4f9306d9af..a273d19956 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -91,9 +91,9 @@
$(SqlClientPackNuspecTemplatePath)
@@ -122,7 +122,7 @@
true
@@ -173,8 +173,15 @@
$(SourceRevisionId)
$(NuspecProperties);COMMITID=$(CommitId)
+ <_AbstractionsPackageVersionTrimmed>$([System.String]::Copy('$(AbstractionsPackageVersion)').Trim())
+ <_LoggingPackageVersionTrimmed>$([System.String]::Copy('$(LoggingPackageVersion)').Trim())
+
+
+
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)'))
From b52b37a915e293364611fecfee7b570fabbe12f3 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Fri, 8 May 2026 12:11:08 -0300
Subject: [PATCH 15/15] Clarify SqlClient pack diagnostics and nuspec comments
---
.../src/Microsoft.Data.SqlClient.csproj | 4 ++--
.../src/Microsoft.Data.SqlClient.nuspec | 13 ++++++++-----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index a273d19956..edb31ba0b3 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -178,9 +178,9 @@
+ Text="AbstractionsPackageVersion is required for SqlClient packaging. When packing via build.proj, set -p:PackageVersionAbstractions=<version>; when packing the project directly, set -p:AbstractionsPackageVersion=<version>; otherwise ensure the Abstractions Versions.props import can resolve a value." />
+ Text="LoggingPackageVersion is required for SqlClient packaging. When packing via build.proj, set -p:PackageVersionLogging=<version>; when packing the project directly, set -p:LoggingPackageVersion=<version>; otherwise ensure the Logging Versions.props import can resolve a value." />
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec
index 641051dc65..8f04553f94 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec
@@ -29,9 +29,9 @@
sqlclient microsoft.data.sqlclient
@@ -121,8 +121,11 @@