From a51b08c06e6612d89040c3105142ad2b620f388c Mon Sep 17 00:00:00 2001 From: Apoorv Deshmukh Date: Wed, 25 Feb 2026 21:03:59 +0530 Subject: [PATCH 1/3] Use logging package for azure and abstractions --- BUILDGUIDE.md | 14 ++++-- build.proj | 4 +- .../Abstractions/src/Abstractions.csproj | 13 +++++- .../src/SqlAuthenticationProvider.Internal.cs | 4 +- .../ActiveDirectoryAuthenticationProvider.cs | 44 ++----------------- .../Azure/src/Azure.csproj | 13 +++++- tools/targets/GenerateMdsPackage.targets | 2 +- 7 files changed, 42 insertions(+), 52 deletions(-) diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 3b3d1e8b4d..f035d9a12a 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -65,13 +65,17 @@ The following build targets are defined in `build.proj`: |Target|Description| |-|-| -|`BuildAbstractions`|Restore, build, and pack the Abstractions package, publishing the resulting NuGet into `packages/`.| +|`BuildAbstractions`|Restore and build the Abstractions package.| |`BuildAllConfigurations`|Default target. Builds the .NET Framework and .NET drivers for all target frameworks and operating systems.| -|`BuildAzure`|Restore, build, and pack the Azure package, publishing the resulting NuGet into `packages/`.| +|`BuildAzure`|Restore and build the Azure package.| +|`BuildLogging`|Restore and build the Logging package.| |`BuildNetCore`|Builds the .NET driver for all target frameworks.| |`BuildNetCoreAllOS`|Builds the .NET driver for all target frameworks and operating systems.| |`BuildNetFx`|Builds the .NET Framework driver for all target frameworks.| |`Clean`|Cleans all generated files.| +|`PackAbstractions`|Pack the Abstractions NuGet package into `packages/`. Requires `BuildAbstractions` first.| +|`PackAzure`|Pack the Azure NuGet package into `packages/`. Requires `BuildAzure` first.| +|`PackLogging`|Pack the Logging NuGet package into `packages/`. Requires `BuildLogging` first.| |`Restore`|Restores NuGet packages.| |`RunTests`|Runs the unit, functional, and manual tests for the .NET Framework and .NET drivers| |`RunUnitTests`|Runs just the unit tests for the .NET Framework and .NET drivers| @@ -188,8 +192,12 @@ packages in the root packages/ directory, and will be automatically searched by Then, you can specify `Package` references be used, for example: ```bash -dotnet build -t:BuildAbstractions +dotnet build -t:BuildLogging +dotnet build -t:PackLogging +dotnet build -t:BuildAbstractions -p:ReferenceType=Package +dotnet build -t:PackAbstractions dotnet build -t:BuildAzure -p:ReferenceType=Package +dotnet build -t:PackAzure dotnet build -t:BuildAll -p:ReferenceType=Package dotnet build -t:BuildAKVNetCore -p:ReferenceType=Package dotnet build -t:GenerateMdsPackage diff --git a/build.proj b/build.proj index ca7d99a99a..9ecf096d9e 100644 --- a/build.proj +++ b/build.proj @@ -160,14 +160,14 @@ - + - + + + + + + + + + + + + + + + + diff --git a/tools/targets/GenerateMdsPackage.targets b/tools/targets/GenerateMdsPackage.targets index 50f9b8fddd..b4bf4a0d5c 100644 --- a/tools/targets/GenerateMdsPackage.targets +++ b/tools/targets/GenerateMdsPackage.targets @@ -9,6 +9,6 @@ - + From 582f2abaee4eb21c7ff26a99b684afacaa371791 Mon Sep 17 00:00:00 2001 From: Apoorv Deshmukh Date: Thu, 26 Feb 2026 19:36:18 +0530 Subject: [PATCH 2/3] Update pipelines to handle the dependency on logging --- .../onebranch-pipeline-design.instructions.md | 75 +++-- eng/pipelines/dotnet-sqlclient-ci-core.yml | 287 +++++++++--------- .../jobs/build-signed-csproj-package-job.yml | 45 ++- .../libraries/onebranch-variables.yml | 4 +- .../stages/sqlclient-onebranch-stages.yml | 75 +++-- 5 files changed, 272 insertions(+), 214 deletions(-) diff --git a/.github/instructions/onebranch-pipeline-design.instructions.md b/.github/instructions/onebranch-pipeline-design.instructions.md index e7efab6be1..36cad1cf02 100644 --- a/.github/instructions/onebranch-pipeline-design.instructions.md +++ b/.github/instructions/onebranch-pipeline-design.instructions.md @@ -24,9 +24,9 @@ Both pipelines use the **OneBranch (1ES) governed template** infrastructure and |---|---------|-------------| | 1 | `Microsoft.SqlServer.Server` | — | | 2 | `Microsoft.Data.SqlClient.Extensions.Logging` | — | -| 3 | `Microsoft.Data.SqlClient.Extensions.Abstractions` | — | +| 3 | `Microsoft.Data.SqlClient.Extensions.Abstractions` | `Extensions.Logging` | | 4 | `Microsoft.Data.SqlClient` | `Extensions.Logging`, `Extensions.Abstractions` | -| 5 | `Microsoft.Data.SqlClient.Extensions.Azure` | `Extensions.Abstractions` | +| 5 | `Microsoft.Data.SqlClient.Extensions.Azure` | `Extensions.Abstractions`, `Extensions.Logging` | | 6 | `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider` | `SqlClient`, `Extensions.Logging` | --- @@ -38,8 +38,8 @@ sequenceDiagram participant T as Trigger / User participant P as Pipeline Orchestrator participant B1a as Job: Build Extensions.Logging - participant B1b as Job: Build Extensions.Abstractions participant B1c as Job: Build SqlServer.Server + participant B1b as Job: Build Extensions.Abstractions participant B2a as Job: Build SqlClient participant B2b as Job: Build Extensions.Azure participant V as Job: Validate MDS Package @@ -55,29 +55,32 @@ sequenceDiagram par Stage 1 jobs (parallel) P->>B1a: Build DLLs → ESRP sign DLLs → Pack → ESRP sign NuGet (Logging) B1a-->>P: ✅ Signed .nupkg - and - P->>B1b: Build DLLs → ESRP sign DLLs → Pack → ESRP sign NuGet (Abstractions) - B1b-->>P: ✅ Signed .nupkg and P->>B1c: Build + ESRP sign + pack SqlServer.Server B1c-->>P: ✅ Signed .nupkg end - Note over P: Stage 2 — buildMDS (dependsOn: build_independent) + Note over P: Stage 2 — build_abstractions (dependsOn: build_independent) + + P->>B1b: Build DLLs → ESRP sign DLLs → Pack → ESRP sign NuGet (Abstractions) + Note right of B1b: Downloads: Extensions.Logging artifact + B1b-->>P: ✅ Signed .nupkg - par Stage 2 jobs (parallel) + Note over P: Stage 3 — build_dependent (dependsOn: build_abstractions) + + par Stage 3 jobs (parallel) P->>B2a: Build + ESRP sign + pack SqlClient Note right of B2a: Downloads: Extensions.Logging,
Extensions.Abstractions artifacts B2a-->>P: ✅ Signed .nupkg + .snupkg and P->>B2b: Build DLLs → ESRP sign DLLs → Pack → ESRP sign NuGet (Azure) - Note right of B2b: Downloads:
Extensions.Abstractions artifact + Note right of B2b: Downloads: Extensions.Abstractions,
Extensions.Logging artifacts B2b-->>P: ✅ Signed .nupkg end - Note over P: Validation + Stage 3 (both dependsOn: buildMDS, run in parallel) + Note over P: Validation + Stage 4 (both dependsOn: build_dependent, run in parallel) - par Validation and Stage 3 (parallel) + par Validation and Stage 4 (parallel) P->>V: Validate signed MDS package V-->>P: ✅ Package validation passed and @@ -107,14 +110,13 @@ sequenceDiagram ### 4.1 Build Phase -The build phase runs automatically on every CI trigger, scheduled run, or manual queue. It is divided into three build stages plus a validation stage, based on the dependency graph. +The build phase runs automatically on every CI trigger, scheduled run, or manual queue. It is divided into four build stages plus a validation stage, based on the dependency graph. #### Stage 1 — `build_independent`: Independent Packages (no dependencies) | Job Template | Package | Build Target | Condition | |--------------|---------|--------------|-----------| | `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Logging` | `BuildLogging` / `PackLogging` | `buildAKVProvider OR buildSqlClient` | -| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Abstractions` | `BuildAbstractions` / `PackAbstractions` | `buildSqlClient` | | `build-signed-csproj-package-job.yml` | `Microsoft.SqlServer.Server` | `PackSqlServer` | `buildSqlServerServer` | - **`dependsOn`**: none @@ -122,47 +124,58 @@ The build phase runs automatically on every CI trigger, scheduled run, or manual - **Conditional builds**: Each job is wrapped with compile-time `${{ if }}` conditionals based on build parameters - csproj-based jobs (`build-signed-csproj-package-job.yml`) perform: **Build DLLs → ESRP DLL signing → NuGet pack (NoBuild=true) → ESRP NuGet signing** → publish artifact -#### Stage 2 — `buildMDS`: Core Packages (depend on Stage 1) +#### Stage 2 — `build_abstractions`: Abstractions Package (depends on Stage 1) | Job Template | Package | Build Target | Artifact Dependencies | |--------------|---------|--------------|----------------------| -| `build-signed-package-job.yml` | `Microsoft.Data.SqlClient` | *(nuspec-based)* | `Extensions.Logging`, `Extensions.Abstractions` | -| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Azure` | `BuildAzure` / `PackAzure` | `Extensions.Abstractions` | +| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Abstractions` | `BuildAbstractions` / `PackAbstractions` | `Extensions.Logging` | - **Stage condition**: `buildSqlClient = true` (entire stage is excluded when false) - **`dependsOn`**: `build_independent` +- Downloads `Microsoft.Data.SqlClient.Extensions.Logging.nupkg` (from Stage 1) pipeline artifact + +#### Stage 3 — `build_dependent`: Core Packages (depend on Stage 2) + +| Job Template | Package | Build Target | Artifact Dependencies | +|--------------|---------|--------------|----------------------| +| `build-signed-package-job.yml` | `Microsoft.Data.SqlClient` | *(nuspec-based)* | `Extensions.Logging`, `Extensions.Abstractions` | +| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Azure` | `BuildAzure` / `PackAzure` | `Extensions.Abstractions`, `Extensions.Logging` | + +- **Stage condition**: `buildSqlClient = true` (entire stage is excluded when false) +- **`dependsOn`**: `build_abstractions` - **Parallelism**: Both jobs run in parallel - The MDS (SqlClient) job also publishes symbol packages (`.snupkg`) when `publishSymbols` is true - All jobs configure APIScan with job-level `ob_sdl_apiscan_*` variables targeting package-specific folders -#### Stage 3 — `build_addons`: Add-on Packages (depend on Stage 2) +#### Stage 4 — `build_addons`: Add-on Packages (depend on Stage 3) | Job Template | Package | Artifact Dependencies | |--------------|---------|----------------------| | `build-akv-official-job.yml` | `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider` | `SqlClient`, `Extensions.Logging` | - **Stage condition**: `buildAKVProvider AND buildSqlClient` (both must be true) -- **`dependsOn`**: `buildMDS` -- Downloads `Microsoft.Data.SqlClient.nupkg` (from Stage 2) and `Microsoft.Data.SqlClient.Extensions.Logging.nupkg` (from Stage 1) pipeline artifacts +- **`dependsOn`**: `build_dependent` +- Downloads `Microsoft.Data.SqlClient.nupkg` (from Stage 3) and `Microsoft.Data.SqlClient.Extensions.Logging.nupkg` (from Stage 1) pipeline artifacts - Uses separate ESRP signing credentials (`Signing`-prefixed variables from `esrp-variables-v2` group) ### 4.2 Validation Stage — `mds_package_validation` -Validates the signed MDS (SqlClient) package after Stage 2 completes. +Validates the signed MDS (SqlClient) package after Stage 3 completes. - **Stage condition**: `buildSqlClient = true` -- **`dependsOn`**: `buildMDS` -- Runs in parallel with Stage 3 (`build_addons`) +- **`dependsOn`**: `build_dependent` +- Runs in parallel with Stage 4 (`build_addons`) - Uses `validate-signed-package-job.yml` template -- Downloads the `drop_buildMDS_build_signed_package` artifact and validates against `CurrentNetFxVersion` (default: `net462`) +- Downloads the `drop_build_dependent_build_signed_package` artifact and validates against `CurrentNetFxVersion` (default: `net462`) ### 4.3 Release Phase — `release` The release stage is gated and only executes on demand when at least one release parameter is set to `true` at queue time. - **`dependsOn`**: Conditional based on which build stages are enabled: - - `build_independent` (always) - - `buildMDS`, `mds_package_validation` (when `buildSqlClient = true`) + - `build_independent` (when releasing SqlServer.Server or Logging) + - `build_abstractions` (when releasing Abstractions) + - `build_dependent`, `mds_package_validation` (when `buildSqlClient = true`) - `build_addons` (when `buildAKVProvider AND buildSqlClient`) - **Gate**: ADO Environment approvals (official pipeline only): - Official: `NuGet-Production` environment with configured approvals @@ -186,11 +199,11 @@ The release stage is gated and only executes on demand when at least one release | Package | Artifact Name | Publish Job | |---------|---------------|-------------| -| `Microsoft.SqlServer.Server` | `drop_build_independent_build_signed_sqlserver_package` | `publish_SqlServer_Server` | -| `Microsoft.Data.SqlClient.Extensions.Logging` | `drop_build_independent_build_signed_Logging_package` | `publish_Logging` | -| `Microsoft.Data.SqlClient.Extensions.Abstractions` | `drop_build_independent_build_signed_Abstractions_package` | `publish_Abstractions` | -| `Microsoft.Data.SqlClient` | `drop_buildMDS_build_signed_package` | `publish_SqlClient` | -| `Microsoft.Data.SqlClient.Extensions.Azure` | `drop_buildMDS_build_signed_Azure_package` | `publish_Extensions_Azure` | +| `Microsoft.SqlServer.Server` | `drop_build_independent_build_package_SqlServer` | `publish_SqlServer_Server` | +| `Microsoft.Data.SqlClient.Extensions.Logging` | `drop_build_independent_build_package_Logging` | `publish_Logging` | +| `Microsoft.Data.SqlClient.Extensions.Abstractions` | `drop_build_abstractions_build_package_Abstractions` | `publish_Abstractions` | +| `Microsoft.Data.SqlClient` | `drop_build_dependent_build_package_SqlClient` | `publish_SqlClient` | +| `Microsoft.Data.SqlClient.Extensions.Azure` | `drop_build_dependent_build_package_Azure` | `publish_Extensions_Azure` | | `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider` | `drop_build_addons_buildSignedAkvPackage` | `publish_AKVProvider` | Each publish job uses the reusable `publish-nuget-package-job.yml` template, which downloads the artifact and pushes `.nupkg`/`.snupkg` files via `NuGetCommand@2` with an external feed service connection. @@ -442,7 +455,7 @@ Each job copies its signed DLLs and PDBs to a package-specific folder under `$(B ## 9. Artifact Strategy - Each build job publishes its output as a **pipeline artifact** managed by OneBranch's `ob_outputDirectory` convention. -- Artifact names follow the OneBranch auto-generated pattern: `drop__` (e.g., `drop_buildMDS_build_signed_package`). +- Artifact names follow the OneBranch auto-generated pattern: `drop__` (e.g., `drop_build_dependent_build_package_SqlClient`). - Downstream stages use `DownloadPipelineArtifact@2` to pull required packages into a local directory. - A local NuGet source is configured at build time pointing to the downloaded artifacts directory so `dotnet restore` resolves internal dependencies. diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 65fe3f5690..556e7b631f 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -4,104 +4,104 @@ # See the LICENSE file in the project root for more information. # ################################################################################# parameters: -# True to emit debug information and steps. -- name: debug - type: boolean - default: false - -# The target frameworks to build and run tests for on Windows. -# -# These are _not_ the target frameworks to build the driver packages for. -# -- name: targetFrameworks - type: object - default: [net462, net8.0, net9.0, net10.0] - -# The target frameworks to build and run tests for on Unix. -# -# These are _not_ the target frameworks to build the driver packages for. -# -- name: targetFrameworksUnix - type: object - default: [net8.0, net9.0, net10.0] - -# Netcore Version for Test Utilities -- name: netcoreVersionTestUtils - type: object - default: net10.0 - -# Build Platforms on Windows -- name: buildPlatforms - type: object - default: [AnyCPU] - -# Test sets to run -- name: testSets - type: object - default: [1, 2, 3] - -# Use Managed/Native SNI on Windows; valid values are: -# [true, false] -# [false, true] -# [false] -# [true] -- name: useManagedSNI - type: object - default: [false, true] - -# SNI Version Override -- name: SNIVersion - type: string - default: '' - -# SNI Version Override Nuget Feed -- name: SNIValidationFeed - type: string - default: https://sqlclientdrivers.pkgs.visualstudio.com/ADO.Net/_packaging/SNIValidation/nuget/v3/index.json - -# 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 - -- name: buildConfiguration - type: string - values: - - Debug - - Release - -- name: defaultPoolName - type: string - default: $(ci_var_defaultPoolName) - -# True to add a Stress Test stage to the pipeline. -- name: enableStressTests - type: boolean - default: false - -# The timeout, in minutes, for each test job. -- name: testJobTimeout - type: number - -# If true, the Always Encrypted (AE) test set will be run, which requires -# Enclave-enabled SQL Server instances. -- name: runAlwaysEncryptedTests - type: boolean - default: true - -- name: dotnetVerbosity - type: string - default: normal - values: - - quiet - - minimal - - normal - - detailed - - diagnostic + # True to emit debug information and steps. + - name: debug + type: boolean + default: false + + # The target frameworks to build and run tests for on Windows. + # + # These are _not_ the target frameworks to build the driver packages for. + # + - name: targetFrameworks + type: object + default: [net462, net8.0, net9.0, net10.0] + + # The target frameworks to build and run tests for on Unix. + # + # These are _not_ the target frameworks to build the driver packages for. + # + - name: targetFrameworksUnix + type: object + default: [net8.0, net9.0, net10.0] + + # Netcore Version for Test Utilities + - name: netcoreVersionTestUtils + type: object + default: net10.0 + + # Build Platforms on Windows + - name: buildPlatforms + type: object + default: [AnyCPU] + + # Test sets to run + - name: testSets + type: object + default: [1, 2, 3] + + # Use Managed/Native SNI on Windows; valid values are: + # [true, false] + # [false, true] + # [false] + # [true] + - name: useManagedSNI + type: object + default: [false, true] + + # SNI Version Override + - name: SNIVersion + type: string + default: "" + + # SNI Version Override Nuget Feed + - name: SNIValidationFeed + type: string + default: https://sqlclientdrivers.pkgs.visualstudio.com/ADO.Net/_packaging/SNIValidation/nuget/v3/index.json + + # 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 + + - name: buildConfiguration + type: string + values: + - Debug + - Release + + - name: defaultPoolName + type: string + default: $(ci_var_defaultPoolName) + + # True to add a Stress Test stage to the pipeline. + - name: enableStressTests + type: boolean + default: false + + # The timeout, in minutes, for each test job. + - name: testJobTimeout + type: number + + # If true, the Always Encrypted (AE) test set will be run, which requires + # Enclave-enabled SQL Server instances. + - name: runAlwaysEncryptedTests + type: boolean + default: true + + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic variables: - template: /eng/pipelines/libraries/ci-build-variables.yml@self @@ -119,7 +119,6 @@ variables: value: MDS.Artifacts stages: - # Generate secrets used throughout the pipeline. - template: /eng/pipelines/stages/generate-secrets-ci-stage.yml@self parameters: @@ -127,6 +126,9 @@ stages: # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. + # + # When building via packages, this depends on the Logging stage since + # Abstractions has a package dependency on Logging. - template: /eng/pipelines/stages/build-abstractions-package-ci-stage.yml@self parameters: abstractionsArtifactsName: $(abstractionsArtifactsName) @@ -135,10 +137,15 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + # When building Abstractions via packages, we must depend on the Logging + # package. + ${{ if eq(parameters.referenceType, 'Package') }}: + additionalDependsOn: + - build_logging_package_stage # Build the Logging package, and publish it to the pipeline artifacts - # under the given artifact name. This runs in parallel with the Abstractions - # stage since neither depends on the other. + # under the given artifact name. This runs in parallel with the Secrets + # generation stage since it has no package dependencies. - template: /eng/pipelines/stages/build-logging-package-ci-stage.yml@self parameters: loggingArtifactsName: $(loggingArtifactsName) @@ -196,16 +203,16 @@ stages: # Run the stress tests, if desired. - ${{ if eq(parameters.enableStressTests, true) }}: - - template: /eng/pipelines/stages/stress-tests-ci-stage.yml@self - parameters: - buildConfiguration: ${{ parameters.buildConfiguration }} - additionalDependsOn: - - build_sqlclient_package_stage - - build_azure_package_stage - mdsArtifactsName: $(mdsArtifactsName) - mdsPackageVersion: $(mdsPackageVersion) - azurePackageVersion: $(azurePackageVersion) - dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + - template: /eng/pipelines/stages/stress-tests-ci-stage.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + additionalDependsOn: + - build_sqlclient_package_stage + - build_azure_package_stage + mdsArtifactsName: $(mdsArtifactsName) + mdsPackageVersion: $(mdsPackageVersion) + azurePackageVersion: $(azurePackageVersion) + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} # Run the MDS and AKV tests. - template: /eng/pipelines/common/templates/stages/ci-run-tests-stage.yml@self @@ -233,45 +240,44 @@ stages: # Steps to run prior to building and running tests on each job. prebuildSteps: - ${{if ne(parameters.SNIVersion, '')}}: - - template: /eng/pipelines/common/templates/steps/override-sni-version.yml@self - parameters: - SNIVersion: ${{parameters.SNIVersion}} - SNIValidationFeed: ${{parameters.SNIValidationFeed}} + - template: /eng/pipelines/common/templates/steps/override-sni-version.yml@self + parameters: + SNIVersion: ${{parameters.SNIVersion}} + SNIValidationFeed: ${{parameters.SNIValidationFeed}} - ${{if eq(parameters.debug, true)}}: - - pwsh: 'Get-ChildItem env: | Sort-Object Name' - displayName: '[Debug] List Environment Variables' + - pwsh: "Get-ChildItem env: | Sort-Object Name" + displayName: "[Debug] List Environment Variables" # Include the code coverage job if the build type is Project. ${{ if eq(parameters.referenceType, 'Project') }}: - # Jobs to run as part of the tests stage, after the tests are done. + # Jobs to run as part of the tests stage, after the tests are done. postTestJobs: - - template: /eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml@self - parameters: - debug: ${{ parameters.debug }} - # We only want to upload coverage results to CodeCov from certain - # pipelines. We use the pipeline name (Build.DefinitionName) to - # choose. This is a predefined variable that is available at - # template expansion time, so we can use it to supply a true boolean - # value to the upload parameter. - # - # https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services - # - # We're choosing to upload from these pipelines only: - # - # - PR-SqlClient-Project - # - CI-SqlClient - # - # Other pipelines that share this template don't add much, if any, - # value to the coverage reports. They have not been configured with - # suitable CodeCov credentials to perform the upload. - # - upload: ${{ or(eq(variables['Build.DefinitionName'], 'PR-SqlClient-Project'), eq(variables['Build.DefinitionName'], 'CI-SqlClient')) }} + - template: /eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml@self + parameters: + debug: ${{ parameters.debug }} + # We only want to upload coverage results to CodeCov from certain + # pipelines. We use the pipeline name (Build.DefinitionName) to + # choose. This is a predefined variable that is available at + # template expansion time, so we can use it to supply a true boolean + # value to the upload parameter. + # + # https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services + # + # We're choosing to upload from these pipelines only: + # + # - PR-SqlClient-Project + # - CI-SqlClient + # + # Other pipelines that share this template don't add much, if any, + # value to the coverage reports. They have not been configured with + # suitable CodeCov credentials to perform the upload. + # + upload: ${{ or(eq(variables['Build.DefinitionName'], 'PR-SqlClient-Project'), eq(variables['Build.DefinitionName'], 'CI-SqlClient')) }} # Configuration of test jobs. Each entry in this object will become a test job, and the # properties of each entry will be supplied as parameters to the test job template. testConfigurations: - # Windows Server 22 with local SQL Server 2019, x64 build platform. windows_sql_19_x64: pool: ${{parameters.defaultPoolName }} @@ -534,7 +540,6 @@ stages: # Only run these tests if explicitly enabled, and if we're not a forked repo (which won't # have access to the necessary Library secrets). ${{ if and(eq(parameters.runAlwaysEncryptedTests, true), eq(variables['System.PullRequest.IsFork'], 'False')) }}: - # Windows Server 22 with remote Enclave-enabled SQL Server 2019, x64 build platform. windows_enclave_sql: pool: ADO-CI-AE-1ES-Pool diff --git a/eng/pipelines/jobs/build-signed-csproj-package-job.yml b/eng/pipelines/jobs/build-signed-csproj-package-job.yml index 1e120e7216..f6cef369c3 100644 --- a/eng/pipelines/jobs/build-signed-csproj-package-job.yml +++ b/eng/pipelines/jobs/build-signed-csproj-package-job.yml @@ -39,13 +39,13 @@ parameters: # Build. - name: buildTarget type: string - default: '' + default: "" # The MSBuild pack target in build.proj (e.g. PackLogging). If not specified, defaults to # Pack. - name: packTarget type: string - default: '' + default: "" # The C# build configuration to build (e.g. Debug or Release). - name: buildConfiguration @@ -59,7 +59,7 @@ parameters: # packages this package depends on, or versions for this package itself. - name: versionProperties type: string - default: '' + default: "" # Assembly file version for APIScan (e.g. 1.0.0.12345). - name: assemblyFileVersion @@ -109,14 +109,27 @@ jobs: steps: - template: /eng/pipelines/steps/script-output-environment-variables-step.yml@self - # The Azure package depends on Abstractions. The other packages we build have no - # inter-package dependencies. + # The Abstractions package depends on Logging. The Azure package depends + # on both Abstractions and Logging (Logging transitively via Abstractions). + - ${{ if eq(parameters.packageName, 'Abstractions') }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Logging Package + inputs: + artifactName: $(loggingArtifactsName) + targetPath: $(Build.SourcesDirectory)/packages + - ${{ if eq(parameters.packageName, 'Azure') }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Abstractions Package - inputs: - artifactName: $(abstractionsArtifactsName) - targetPath: $(Build.SourcesDirectory)/packages + - task: DownloadPipelineArtifact@2 + displayName: Download Abstractions Package + inputs: + artifactName: $(abstractionsArtifactsName) + targetPath: $(Build.SourcesDirectory)/packages + + - task: DownloadPipelineArtifact@2 + displayName: Download Logging Package + inputs: + artifactName: $(loggingArtifactsName) + targetPath: $(Build.SourcesDirectory)/packages # Install the .NET SDK. - template: /eng/pipelines/steps/install-dotnet.yml@self @@ -144,7 +157,7 @@ jobs: displayName: Copy DLLs for APIScan inputs: SourceFolder: $(BUILD_OUTPUT)/Package/bin - Contents: '**/${{ parameters.packageFullName }}.dll' + Contents: "**/${{ parameters.packageFullName }}.dll" TargetFolder: $(ob_sdl_apiscan_softwareFolder) # We must preserve the folder structure since our C# projects may produce multiple # identically named DLLs for different target frameworks (e.g. netstandard2.0, net5.0, @@ -155,7 +168,7 @@ jobs: displayName: Copy PDBs for APIScan inputs: SourceFolder: $(BUILD_OUTPUT)/Package/bin - Contents: '**/${{ parameters.packageFullName }}.pdb' + Contents: "**/${{ parameters.packageFullName }}.pdb" TargetFolder: $(ob_sdl_apiscan_symbolsFolder) flattenFolders: false @@ -178,7 +191,7 @@ jobs: # Publish symbols to servers - ${{ if eq(parameters.publishSymbols, true) }}: - - template: /eng/pipelines/common/templates/steps/publish-symbols-step.yml@self - parameters: - packageFullName: ${{ parameters.packageFullName }} - packageVersion: ${{ parameters.packageVersion }} + - template: /eng/pipelines/common/templates/steps/publish-symbols-step.yml@self + parameters: + packageFullName: ${{ parameters.packageFullName }} + packageVersion: ${{ parameters.packageVersion }} diff --git a/eng/pipelines/libraries/onebranch-variables.yml b/eng/pipelines/libraries/onebranch-variables.yml index dd52ca32dd..44d8cc0528 100644 --- a/eng/pipelines/libraries/onebranch-variables.yml +++ b/eng/pipelines/libraries/onebranch-variables.yml @@ -15,7 +15,7 @@ variables: - name: Packaging.EnableSBOMSigning value: true - name: WindowsContainerImage - value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' # Docker image which is used to build the project https://aka.ms/obpipelines/containers + value: "onebranch.azurecr.io/windows/ltsc2022/vse2022:latest" # Docker image which is used to build the project https://aka.ms/obpipelines/containers # OneBranch automatically publishes pipeline artifacts from all jobs. Use of the # PublishPipelineArtifacts task is prohibited. All content in the ob_outputDirectory is @@ -32,7 +32,7 @@ variables: # The Abstractions package artifacts. - name: abstractionsArtifactsName - value: drop_build_independent_build_package_Abstractions + value: drop_build_abstractions_build_package_Abstractions # The AKV package artifacts. - name: akvArtifactsName diff --git a/eng/pipelines/stages/sqlclient-onebranch-stages.yml b/eng/pipelines/stages/sqlclient-onebranch-stages.yml index 5b3b88e210..d43ca8af2d 100644 --- a/eng/pipelines/stages/sqlclient-onebranch-stages.yml +++ b/eng/pipelines/stages/sqlclient-onebranch-stages.yml @@ -19,7 +19,6 @@ # parameters: - # ── General parameters ───────────────────────────────────────────────── # True to enable debug information and steps. @@ -87,7 +86,7 @@ parameters: stages: # ==================================================================== # Stage 1: Independent packages (no cross-package dependencies) - # Logging, Abstractions, and SqlServer.Server build in parallel. + # Logging and SqlServer.Server build in parallel. # ==================================================================== - stage: build_independent displayName: "Build Independent Packages" @@ -128,16 +127,16 @@ stages: authAkvName: $(AuthAKVName) authSignCertName: $(AuthSignCertName) - - ${{ if eq(parameters.buildSqlClient, true) }}: + - ${{ if eq(parameters.buildSqlServerServer, true) }}: - template: /eng/pipelines/jobs/build-signed-csproj-package-job.yml@self parameters: - packageName: Abstractions - packageFullName: Microsoft.Data.SqlClient.Extensions.Abstractions - packageVersion: $(effectiveAbstractionsVersion) + packageName: SqlServer + packageFullName: Microsoft.SqlServer.Server + packageVersion: $(effectiveSqlServerVersion) versionProperties: >- - -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion) - -p:AbstractionsAssemblyFileVersion=$(abstractionsAssemblyFileVersion) - assemblyFileVersion: $(abstractionsAssemblyFileVersion) + -p:SqlServerAssemblyFileVersion=$(sqlServerAssemblyFileVersion) + -p:SqlServerPackageVersion=$(effectiveSqlServerVersion) + assemblyFileVersion: $(sqlServerAssemblyFileVersion) publishSymbols: ${{ parameters.publishSymbols }} esrpConnectedServiceName: $(ESRPConnectedServiceName) esrpClientId: $(ESRPClientId) @@ -146,16 +145,39 @@ stages: authAkvName: $(AuthAKVName) authSignCertName: $(AuthSignCertName) - - ${{ if eq(parameters.buildSqlServerServer, true) }}: + # ==================================================================== + # Stage 2: Abstractions package (depends on Logging from Stage 1) + # Abstractions must build after Logging since it has a package + # dependency on Extensions.Logging. + # ==================================================================== + - ${{ if eq(parameters.buildSqlClient, true) }}: + - stage: build_abstractions + displayName: "Build Abstractions Package" + dependsOn: build_independent + + variables: + - ${{ if parameters.isPreview }}: + - name: effectiveLoggingVersion + value: $(loggingPackagePreviewVersion) + - name: effectiveAbstractionsVersion + value: $(abstractionsPackagePreviewVersion) + - ${{ else }}: + - name: effectiveLoggingVersion + value: $(loggingPackageVersion) + - name: effectiveAbstractionsVersion + value: $(abstractionsPackageVersion) + + jobs: - template: /eng/pipelines/jobs/build-signed-csproj-package-job.yml@self parameters: - packageName: SqlServer - packageFullName: Microsoft.SqlServer.Server - packageVersion: $(effectiveSqlServerVersion) + packageName: Abstractions + packageFullName: Microsoft.Data.SqlClient.Extensions.Abstractions + packageVersion: $(effectiveAbstractionsVersion) versionProperties: >- - -p:SqlServerAssemblyFileVersion=$(sqlServerAssemblyFileVersion) - -p:SqlServerPackageVersion=$(effectiveSqlServerVersion) - assemblyFileVersion: $(sqlServerAssemblyFileVersion) + -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion) + -p:AbstractionsAssemblyFileVersion=$(abstractionsAssemblyFileVersion) + -p:LoggingPackageVersion=$(effectiveLoggingVersion) + assemblyFileVersion: $(abstractionsAssemblyFileVersion) publishSymbols: ${{ parameters.publishSymbols }} esrpConnectedServiceName: $(ESRPConnectedServiceName) esrpClientId: $(ESRPClientId) @@ -165,14 +187,14 @@ stages: authSignCertName: $(AuthSignCertName) # ==================================================================== - # Stage 2: Core packages (depend on independent packages) - # MDS and Extensions.Azure build in parallel after Stage 1 completes. + # Stage 3: Core packages (depend on Abstractions) + # MDS and Extensions.Azure build in parallel after Abstractions. # Stage name kept as 'build_dependent' for validate job compatibility. # ==================================================================== - ${{ if eq(parameters.buildSqlClient, true) }}: - stage: build_dependent displayName: "Build Core Packages" - dependsOn: build_independent + dependsOn: build_abstractions variables: # Resolved package versions: use preview versions when isPreview is true @@ -216,6 +238,7 @@ stages: -p:AzurePackageVersion=$(effectiveAzureVersion) -p:AzureAssemblyFileVersion=$(azureAssemblyFileVersion) -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion) + -p:LoggingPackageVersion=$(effectiveLoggingVersion) assemblyFileVersion: $(azureAssemblyFileVersion) publishSymbols: ${{ parameters.publishSymbols }} esrpConnectedServiceName: $(ESRPConnectedServiceName) @@ -226,7 +249,7 @@ stages: authSignCertName: $(AuthSignCertName) # ==================================================================== - # Stage 3: Add-on packages (depend on core packages) + # Stage 4: Add-on packages (depend on core packages) # AKV Provider builds after MDS completes. # ==================================================================== - ${{ if and(eq(parameters.buildAKVProvider, true), eq(parameters.buildSqlClient, true)) }}: @@ -321,8 +344,10 @@ stages: - stage: Production_Release displayName: "Release to NuGet" dependsOn: - - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging, parameters.releaseAbstractions) }}: + - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging) }}: - build_independent + - ${{ if parameters.releaseAbstractions }}: + - build_abstractions - ${{ if or(parameters.releaseSqlClient, parameters.releaseExtAzure) }}: - build_dependent - mds_package_validation @@ -355,7 +380,7 @@ stages: - template: /eng/pipelines/common/templates/jobs/publish-nuget-package-job.yml@self parameters: packageDisplayName: Microsoft.Data.SqlClient.Extensions.Abstractions - artifactName: drop_build_independent_build_package_Abstractions + artifactName: drop_build_abstractions_build_package_Abstractions nugetServiceConnection: $(NuGetServiceConnection) isProduction: true dryRun: ${{ parameters.releaseDryRun }} @@ -392,8 +417,10 @@ stages: - stage: Test_Release displayName: "Release to NuGet (Dry Run)" dependsOn: - - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging, parameters.releaseAbstractions) }}: + - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging) }}: - build_independent + - ${{ if parameters.releaseAbstractions }}: + - build_abstractions - ${{ if or(parameters.releaseSqlClient, parameters.releaseExtAzure) }}: - build_dependent - mds_package_validation @@ -424,7 +451,7 @@ stages: - template: /eng/pipelines/common/templates/jobs/publish-nuget-package-job.yml@self parameters: packageDisplayName: Microsoft.Data.SqlClient.Extensions.Abstractions - artifactName: drop_build_independent_build_package_Abstractions + artifactName: drop_build_abstractions_build_package_Abstractions nugetServiceConnection: $(NuGetServiceConnection) dryRun: true From bc06bacbe7fa5c5ca98df0c2b9b800f3d22c23b1 Mon Sep 17 00:00:00 2001 From: Apoorv Deshmukh Date: Thu, 26 Feb 2026 22:41:46 +0530 Subject: [PATCH 3/3] Address review comments --- BUILDGUIDE.md | 4 +-- eng/pipelines/dotnet-sqlclient-ci-core.yml | 24 +++++++-------- .../jobs/build-signed-csproj-package-job.yml | 29 +++++++------------ .../stages/sqlclient-onebranch-stages.yml | 8 +++++ 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index f035d9a12a..c8404137c9 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -195,9 +195,9 @@ Then, you can specify `Package` references be used, for example: dotnet build -t:BuildLogging dotnet build -t:PackLogging dotnet build -t:BuildAbstractions -p:ReferenceType=Package -dotnet build -t:PackAbstractions +dotnet build -t:PackAbstractions -p:ReferenceType=Package dotnet build -t:BuildAzure -p:ReferenceType=Package -dotnet build -t:PackAzure +dotnet build -t:PackAzure -p:ReferenceType=Package dotnet build -t:BuildAll -p:ReferenceType=Package dotnet build -t:BuildAKVNetCore -p:ReferenceType=Package dotnet build -t:GenerateMdsPackage diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 556e7b631f..86fdd5ed85 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -124,6 +124,18 @@ stages: parameters: debug: ${{ parameters.debug }} + # Build the Logging package, and publish it to the pipeline artifacts + # under the given artifact name. This runs in parallel with the Secrets + # generation stage since it has no package dependencies. + - template: /eng/pipelines/stages/build-logging-package-ci-stage.yml@self + parameters: + loggingArtifactsName: $(loggingArtifactsName) + loggingAssemblyFileVersion: $(loggingAssemblyFileVersion) + loggingPackageVersion: $(loggingPackageVersion) + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. # @@ -143,18 +155,6 @@ stages: additionalDependsOn: - build_logging_package_stage - # Build the Logging package, and publish it to the pipeline artifacts - # under the given artifact name. This runs in parallel with the Secrets - # generation stage since it has no package dependencies. - - template: /eng/pipelines/stages/build-logging-package-ci-stage.yml@self - parameters: - loggingArtifactsName: $(loggingArtifactsName) - loggingAssemblyFileVersion: $(loggingAssemblyFileVersion) - loggingPackageVersion: $(loggingPackageVersion) - buildConfiguration: ${{ parameters.buildConfiguration }} - debug: ${{ parameters.debug }} - dotnetVerbosity: ${{ parameters.dotnetVerbosity }} - # Build the SqlClienet package. # # For legacy reasons, this also builds the AKV package. diff --git a/eng/pipelines/jobs/build-signed-csproj-package-job.yml b/eng/pipelines/jobs/build-signed-csproj-package-job.yml index f6cef369c3..06d409143b 100644 --- a/eng/pipelines/jobs/build-signed-csproj-package-job.yml +++ b/eng/pipelines/jobs/build-signed-csproj-package-job.yml @@ -88,6 +88,13 @@ parameters: - name: authSignCertName type: string + # Optional list of pipeline artifacts to download before building. Each entry is an object + # with 'artifactName' (the pipeline artifact name) and 'displayName' (used in the task label). + # This replaces hard-coded packageName conditionals so callers declare their own dependencies. + - name: downloadArtifacts + type: object + default: [] + jobs: - job: build_package_${{ parameters.packageName }} displayName: Build ${{ parameters.packageFullName }} @@ -109,26 +116,12 @@ jobs: steps: - template: /eng/pipelines/steps/script-output-environment-variables-step.yml@self - # The Abstractions package depends on Logging. The Azure package depends - # on both Abstractions and Logging (Logging transitively via Abstractions). - - ${{ if eq(parameters.packageName, 'Abstractions') }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Logging Package - inputs: - artifactName: $(loggingArtifactsName) - targetPath: $(Build.SourcesDirectory)/packages - - - ${{ if eq(parameters.packageName, 'Azure') }}: - - task: DownloadPipelineArtifact@2 - displayName: Download Abstractions Package - inputs: - artifactName: $(abstractionsArtifactsName) - targetPath: $(Build.SourcesDirectory)/packages - + # Download any pipeline artifacts this package depends on. + - ${{ each artifact in parameters.downloadArtifacts }}: - task: DownloadPipelineArtifact@2 - displayName: Download Logging Package + displayName: Download ${{ artifact.displayName }} inputs: - artifactName: $(loggingArtifactsName) + artifactName: ${{ artifact.artifactName }} targetPath: $(Build.SourcesDirectory)/packages # Install the .NET SDK. diff --git a/eng/pipelines/stages/sqlclient-onebranch-stages.yml b/eng/pipelines/stages/sqlclient-onebranch-stages.yml index d43ca8af2d..3fd0020ec0 100644 --- a/eng/pipelines/stages/sqlclient-onebranch-stages.yml +++ b/eng/pipelines/stages/sqlclient-onebranch-stages.yml @@ -185,6 +185,9 @@ stages: appRegistrationTenantId: $(AppRegistrationTenantId) authAkvName: $(AuthAKVName) authSignCertName: $(AuthSignCertName) + downloadArtifacts: + - artifactName: $(loggingArtifactsName) + displayName: Logging Package # ==================================================================== # Stage 3: Core packages (depend on Abstractions) @@ -247,6 +250,11 @@ stages: appRegistrationTenantId: $(AppRegistrationTenantId) authAkvName: $(AuthAKVName) authSignCertName: $(AuthSignCertName) + downloadArtifacts: + - artifactName: $(abstractionsArtifactsName) + displayName: Abstractions Package + - artifactName: $(loggingArtifactsName) + displayName: Logging Package # ==================================================================== # Stage 4: Add-on packages (depend on core packages)