From d7a3c9fb60071742c5f8fcf71a5199a349814465 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 21 Aug 2026 09:21:30 -0300 Subject: [PATCH 1/4] Add assembly signing for Microsoft.SqlServer.Server Introduce the shared signing-key download step and thread isInternalBuild through the CI core so the SqlServer package is strong-name signed on internal Package-mode builds. - Add eng/pipelines/common/steps/download-assembly-signing-key.yml, which exports driverKeyFile or testKeyFile from ADO secure files. - Adopt that step in the OneBranch build and nightly CI package pipelines, renaming keyFile to driverKeyFile. - Declare isInternalBuild in dotnet-sqlclient-ci-core.yml and set it from the CI package- and project-reference pipelines. - Sign the SqlServer package when isInternalBuild is true and referenceType is not Project. --- .../steps/download-assembly-signing-key.yml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 eng/pipelines/common/steps/download-assembly-signing-key.yml diff --git a/eng/pipelines/common/steps/download-assembly-signing-key.yml b/eng/pipelines/common/steps/download-assembly-signing-key.yml new file mode 100644 index 0000000000..0a58703319 --- /dev/null +++ b/eng/pipelines/common/steps/download-assembly-signing-key.yml @@ -0,0 +1,39 @@ +################################################################################ +# 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. +################################################################################ + +# Downloads a signing key from ADO secure files. +# +# When isTest is false, downloads the driver signing key and exports it as 'driverKeyFile'. When +# isTest is true, downloads the test signing key and exports it as 'testKeyFile'. +# +# Downstream steps reference the path via: +# +# $(driverKeyFile.secureFilePath) or +# $(testKeyFile.secureFilePath) + +parameters: + + # When false, download the driver signing key. + # When true, download the test signing key. + - name: isTest + type: boolean + default: false + +steps: + + - ${{ if eq(parameters.isTest, false) }}: + - task: DownloadSecureFile@1 + displayName: Download Driver Signing Key + inputs: + secureFile: netfxKeypair.snk + name: driverKeyFile + + - ${{ else }}: + - task: DownloadSecureFile@1 + displayName: Download Test Signing Key + inputs: + secureFile: sqlclient-test-key.snk + name: testKeyFile From 2d3255cbdbd3ecade9d67ac392070c80ee357cd3 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 26 Aug 2026 07:41:49 -0300 Subject: [PATCH 2/4] Address PR #4566 feedback: split signing key templates, drop defaults - Split download-assembly-signing-key.yml into download-driver-signing-key-step.yml and download-test-signing-key-step.yml, each parameterless with its own output. - Restore "strong-name signing" terminology; always name the driver or test key. - Remove parameter defaults added in this branch; pass values explicitly, including isInternalBuild: false in both PR pipelines. - Fold the driver key download into the existing signing conditional in the pack job. --- .../steps/download-assembly-signing-key.yml | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 eng/pipelines/common/steps/download-assembly-signing-key.yml diff --git a/eng/pipelines/common/steps/download-assembly-signing-key.yml b/eng/pipelines/common/steps/download-assembly-signing-key.yml deleted file mode 100644 index 0a58703319..0000000000 --- a/eng/pipelines/common/steps/download-assembly-signing-key.yml +++ /dev/null @@ -1,39 +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. -################################################################################ - -# Downloads a signing key from ADO secure files. -# -# When isTest is false, downloads the driver signing key and exports it as 'driverKeyFile'. When -# isTest is true, downloads the test signing key and exports it as 'testKeyFile'. -# -# Downstream steps reference the path via: -# -# $(driverKeyFile.secureFilePath) or -# $(testKeyFile.secureFilePath) - -parameters: - - # When false, download the driver signing key. - # When true, download the test signing key. - - name: isTest - type: boolean - default: false - -steps: - - - ${{ if eq(parameters.isTest, false) }}: - - task: DownloadSecureFile@1 - displayName: Download Driver Signing Key - inputs: - secureFile: netfxKeypair.snk - name: driverKeyFile - - - ${{ else }}: - - task: DownloadSecureFile@1 - displayName: Download Test Signing Key - inputs: - secureFile: sqlclient-test-key.snk - name: testKeyFile From fdb3eb45da1f6fa103616358baab9c8c9d1c415b Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:34:33 -0300 Subject: [PATCH 3/4] Add assembly signing for Microsoft.Data.SqlClient.Extensions.Azure Sign the Azure package and its test assembly on internal Package-mode builds. Azure references Abstractions and Logging, both of which are signed earlier in this stack, so the reference closure is complete. - Thread isInternalBuild from the CI core into the Azure stage, pack job and test jobs, downloading the driver and test signing keys as needed. - Add a signed InternalsVisibleTo grant for the Azure test assembly, which needs internal access for the WAM broker tests, and sign that assembly when a test key is supplied. - Thread signing arguments into the build.proj TestAzure target. - Rename the test job's buildArguments variable to dotnetBuildOpts; Azure Pipelines exposes variables as environment variables and the dotnet CLI injects BUILDARGUMENTS into dotnet build. --- build.proj | 8 +++- eng/pipelines/dotnet-sqlclient-ci-core.yml | 1 + .../jobs/pack-azure-package-ci-job.yml | 23 ++++++++++- .../jobs/test-azure-package-ci-job.yml | 38 +++++++++++++++---- .../stages/build-azure-package-ci-stage.yml | 9 +++++ .../Azure/src/Azure.csproj | 12 ++++++ .../Azure/test/Azure.Test.csproj | 8 +++- 7 files changed, 89 insertions(+), 10 deletions(-) diff --git a/build.proj b/build.proj index ef8ef1947c..6c319599d2 100644 --- a/build.proj +++ b/build.proj @@ -1221,7 +1221,13 @@ "$(DotnetPath)dotnet" test "$(AzureTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) @@ -1229,7 +1235,7 @@ --results-directory "$(TestResultsFolderPath)" --logger:"trx;LogFilePrefix=$(LogFilePrefix)" - + $(ReferenceTypeArgument) $(PackageVersionSqlClientArgument) $(PackageVersionSqlServerArgument) diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 1dca45f32c..653374b85e 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -269,6 +269,7 @@ stages: azureArtifactsName: $(azureArtifactsName) buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} + isInternalBuild: ${{ parameters.isInternalBuild }} # When building via packages, we must depend on the Abstractions, Logging, # SqlServer, and MDS packages. ${{ if eq(parameters.referenceType, 'Package') }}: diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 884d4a5c32..8359434360 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -85,6 +85,10 @@ parameters: - name: poolImage type: string + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + jobs: - job: pack_azure_package_job @@ -155,12 +159,29 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. # # 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') }}: + - ${{ if and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + # BuildNumber supplies the revision component of FileVersion; without + # it the assembly is stamped Major.Minor.Patch.0 (see Project branch). + buildProperties: SqlClientPackageVersion=${{ parameters.packageVersion }};ReferenceType=Package;BuildNumber=$(Build.BuildNumber);SigningKeyPath=$(driverKeyFile.secureFilePath) + + - ${{ elseif eq(parameters.referenceType, 'Package') }}: - task: DotNetCoreCLI@2 displayName: Create NuGet Package inputs: diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index e927eb6e6e..c0992ea50a 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -125,6 +125,11 @@ parameters: type: stepList default: [] + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + # The pool VM image to use. - name: poolImage type: string @@ -152,8 +157,10 @@ jobs: - name: project value: src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj - # dotnet CLI arguments for build/test/pack commands. - - name: buildArguments + # dotnet CLI arguments for build/test commands. + # + # Not named 'buildArguments': dotnet injects $BUILDARGUMENTS into 'dotnet build'. + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} @@ -161,6 +168,16 @@ jobs: -p:SqlClientPackageVersion=${{ parameters.packageVersion }} -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + # Signing arguments - only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), eq(parameters.referenceType, 'Package')) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + # Explicitly unset the $PLATFORM environment variable that is set by the # 'ADO Build properties' Library in the ADO SqlClientDrivers public # project. This is defined with a non-standard Platform of 'AnyCPU', and @@ -230,6 +247,13 @@ jobs: debug: ${{ parameters.debug }} runtimes: [8.x, 9.x] + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), eq(parameters.referenceType, 'Package')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + # The Windows agent images include a suitable .NET Framework runtime, so # we don't have to install one explicitly. @@ -270,7 +294,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # List the DLLs in the output directory for debugging purposes. - ${{ if eq(parameters.debug, true) }}: @@ -305,7 +329,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -323,7 +347,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -343,7 +367,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -361,7 +385,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml index 1f502a5fee..fa42f2e196 100644 --- a/eng/pipelines/stages/build-azure-package-ci-stage.yml +++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml @@ -112,6 +112,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_azure_package_stage @@ -148,6 +153,7 @@ stages: displayNamePrefix: Linux Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} jobNameSuffix: linux_integration + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} @@ -177,6 +183,7 @@ stages: displayNamePrefix: Win Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} jobNameSuffix: windows_integration + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} @@ -212,6 +219,7 @@ stages: displayNamePrefix: macOS dotnetVerbosity: ${{ parameters.dotnetVerbosity }} jobNameSuffix: macos + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} @@ -245,3 +253,4 @@ stages: dotnetVerbosity: ${{ parameters.dotnetVerbosity }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj index da0a4cb4c7..8734cc2ccb 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj @@ -33,10 +33,22 @@ + + + + + + + $(RepoRoot)artifacts/ diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index 79372ca2d8..ea8045d130 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -13,12 +13,18 @@ net462;net8.0;net9.0;net10.0 + + + + true + $(TestSigningKeyPath) + + enable enable - From ac4dd9691aee2d421b88de379311dae8c454dbcb Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:40:22 -0300 Subject: [PATCH 4/4] Apply PR #4566/#4567 feedback to the Azure jobs Pre-emptively align this PR with the review feedback already addressed lower in the stack, so the same comments aren't raised again. - Reference the split download-driver-signing-key-step.yml and download-test-signing-key-step.yml templates instead of the removed download-assembly-signing-key.yml. - Quote SigningKeyPath and TestSigningKeyPath to tolerate whitespace in the secure file paths. - Fold the driver key download into the existing signing conditional in the pack job, removing the duplicated conditional. - Use positive referenceType comparisons (eq 'Package'). - Drop the isInternalBuild parameter defaults; every caller already passes it explicitly. - Normalize the BuildNumber/FileVersion note across all pack branches. - Restore an accidentally dropped blank line in Azure.Test.csproj. --- .../jobs/pack-azure-package-ci-job.yml | 26 +++++++++---------- .../jobs/test-azure-package-ci-job.yml | 14 +++++----- .../stages/build-azure-package-ci-stage.yml | 1 - .../Azure/test/Azure.Test.csproj | 1 + 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 8359434360..daa76e9560 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -159,16 +159,15 @@ jobs: parameters: debug: ${{ parameters.debug }} - # Download the assembly signing key for internal Package-mode builds. - - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: - - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - - # Create the NuGet packages. + # Create the NuGet packages. Internal Package-mode builds strong-name sign the assemblies + # with the driver key. # # 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 and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + - ${{ if and(eq(parameters.isInternalBuild, true), eq(parameters.referenceType, 'Package')) }}: + - template: /eng/pipelines/common/steps/download-driver-signing-key-step.yml@self + - task: DotNetCoreCLI@2 displayName: Create NuGet Package inputs: @@ -177,9 +176,10 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - # BuildNumber supplies the revision component of FileVersion; without - # it the assembly is stamped Major.Minor.Patch.0 (see Project branch). - buildProperties: SqlClientPackageVersion=${{ parameters.packageVersion }};ReferenceType=Package;BuildNumber=$(Build.BuildNumber);SigningKeyPath=$(driverKeyFile.secureFilePath) + # BuildNumber supplies the revision component of FileVersion + # (Major.Minor.Patch.Revision). Without it, FileVersionBuildNumber + # defaults to 0 and the assembly is stamped Major.Minor.Patch.0. + buildProperties: SqlClientPackageVersion=${{ parameters.packageVersion }};ReferenceType=Package;BuildNumber=$(Build.BuildNumber);SigningKeyPath="$(driverKeyFile.secureFilePath)" - ${{ elseif eq(parameters.referenceType, 'Package') }}: - task: DotNetCoreCLI@2 @@ -190,8 +190,9 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - # BuildNumber supplies the revision component of FileVersion; without - # it the assembly is stamped Major.Minor.Patch.0 (see Project branch). + # BuildNumber supplies the revision component of FileVersion + # (Major.Minor.Patch.Revision). Without it, FileVersionBuildNumber + # defaults to 0 and the assembly is stamped Major.Minor.Patch.0. buildProperties: SqlClientPackageVersion=${{ parameters.packageVersion }};ReferenceType=Package;BuildNumber=$(Build.BuildNumber) - ${{ else }}: @@ -205,8 +206,7 @@ jobs: verbosityToPack: ${{ parameters.dotnetVerbosity }} # BuildNumber supplies the revision component of FileVersion # (Major.Minor.Patch.Revision). Without it, FileVersionBuildNumber - # defaults to 0 and the assembly is stamped Major.Minor.Patch.0, - # inconsistent with the MDS/AKV packages that pass it. + # defaults to 0 and the assembly is stamped Major.Minor.Patch.0. buildProperties: SqlClientPackageVersion=${{ parameters.packageVersion }};BuildNumber=$(Build.BuildNumber) # Publish the NuGet packages as a named pipeline artifact. diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index c0992ea50a..c317d8563e 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -168,12 +168,12 @@ jobs: -p:SqlClientPackageVersion=${{ parameters.packageVersion }} -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} - # Signing arguments - only set for internal Package-mode builds. + # Strong-name signing arguments - only set for internal Package-mode builds. - ${{ if and(eq(parameters.isInternalBuild, true), eq(parameters.referenceType, 'Package')) }}: - name: signingArguments value: >- - -p:SigningKeyPath=$(driverKeyFile.secureFilePath) - -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + -p:SigningKeyPath="$(driverKeyFile.secureFilePath)" + -p:TestSigningKeyPath="$(testKeyFile.secureFilePath)" - ${{ else }}: - name: signingArguments value: '' @@ -247,12 +247,10 @@ jobs: debug: ${{ parameters.debug }} runtimes: [8.x, 9.x] - # Download the assembly signing keys for internal Package-mode builds. + # Download the driver and test strong-name signing keys for internal Package-mode builds. - ${{ if and(eq(parameters.isInternalBuild, true), eq(parameters.referenceType, 'Package')) }}: - - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - parameters: - isTest: true + - template: /eng/pipelines/common/steps/download-driver-signing-key-step.yml@self + - template: /eng/pipelines/common/steps/download-test-signing-key-step.yml@self # The Windows agent images include a suitable .NET Framework runtime, so # we don't have to install one explicitly. diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml index fa42f2e196..40ea42de71 100644 --- a/eng/pipelines/stages/build-azure-package-ci-stage.yml +++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml @@ -115,7 +115,6 @@ parameters: # True when building on the internal ADO.Net project. - name: isInternalBuild type: boolean - default: false stages: diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index ea8045d130..9b294a4f98 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -25,6 +25,7 @@ enable enable +