From 8dcc62d265ddff978299bde77b6dd028eb4bd105 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:03:07 -0400 Subject: [PATCH 01/12] Fixed pipeilne issues for ADO.Net pipelines. --- .../common/templates/jobs/build-signed-package-job.yml | 7 +++++-- eng/pipelines/common/templates/steps/code-analyze-step.yml | 2 +- eng/pipelines/jobs/test-azure-package-ci-job.yml | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml index 22e6758c3e..35c3a284a5 100644 --- a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml @@ -36,9 +36,12 @@ jobs: - script: SET displayName: 'Print Environment Variables' - - powershell: | + - pwsh: | Write-Host "##vso[task.setvariable variable=CDP_BUILD_TYPE_COPY;isOutput=true]$($env:CDP_BUILD_TYPE)" - name: GetBuildType + displayName: Get Build Type + + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self # Install the .NET SDK. - template: /eng/pipelines/steps/install-dotnet.yml@self diff --git a/eng/pipelines/common/templates/steps/code-analyze-step.yml b/eng/pipelines/common/templates/steps/code-analyze-step.yml index ec226e134c..3ee9b4e92e 100644 --- a/eng/pipelines/common/templates/steps/code-analyze-step.yml +++ b/eng/pipelines/common/templates/steps/code-analyze-step.yml @@ -32,7 +32,7 @@ steps: msBuildCommandline: >- msbuild ${{parameters.sourceRoot}}\build.proj + -t:BuildAllConfigurations -p:configuration=Release -p:GenerateNuget=false -p:BuildTools=false - -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index 2d2da14435..93b8b60132 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -273,10 +273,10 @@ jobs: # List the DLLs in the output directory for debugging purposes. - ${{ if eq(parameters.debug, true) }}: - - pwsh: > + - pwsh: >- Get-ChildItem - -Path "src/Microsoft.Data.SqlClient.Extensions/Azure/test/bin/${{ parameters.buildConfiguration }}" - -Recurse + -Path "src/Microsoft.Data.SqlClient.Extensions/Azure/test/bin/${{ parameters.buildConfiguration }}" + -Recurse displayName: '[Debug] List Output DLLs' # Run the tests for each .NET runtime. From 9f7a47a2c0357974f93d6a567956063220ec7268 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:09:07 -0400 Subject: [PATCH 02/12] Fixed AKV pipeline errors in the ADO.Net pipelines. --- eng/pipelines/jobs/build-akv-official-job.yml | 3 +++ eng/pipelines/steps/compound-build-akv-step.yml | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/jobs/build-akv-official-job.yml b/eng/pipelines/jobs/build-akv-official-job.yml index fab4c1aa9c..c7ed0a7354 100644 --- a/eng/pipelines/jobs/build-akv-official-job.yml +++ b/eng/pipelines/jobs/build-akv-official-job.yml @@ -89,6 +89,9 @@ jobs: $jsonParams | ConvertFrom-Json | Format-List displayName: 'Output Job Parameters' + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self + # Perform analysis before building, since this step will clobber build # output. - template: /eng/pipelines/steps/roslyn-analyzers-akv-step.yml@self diff --git a/eng/pipelines/steps/compound-build-akv-step.yml b/eng/pipelines/steps/compound-build-akv-step.yml index 53b3d32371..9cb977ca34 100644 --- a/eng/pipelines/steps/compound-build-akv-step.yml +++ b/eng/pipelines/steps/compound-build-akv-step.yml @@ -31,9 +31,6 @@ steps: retryCount: 5 secureFile: 'netfxKeypair.snk' - # Install the .NET SDK. - - template: /eng/pipelines/steps/install-dotnet.yml@self - - task: MSBuild@1 displayName: 'Build.proj - BuildAkv' inputs: @@ -46,6 +43,6 @@ steps: -p:MdsPackageVersion=${{ parameters.mdsPackageVersion }} -p:ReferenceType=Package -p:SigningKeyPath=$(Agent.TempDirectory)/netfxKeypair.snk - + - script: tree /a /f $(BUILD_OUTPUT) displayName: Output Build Output Tree From 9a275d3099a913a60bc4c7108d0994fbc91283a0 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 26 Jan 2026 16:24:38 -0400 Subject: [PATCH 03/12] Added missing Abstractions package version to MDS NuGet generation. --- eng/pipelines/common/templates/jobs/build-signed-package-job.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml index 35c3a284a5..d3beb8c2c1 100644 --- a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml @@ -81,6 +81,7 @@ jobs: packageVersion: $(mdsPackageVersion) properties: 'AbstractionsPackageVersion=$(abstractionsPackageVersion)' referenceType: Package + properties: 'AbstractionsPackageVersion=$(abstractionsPackageVersion)' - template: /eng/pipelines/common/templates/steps/esrp-code-signing-step.yml@self parameters: From 719dba632e2175f1afa1b61ce7e8d28b692bb404 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:00:50 -0400 Subject: [PATCH 04/12] Fixed official pipeline validation artifact download. --- .../jobs/validate-signed-package-job.yml | 28 ++++--------------- .../SqlAuthenticationProviderManagerTests.cs | 4 +-- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml index 6dba0a8eab..b4655dabba 100644 --- a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml @@ -4,26 +4,9 @@ # See the LICENSE file in the project root for more information. # ################################################################################# parameters: - - name: downloadPackageStep - type: step - default: - script: echo - name: packageFolderName type: string - default: drop_build_build_signed_package - - - name: dependsOn - type: string - default: '' - - - name: packageType - type: string - default: both - values: - - dll - - pdb - - both - name: isPreview type: boolean @@ -31,8 +14,7 @@ parameters: jobs: - job: validate_signed_package displayName: 'Verify signed package' - ${{ if ne(parameters.dependsOn, '')}}: - dependsOn: '${{parameters.dependsOn }}' + pool: type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs isCustom: true @@ -69,7 +51,10 @@ jobs: nuget locals all -Clear displayName: 'Clear local cache' - - ${{parameters.downloadPackageStep }} + - download: current + artifact: ${{parameters.packageFolderName}} + patterns: '**/*.*nupkg' + displayName: 'Download NuGet Package' - powershell: | # Install nuget package @@ -82,9 +67,6 @@ jobs: displayName: 'Extract Nuget in temp folder' - powershell: | - # Artifact is stored in the Nuget folder - $packageType = '${{parameters.packageType}}' - Write-Host "--------------------------------------------------" Write-Host "This will verify the artifact signature" -ForegroundColor Green Write-Host "--------------------------------------------------" diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlAuthenticationProviderManagerTests.cs b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlAuthenticationProviderManagerTests.cs index 5409b0f7e4..778d69991b 100644 --- a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlAuthenticationProviderManagerTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/SqlAuthenticationProviderManagerTests.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Xunit; -namespace Microsoft.Data.SqlClient.Test.UnitTests; +namespace Microsoft.Data.SqlClient.UnitTests; public class SqlAuthenticationProviderManagerTests { @@ -67,7 +67,7 @@ public void Abstractions_And_Manager_GetSetProvider_Equivalent() provider2, SqlAuthenticationProviderManager.GetProvider( SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow)); - + Assert.Same( provider2, SqlAuthenticationProvider.GetProvider( From 16e6d6f4d69b5999ad9ddad6945179a18d1010f3 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:38:16 -0400 Subject: [PATCH 05/12] Addressed comments from Copilot in previous PRs. --- .github/workflows/codeql.yml | 11 +++++++++-- eng/pipelines/sqlclient-pr-package-ref-pipeline.yml | 2 +- eng/pipelines/sqlclient-pr-project-ref-pipeline.yml | 2 +- .../src/SqlAuthenticationProviderException.cs | 4 ++-- .../src/ActiveDirectoryAuthenticationProvider.cs | 9 ++++++++- .../Azure/test/StringExtensions.cs | 1 + 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d30ed765c2..65b66fda31 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,10 +12,17 @@ name: "CodeQL Advanced" on: + # Scan on pushes to the default branch and any protected branches. push: - branches: [ "main", "feat/*", "dev/**/*" ] + + # Scan on PRs that target matching branches. pull_request: - branches: [ "main", "feat/*", "dev/**/*" ] + branches: + - main + - feat/** + - dev/** + + # Scan weekly on Saturdays at 23:33 UTC schedule: - cron: '33 23 * * 6' diff --git a/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml b/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml index b875aa2cfe..b88a5b6895 100644 --- a/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml +++ b/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml @@ -30,7 +30,7 @@ pr: branches: include: # GitHub repo branch targets that will trigger PR validation builds. - - dev/**/* + - dev/* - feat/* - main diff --git a/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml b/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml index b8f13f31aa..59c0945257 100644 --- a/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml +++ b/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml @@ -30,7 +30,7 @@ pr: branches: include: # GitHub repo branch targets that will trigger PR validation builds. - - dev/**/* + - dev/* - feat/* - main diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProviderException.cs b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProviderException.cs index ebcd89fa0c..30209f70ce 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProviderException.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProviderException.cs @@ -11,7 +11,7 @@ public abstract class SqlAuthenticationProviderException : Exception /// The string value used when the failure code is not known. /// private const string Unknown = "Unknown"; - + /// protected SqlAuthenticationProviderException( string message, @@ -37,7 +37,7 @@ protected SqlAuthenticationProviderException( Method = method; FailureCode = failureCode; ShouldRetry = shouldRetry; - RetryPeriod = shouldRetry && retryPeriod > 0? retryPeriod : 0; + RetryPeriod = (shouldRetry && retryPeriod > 0) ? retryPeriod : 0; } /// diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs index f383ca600f..374d32f443 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs @@ -365,7 +365,14 @@ previousPw is byte[] previousPwBytes && { if (retryAfter.Delta.HasValue) { - retryPeriod = retryAfter.Delta.Value.Milliseconds; + if (retryAfter.Delta.Value.TotalMilliseconds > int.MaxValue) + { + retryPeriod = int.MaxValue; + } + else + { + retryPeriod = Convert.ToInt32(retryAfter.Delta.Value.TotalMilliseconds); + } } else if (retryAfter.Date.HasValue) { diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs index fc7801ee78..513224df0f 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs @@ -6,6 +6,7 @@ /// Adds the missing IsEmpty() method to string that doesn't waste time on null checks like /// String.IsNullOrEmpty() does, and has a nice shorter name. /// +/// The string to check; must not be null internal static class StringExtensions { internal static bool IsEmpty(this string str) From b2112704c5ae2196a91b08ee230d6c012ca85aa5 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 28 Jan 2026 08:12:58 -0400 Subject: [PATCH 06/12] Addressed Copilot suggestions. --- .github/workflows/codeql.yml | 4 +- .../jobs/build-signed-package-job.yml | 2 + .../jobs/validate-signed-package-job.yml | 2 + .../ActiveDirectoryAuthenticationProvider.cs | 37 ++++++++++--------- .../Azure/test/StringExtensions.cs | 10 +++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 65b66fda31..987e96f345 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,8 +12,10 @@ name: "CodeQL Advanced" on: - # Scan on pushes to the default branch and any protected branches. + # Scan on pushes to main only. push: + branches: + - main # Scan on PRs that target matching branches. pull_request: diff --git a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml index d3beb8c2c1..dfe7c1eef9 100644 --- a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml @@ -38,6 +38,8 @@ jobs: - pwsh: | Write-Host "##vso[task.setvariable variable=CDP_BUILD_TYPE_COPY;isOutput=true]$($env:CDP_BUILD_TYPE)" + # This variable is used far away in validate-signed-packages-job.yml. + name: GetBuildType displayName: Get Build Type # Install the .NET SDK. diff --git a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml index b4655dabba..11a5d530ec 100644 --- a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml @@ -28,6 +28,8 @@ jobs: value: $(Pipeline.Workspace)\${{parameters.packageFolderName }} - name: BuildType + # This variable is set in the build-signed-package-job.yml job. Any changes + # to the names of the stage, job, or variable must be reflected here. value: $[ stageDependencies.buildMDS.build_signed_package.outputs['GetBuildType.CDP_BUILD_TYPE_COPY'] ] - ${{ if parameters.isPreview }}: diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs index 374d32f443..fcbb630683 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs @@ -358,27 +358,28 @@ previousPw is byte[] previousPwBytes && if (ex is MsalServiceException svcEx && svcEx.StatusCode == MsalRetryStatusCode) { - int retryPeriod = 0; - var retryAfter = svcEx.Headers.RetryAfter; if (retryAfter is not null) { - if (retryAfter.Delta.HasValue) - { - if (retryAfter.Delta.Value.TotalMilliseconds > int.MaxValue) - { - retryPeriod = int.MaxValue; - } - else - { - retryPeriod = Convert.ToInt32(retryAfter.Delta.Value.TotalMilliseconds); - } - } - else if (retryAfter.Date.HasValue) - { - retryPeriod = Convert.ToInt32(retryAfter.Date.Value.Offset.TotalMilliseconds); - } - + // Prefer the Delta value over Date. + double totalMilliseconds = + retryAfter.Delta.HasValue + ? retryAfter.Delta.Value.TotalMilliseconds + : retryAfter.Date.HasValue + ? retryAfter.Date.Value.Offset.TotalMilliseconds + : 0; + + int retryPeriod = + // Ignore negative values. + totalMilliseconds <= 0 + ? 0 + // Avoid overflow when converting to an int. + : totalMilliseconds > int.MaxValue + ? int.MaxValue + // Convert from double to int safely. + : Convert.ToInt32(totalMilliseconds); + + // Report the retryable error. throw new Extensions.Azure.AuthenticationException( parameters.AuthenticationMethod, ex.ErrorCode, diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs index 513224df0f..a3045d579e 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/StringExtensions.cs @@ -3,12 +3,16 @@ // See the LICENSE file in the project root for more information. /// -/// Adds the missing IsEmpty() method to string that doesn't waste time on null checks like -/// String.IsNullOrEmpty() does, and has a nice shorter name. +/// String extensions used by our tests. /// -/// The string to check; must not be null internal static class StringExtensions { + /// + /// Adds the IsEmpty() method to string that doesn't waste time on null checks + /// like String.IsNullOrEmpty() does, and has a nice short name. + /// + /// The string to check; must not be null. + /// True if the string is empty, false otherwise. internal static bool IsEmpty(this string str) { return str.Length == 0; From faecd74a5308bae7b64f2bfab23b51474883f30b Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:45:33 -0400 Subject: [PATCH 07/12] Task 41895: Complete Step 4 PR - Addressed comments from Step 3 PR. --- Directory.Packages.props | 4 +++- .../Azure/src/Azure.csproj | 1 + .../Connection/SqlConnectionInternal.cs | 23 +++++++++++++++++++ tools/specs/Microsoft.Data.SqlClient.nuspec | 8 ------- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c0637bf065..d94e5a29d1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -87,7 +87,6 @@ - @@ -117,6 +116,9 @@ + + + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj index 4fd4d4860e..c22bfdce3c 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj @@ -95,6 +95,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs index ffc411b8c0..4f254a1ba6 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs @@ -2864,6 +2864,20 @@ private SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) // Fall through to retry... } + // If the provider throws anything else, it's an API violation, which we must + // consume to avoid breaking our API promise. + catch (Exception ex) + { + throw ADP.CreateSqlException( + new ProviderApiViolationException( + message: + "API violation; provider threw unexpected exception " + + ex.GetType().FullName + ": " + ex.Message, + causedBy: ex), + ConnectionOptions, + this, + username); + } } // Nullable context has exposed that _fedAuthToken may be null here, @@ -2891,6 +2905,15 @@ private SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) return _fedAuthToken; } + // Thrown when an authentication provider violates the expected API contract. + private class ProviderApiViolationException : SqlAuthenticationProviderException + { + public ProviderApiViolationException(string message, Exception causedBy) + : base(message, causedBy) + { + } + } + #nullable disable private void Login( diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 079e16d41c..01bcaa1aa2 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -36,8 +36,6 @@ - - @@ -54,8 +52,6 @@ - - @@ -67,8 +63,6 @@ - - @@ -80,8 +74,6 @@ - - From 26031e455550c56d0685e2a195365f127ead3e9c Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 10 Feb 2026 08:36:52 -0400 Subject: [PATCH 08/12] Task 41895: Complete Step 4 PR - Addressed Copilot comments from Step 3 PR. --- .../Data/SqlClient/Connection/SqlConnectionInternal.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs index 4f254a1ba6..49be561e8b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs @@ -2845,7 +2845,10 @@ private SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) if (_timeout.IsExpired || _timeout.MillisecondsRemaining <= 0) { // No, so we throw. - SqlClientEventSource.Log.TryTraceEvent(" Attempt: {0}, Timeout: {1}", attempt, ex.FailureCode); + SqlClientEventSource.Log.TryTraceEvent( + " Attempt: {0}, FailureCode: {1}", + attempt, + ex.FailureCode); throw SQL.ActiveDirectoryTokenRetrievingTimeout(Enum.GetName(typeof(SqlAuthenticationMethod), ConnectionOptions.Authentication), ex.FailureCode, ex); } From 029f54da27ec66de0f0b546712afd8f3d0688655 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:23:05 -0400 Subject: [PATCH 09/12] Task 41895: Complete Step 4 PR - Addressed Copilot comments. --- .../jobs/build-signed-package-job.yml | 4 ---- .../ActiveDirectoryAuthenticationProvider.cs | 22 +++++++++++++------ .../Connection/SqlConnectionInternal.cs | 8 +++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml index dfe7c1eef9..bf5ee07ebb 100644 --- a/eng/pipelines/common/templates/jobs/build-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/build-signed-package-job.yml @@ -45,9 +45,6 @@ jobs: # Install the .NET SDK. - template: /eng/pipelines/steps/install-dotnet.yml@self - # Install the .NET SDK. - - template: /eng/pipelines/steps/install-dotnet.yml@self - # Build our tooling, which is required by the analysis step below, but # shouldn't be analyzed itself. - task: MSBuild@1 @@ -83,7 +80,6 @@ jobs: packageVersion: $(mdsPackageVersion) properties: 'AbstractionsPackageVersion=$(abstractionsPackageVersion)' referenceType: Package - properties: 'AbstractionsPackageVersion=$(abstractionsPackageVersion)' - template: /eng/pipelines/common/templates/steps/esrp-code-signing-step.yml@self parameters: diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs index fcbb630683..03222adf61 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/ActiveDirectoryAuthenticationProvider.cs @@ -362,15 +362,23 @@ previousPw is byte[] previousPwBytes && if (retryAfter is not null) { // Prefer the Delta value over Date. - double totalMilliseconds = - retryAfter.Delta.HasValue - ? retryAfter.Delta.Value.TotalMilliseconds - : retryAfter.Date.HasValue - ? retryAfter.Date.Value.Offset.TotalMilliseconds - : 0; + double totalMilliseconds = 0; + + if (retryAfter.Delta.HasValue) + { + totalMilliseconds = retryAfter.Delta.Value.TotalMilliseconds; + } + else if (retryAfter.Date.HasValue) + { + var now = DateTimeOffset.UtcNow; + if (retryAfter.Date.Value > now) + { + totalMilliseconds = (retryAfter.Date.Value - now).TotalMilliseconds; + } + } int retryPeriod = - // Ignore negative values. + // Ignore nonsensical values. totalMilliseconds <= 0 ? 0 // Avoid overflow when converting to an int. diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs index 49be561e8b..35367ed82b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs @@ -2871,6 +2871,14 @@ private SqlFedAuthToken GetFedAuthToken(SqlFedAuthInfo fedAuthInfo) // consume to avoid breaking our API promise. catch (Exception ex) { + // Some exceptions should escape as-is. + if (! ADP.IsCatchableExceptionType(ex)) + { + throw; + } + + // Wrap the exception in a SqlAuthenticationProviderException to maintain our + // API promise. throw ADP.CreateSqlException( new ProviderApiViolationException( message: From a01354cf3ca7fb99cd6a19b7b7e63c64096f0c0c Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 12 Feb 2026 07:38:25 -0400 Subject: [PATCH 10/12] Task 41895: Complete Step 4 PR - Addressed comments in the PR. --- Directory.Packages.props | 1 - 1 file changed, 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index d94e5a29d1..e4953215a7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -115,7 +115,6 @@ - From d4fb1cbf4709c5446c7065a580e15eb063c86754 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 12 Feb 2026 08:52:54 -0400 Subject: [PATCH 11/12] Task 41895: Complete Step 4 PR - Addressed Copilot comments. --- .../jobs/run-tests-package-reference-job.yml | 17 +++++++---------- .../jobs/validate-signed-package-job.yml | 6 +++--- .../dotnet-sqlclient-signing-pipeline.yml | 13 ++----------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml index a6e7755c6b..6d07e60ff7 100644 --- a/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml +++ b/eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml @@ -4,14 +4,9 @@ # See the LICENSE file in the project root for more information. # ################################################################################# parameters: - - name: downloadPackageStep - type: step - default: - script: echo - - name: dependsOn + - name: artifactName type: string - default: empty - name: isPreview type: boolean @@ -21,10 +16,9 @@ parameters: type: number jobs: + - job: run_tests_package_reference displayName: 'Run tests with package reference' - ${{ if ne(parameters.dependsOn, 'empty')}}: - dependsOn: '${{parameters.dependsOn }}' # Some of our tests take longer than the default 60 minutes to run on some # OSes and configurations. @@ -42,7 +36,10 @@ jobs: steps: - template: /eng/pipelines/common/templates/steps/pre-build-step.yml - - ${{parameters.downloadPackageStep }} + - download: current + artifact: ${{parameters.artifactName}} + patterns: '**/*.*nupkg' + displayName: 'Download NuGet Package' - template: /eng/pipelines/common/templates/steps/update-config-file-step.yml parameters: @@ -52,7 +49,7 @@ jobs: - template: /eng/pipelines/common/templates/steps/prepare-test-db-step.yml -# build & test + # build & test - template: /eng/pipelines/common/templates/steps/build-and-run-tests-netfx-step.yml parameters: ${{ if parameters.isPreview }}: diff --git a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml index 11a5d530ec..e1f7bb09b1 100644 --- a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml @@ -5,7 +5,7 @@ ################################################################################# parameters: - - name: packageFolderName + - name: artifactName type: string - name: isPreview @@ -25,7 +25,7 @@ jobs: - template: /eng/pipelines/libraries/mds-validation-variables.yml@self - name: pathToDownloadedNuget # path to the downloaded nuget files - value: $(Pipeline.Workspace)\${{parameters.packageFolderName }} + value: $(Pipeline.Workspace)\${{parameters.artifactName }} - name: BuildType # This variable is set in the build-signed-package-job.yml job. Any changes @@ -54,7 +54,7 @@ jobs: displayName: 'Clear local cache' - download: current - artifact: ${{parameters.packageFolderName}} + artifact: ${{parameters.artifactName}} patterns: '**/*.*nupkg' displayName: 'Download NuGet Package' diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index 78c0f230b6..2c27a1c407 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -159,21 +159,12 @@ extends: jobs: - template: /eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self parameters: - packageFolderName: $(mdsArtifactName) + artifactName: $(mdsArtifactName) isPreview: ${{ parameters['isPreview'] }} - downloadPackageStep: - download: current - artifact: $(mdsArtifactName) - patterns: '**/*.*nupkg' - displayName: 'Download NuGet Package' # Disabling as of 10/15/2025 due to OneBranch apparently disallowing MSBuild tasks in validation stages. # - template: /eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self # parameters: +# artifactName: $(mdsArtifactName) # isPreview: ${{ parameters['isPreview'] }} # timeout: ${{ parameters.testJobTimeout }} -# downloadPackageStep: -# download: current -# artifact: $(mdsArtifactName) -# patterns: '**/*.nupkg' -# displayName: 'Download NuGet Package' From 11465b50c4b81f8e8da7a07982539273b0fea4e0 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 12 Feb 2026 08:54:38 -0400 Subject: [PATCH 12/12] Task 41895: Complete Step 4 PR - Fixed nuget verification steps. --- .../templates/jobs/validate-signed-package-job.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml index e1f7bb09b1..237d4798f6 100644 --- a/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/common/templates/jobs/validate-signed-package-job.yml @@ -73,14 +73,8 @@ jobs: Write-Host "This will verify the artifact signature" -ForegroundColor Green Write-Host "--------------------------------------------------" - if ($packageType -eq 'dll' -or $packageType -eq 'both') - { - nuget verify -All $(pathToDownloadedNuget)\*.nupkg - } - if ($packageType -eq 'pdb' -or $packageType -eq 'both') - { - nuget verify -All $(pathToDownloadedNuget)\*.snupkg - } + nuget verify -All $(pathToDownloadedNuget)\*.nupkg + nuget verify -All $(pathToDownloadedNuget)\*.snupkg displayName: 'Verify nuget signature' - powershell: |