diff --git a/.github/instructions/onebranch-pipeline-design.instructions.md b/.github/instructions/onebranch-pipeline-design.instructions.md
index 1c848e2493..0860d5db52 100644
--- a/.github/instructions/onebranch-pipeline-design.instructions.md
+++ b/.github/instructions/onebranch-pipeline-design.instructions.md
@@ -1,534 +1,157 @@
---
applyTo: "eng/pipelines/**/*.yml"
---
-# Multi-Product Azure DevOps Pipeline in dotnet/sqlclient — Design Specification
+# OneBranch Pipeline Guidelines
-## 1. Overview
+## Purpose
-This document describes the design of the unified Azure DevOps YAML pipeline that builds, signs, packages, and optionally releases six NuGet packages with interdependencies. The pipeline uses **stages** and **jobs** to maximize parallelism while respecting dependency order. It comprises five stages: three build stages, a validation stage, and an on-demand release stage.
+Rules and conventions for editing the OneBranch Azure DevOps YAML pipelines that build, sign, package, and release six NuGet packages with interdependencies.
-Two pipeline variants exist from the same stage/job structure:
+## Pipeline Variants
+
+- `sqlclient-official.yml` — Official pipeline; uses `OneBranch.Official.CrossPlat.yml`; CI trigger on `internal/main` + daily schedule at 04:30 UTC
+- `sqlclient-non-official.yml` — Non-Official pipeline; uses `OneBranch.NonOfficial.CrossPlat.yml`; manual only (`pr: none`, `trigger: none`)
+- Both live under `eng/pipelines/onebranch/` and extend OneBranch governed templates
+- Never parameterize the OneBranch template name — hardcode it per pipeline for PRC compliance
+- Official pipeline must never be run on PRs or dev branches.
+
+## Package Dependency Order
+
+Respect this graph when modifying build stages:
-| Pipeline | Template | Trigger | Purpose |
-|----------|----------|---------|---------|
-| `dotnet-sqlclient-official-pipeline.yml` | `OneBranch.Official.CrossPlat.yml` | CI + scheduled | Production-signed builds |
-| `dotnet-sqlclient-non-official-pipeline.yml` | `OneBranch.NonOfficial.CrossPlat.yml` | Manual only | Validation / test builds (release in dry-run mode) |
+1. `Microsoft.SqlServer.Server` — no dependencies
+2. `Microsoft.Data.SqlClient.Internal.Logging` — no dependencies
+3. `Microsoft.Data.SqlClient.Extensions.Abstractions` — depends on Logging
+4. `Microsoft.Data.SqlClient` — depends on Logging + Abstractions
+5. `Microsoft.Data.SqlClient.Extensions.Azure` — depends on Abstractions + Logging
+6. `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider` — depends on SqlClient + Abstractions + Logging
+
+## Build Stages
-Both pipelines use the **OneBranch (1ES) governed template** infrastructure and share identical stage definitions, job templates, and variable chains.
-
----
-
-## 2. Products and Dependencies
-
-| # | Package | Dependencies |
-|---|---------|-------------|
-| 1 | `Microsoft.SqlServer.Server` | — |
-| 2 | `Microsoft.Data.SqlClient.Internal.Logging` | — |
-| 3 | `Microsoft.Data.SqlClient.Extensions.Abstractions` | `Internal.Logging` |
-| 4 | `Microsoft.Data.SqlClient` | `Internal.Logging`, `Extensions.Abstractions` |
-| 5 | `Microsoft.Data.SqlClient.Extensions.Azure` | `Extensions.Abstractions`, `Internal.Logging` |
-| 6 | `Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider` | `SqlClient`, `Internal.Logging` |
-
----
-
-## 3. Pipeline Flow — Sequence Diagram
-
-```mermaid
-sequenceDiagram
- participant T as Trigger / User
- participant P as Pipeline Orchestrator
- participant B1a as Job: Build Internal.Logging
- 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
- participant B3 as Job: Build AKV Provider
- participant R as Stage: Release
-
- Note over T,R: ══════ BUILD & SIGN PHASE ══════
-
- T->>P: Pipeline triggered (CI / Scheduled / Manual)
-
- Note over P: Stage 1 — build_independent (parallel, no deps)
-
- par Stage 1 jobs (parallel)
- P->>B1a: Build DLLs → ESRP sign DLLs → Pack → ESRP sign NuGet (Logging)
- B1a-->>P: ✅ Signed .nupkg
- and
- P->>B1c: Build + ESRP sign + pack SqlServer.Server
- B1c-->>P: ✅ Signed .nupkg
- end
-
- 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: Internal.Logging artifact
- B1b-->>P: ✅ Signed .nupkg
-
- 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: Internal.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,
Internal.Logging artifacts
- B2b-->>P: ✅ Signed .nupkg
- end
-
- Note over P: Validation + Stage 4 (both dependsOn: build_dependent, run in parallel)
-
- par Validation and Stage 4 (parallel)
- P->>V: Validate signed MDS package
- V-->>P: ✅ Package validation passed
- and
- P->>B3: Build + ESRP sign + pack AKV Provider
- Note right of B3: Downloads: SqlClient,
Internal.Logging artifacts
- B3-->>P: ✅ Signed .nupkg
- end
-
- Note over T,R: ══════ RELEASE PHASE (on-demand) ══════
-
- alt At least one release parameter is true
- P->>R: Stage: release (dependsOn: conditional on build stages)
- Note right of R: ADO Environment Approval
(NuGet-Production environment)
- R-->>P: ✅ Approved
- Note right of R: Publish selected packages
via NuGetCommand@2
- R-->>P: ✅ Published to NuGet
- else No release parameters set
- Note over P: Release stage skipped
- end
-
- Note over T,R: Pipeline complete 🎉
-```
-
----
-
-## 4. Stage Design
-
-### 4.1 Build Phase
-
-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.Internal.Logging` | `BuildLogging` / `PackLogging` | `buildAKVProvider OR buildSqlClient` |
-| `build-signed-csproj-package-job.yml` | `Microsoft.SqlServer.Server` | `PackSqlServer` | `buildSqlServerServer` |
-
-- **`dependsOn`**: none
-- **Parallelism**: Jobs run in parallel (depending on which are enabled)
-- **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 — `build_abstractions`: Abstractions Package (depends on Stage 1)
-
-| Job Template | Package | Build Target | Artifact Dependencies |
-|--------------|---------|--------------|----------------------|
-| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Abstractions` | `BuildAbstractions` / `PackAbstractions` | `Internal.Logging` |
-
-- **Stage condition**: `buildSqlClient = true` (entire stage is excluded when false)
-- **`dependsOn`**: `build_independent`
-- Downloads `Microsoft.Data.SqlClient.Internal.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)* | `Internal.Logging`, `Extensions.Abstractions` |
-| `build-signed-csproj-package-job.yml` | `Microsoft.Data.SqlClient.Extensions.Azure` | `BuildAzure` / `PackAzure` | `Extensions.Abstractions`, `Internal.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 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`, `Internal.Logging` |
-
-- **Stage condition**: `buildAKVProvider AND buildSqlClient` (both must be true)
-- **`dependsOn`**: `build_dependent`
-- Downloads `Microsoft.Data.SqlClient.nupkg` (from Stage 3) and `Microsoft.Data.SqlClient.Internal.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 3 completes.
-
-- **Stage condition**: `buildSqlClient = true`
-- **`dependsOn`**: `build_dependent`
-- Runs in parallel with Stage 4 (`build_addons`)
-- Uses `validate-signed-package-job.yml` template
-- 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` (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
- - Non-Official: `NuGet-DryRun` environment (no approvals, validation only)
-- **Package selection**: Controlled by 6 runtime boolean parameters (see Section 5.2)
-- **Stage condition**: The entire stage is skipped unless at least one release parameter is `true`:
- ```yaml
- - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging, ...) }}:
- - stage: release
- ```
-- **Publish jobs**: Each package has a conditional publish job that is included at compile time only when its parameter is `true`:
- ```yaml
- - ${{ if eq(parameters.releaseXxx, true) }}:
- - template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
- ```
-- **Environment variables**: Stage sets `ob_release_usedeploymentjob: true` for OneBranch integration:
- - Official: `ob_release_environment: 'NuGet-Production'`
- - Non-Official: `ob_release_environment: 'NuGet-DryRun'`
-
-#### Artifact → Publish Job Mapping
-
-| Package | Artifact Name | Publish Job |
-|---------|---------------|-------------|
-| `Microsoft.SqlServer.Server` | `drop_build_independent_build_package_SqlServer` | `publish_SqlServer_Server` |
-| `Microsoft.Data.SqlClient.Internal.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.
-
-#### Dry-Run Mode
-
-Two ADO environments control release behavior:
-
-| Environment | Pipeline | Behavior |
-|------------|----------|----------|
-| `NuGet-DryRun` | Non-Official | Validation only — packages are never pushed |
-| `NuGet-Production` | Official | Real releases with approval gate |
-
-**Non-official pipeline**: Always runs in dry-run mode. There is no `releaseDryRun` parameter — `dryRun: true` is hardcoded in every publish job. This prevents accidental publication from validation builds.
-
-**Official pipeline**: Exposes a `releaseDryRun` parameter (default: `true` for safety). When enabled, the template downloads artifacts and lists the `.nupkg`/`.snupkg` files that *would* be published but skips the actual `NuGetCommand@2` push. Set `releaseDryRun: false` to perform real pushes after final validation.
-
----
-
-## 5. Runtime Parameters
-
-### 5.1 Build Parameters
-
-The pipeline exposes the following parameters at queue time:
-
-```yaml
-parameters:
- - name: debug
- displayName: 'Enable debug output'
- type: boolean
- default: false
-
- - name: publishSymbols
- displayName: 'Publish symbols'
- type: boolean
- default: false
-
- - name: CurrentNetFxVersion
- displayName: 'Lowest supported .NET Framework version (MDS validation)'
- type: string
- default: 'net462'
-
- - name: isPreview
- displayName: 'Is this a preview build?'
- type: boolean
- default: false
-
- - name: testJobTimeout
- displayName: 'Test job timeout (in minutes)'
- type: number
- default: 60
-
- # Build parameters — control which packages to build
- - name: buildSqlServerServer
- displayName: 'Build Microsoft.SqlServer.Server'
- type: boolean
- default: true
-
- - name: buildSqlClient
- displayName: 'Build Microsoft.Data.SqlClient and Extensions'
- type: boolean
- default: true
-
- - name: buildAKVProvider
- displayName: 'Build Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider'
- type: boolean
- default: true
-```
-
-The `isPreview` parameter controls version resolution — when `true`, each package uses its preview version (e.g., `loggingPackagePreviewVersion`) instead of the GA version (e.g., `loggingPackageVersion`). All versions are defined in the centralized `libraries/common-variables.yml`.
-
-The build parameters enable selective package building:
-- `buildSqlServerServer` — controls SqlServer.Server build job
-- `buildSqlClient` — controls MDS, Extensions.Azure, Abstractions, Logging (when AKV is disabled), and validation stages
-- `buildAKVProvider` — controls AKV Provider build (also requires `buildSqlClient=true`) and Logging (when SqlClient is disabled)
-
-When set to `false`, the respective jobs/stages are excluded at compile-time using `${{ if }}` conditionals. This allows faster pipeline runs when only certain packages need to be built.
-
-### 5.2 Release Parameters
-
-Six boolean parameters control selective package release. All default to `false` so the release stage is skipped on normal CI/scheduled builds:
-
-```yaml
-parameters:
- - name: releaseSqlServerServer
- displayName: 'Release Microsoft.SqlServer.Server'
- type: boolean
- default: false
-
- - name: releaseLogging
- displayName: 'Release Microsoft.Data.SqlClient.Internal.Logging'
- type: boolean
- default: false
-
- - name: releaseAbstractions
- displayName: 'Release Microsoft.Data.SqlClient.Extensions.Abstractions'
- type: boolean
- default: false
-
- - name: releaseSqlClient
- displayName: 'Release Microsoft.Data.SqlClient'
- type: boolean
- default: false
-
- - name: releaseAzure
- displayName: 'Release Microsoft.Data.SqlClient.Extensions.Azure'
- type: boolean
- default: false
-
- - name: releaseAKVProvider
- displayName: 'Release Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider'
- type: boolean
- default: false
-```
-
-#### Dry-Run Parameter (Official Pipeline Only)
-
-The **official pipeline** includes a `releaseDryRun` parameter that defaults to `true` for safety:
-
-```yaml
- - name: releaseDryRun
- displayName: 'Release Dry Run (do not push to NuGet)'
- type: boolean
- default: true # safety default — must explicitly disable for real releases
-```
-
-When `releaseDryRun: true`, publish jobs download artifacts and list packages but skip actual NuGet push. Set to `false` for production releases.
-
-> **Note**: The non-official pipeline does **not** expose this parameter — dry-run mode is hardcoded and cannot be disabled.
-
----
-
-## 6. Variable & Version Management
-
-### 6.1 Variable Chain
-
-Variables are defined in a layered template chain. All variable groups live inside the templates — none are declared inline at the pipeline level:
-
-```
-dotnet-sqlclient-official-pipeline.yml
- └─ libraries/variables.yml
- └─ libraries/build-variables.yml
- ├─ group: 'Release Variables'
- ├─ group: 'Symbols publishing' ← SymbolsPublishServer, SymbolsPublishTokenUri, etc.
- └─ libraries/common-variables.yml
- ├─ group: 'ESRP Federated Creds (AME)' ← ESRP signing credentials
- ├─ SymbolServer / SymbolTokenUri aliases ← mapped from Symbols publishing group
- └─ all package versions, paths, build variables
-```
-
-### 6.2 Package Version Variables
-
-All package versions are centralized in `libraries/common-variables.yml`:
-
-| Package | GA Version Var | Preview Version Var | Assembly Version Var |
-|---------|---------------|--------------------|--------------------|
-| Logging | `loggingPackageVersion` | `loggingPackagePreviewVersion` | `loggingAssemblyFileVersion` |
-| Abstractions | `abstractionsPackageVersion` | `abstractionsPackagePreviewVersion` | `abstractionsAssemblyFileVersion` |
-| SqlServer.Server | `sqlServerPackageVersion` | `sqlServerPackagePreviewVersion` | `sqlServerAssemblyFileVersion` |
-| SqlClient (MDS) | `mdsPackageVersion` | `mdsPackagePreviewVersion` | `mdsAssemblyFileVersion` |
-| Extensions.Azure | `azurePackageVersion` | `azurePackagePreviewVersion` | `azureAssemblyFileVersion` |
-| AKV Provider | `akvPackageVersion` | `akvPackagePreviewVersion` | `akvAssemblyFileVersion` |
-
-The pipeline resolves `effective*Version` variables at compile time based on the `isPreview` parameter.
-
-### 6.3 Release & Symbol Variables
-
-| Variable | Defined In | Purpose |
-|----------|-----------|---------|
-| `NuGetServiceConnection` | `libraries/common-variables.yml` | External NuGet service connection name for `NuGetCommand@2` push |
-| `SymbolServer` | `libraries/common-variables.yml` (alias) | Alias for `$(SymbolsPublishServer)` — used by MDS `publish-symbols-step.yml` |
-| `SymbolTokenUri` | `libraries/common-variables.yml` (alias) | Alias for `$(SymbolsPublishTokenUri)` — used by MDS `publish-symbols-step.yml` |
-
-### 6.4 Variable Groups
-
-| Group | Included In | Purpose |
-|-------|------------|---------|
-| `Release Variables` | `build-variables.yml` | Release-specific configuration |
-| `Symbols publishing` | `build-variables.yml` | Symbol publishing credentials (`SymbolsAzureSubscription`, `SymbolsPublishServer`, `SymbolsPublishTokenUri`, `SymbolsUploadAccount`, `SymbolsPublishProjectName`) |
-| `ESRP Federated Creds (AME)` | `common-variables.yml` | Federated identity for ESRP signing (`ESRPConnectedServiceName`, `ESRPClientId`, `AppRegistrationClientId`, `AppRegistrationTenantId`, `AuthAKVName`, `AuthSignCertName`) |
-
----
-
-## 7. Code Signing (ESRP)
-
-All packages are signed using **ESRP (Enterprise Security Release Pipeline)** with federated identity authentication.
-
-### Signing Flow (per job)
-
-#### csproj-based Extension Packages (Logging, Abstractions, Azure)
-1. **Build DLLs only** — `build.proj` target (e.g., `BuildLogging`) compiles assemblies without creating NuGet packages
-2. **ESRP DLL signing** — Assemblies are signed with Authenticode certificates via ESRP
-3. **NuGet pack** — `build.proj` pack target (e.g., `PackLogging`) creates `.nupkg` from signed DLLs using `NoBuild=true`
-4. **ESRP NuGet signing** — The `.nupkg` files are signed with NuGet certificates via ESRP
-
-This workflow ensures the NuGet package contains **signed DLLs** rather than signing the NuGet package around unsigned assemblies.
-
-#### nuspec-based Packages (SqlServer.Server, SqlClient, AKV Provider)
-1. **Build + pack** — MSBuild creates both assemblies and NuGet packages
-2. **ESRP DLL signing** — Assemblies are signed with Authenticode certificates via ESRP
-3. **ESRP NuGet signing** — The `.nupkg` files are signed with NuGet certificates via ESRP
-
-### Credential Model
-
-- Extension packages (Logging, Abstractions, Azure, SqlServer.Server, SqlClient) use the primary ESRP credentials from the `ESRP Federated Creds (AME)` variable group (loaded via `common-variables.yml`)
-- AKV Provider uses separate `Signing`-prefixed credential parameters that are passed explicitly to the `build-akv-official-job.yml` template
-- All credentials are sourced from Azure Key Vault and federated identity — no secrets stored in pipeline YAML
-
----
-
-## 8. SDL & Compliance (OneBranch)
-
-Both pipelines use **OneBranch governed templates** for 1ES compliance. The SDL configuration differs between Official and Non-Official:
-
-| SDL Tool | Official | Non-Official | Purpose |
-|----------|----------|--------------|---------|
-| **TSA** | ✅ `enabled: true` | ❌ `enabled: false` | Uploads SDL results to TSA for downstream analysis |
-| **ApiScan** | ✅ `enabled: true`, `break: true` | ✅ `enabled: true`, `break: true` | Scans APIs for compliance issues |
-| **CodeQL** | ✅ (non-preview) | ✅ (non-preview) | Static analysis for security vulnerabilities |
-| **SBOM** | ✅ (non-preview) | ✅ (non-preview) | Software Bill of Materials generation |
-| **Policheck** | ✅ `break: true` | ✅ `break: true` | Scans for policy-violating content |
-| **BinSkim** | ✅ (async, non-preview) | ✅ (async, non-preview) | Binary security analysis |
-| **CredScan** | ✅ (async, non-preview) | ✅ (async, non-preview) | Credential leak detection |
-| **Roslyn** | ✅ (async, non-preview) | ✅ (async, non-preview) | Roslyn-based security analyzers |
-| **Armory** | ✅ `break: true` | ✅ `break: true` | Additional security scanning |
-
-### APIScan Configuration
-
-APIScan is configured at **both pipeline level and job level**:
-
-**Pipeline-level** (`globalSdl:apiscan:`): Sets default configuration inherited by all jobs. This is configured for MDS (Microsoft.Data.SqlClient) as the primary product.
-
-**Job-level** (`ob_sdl_apiscan_*` variables): Each build job overrides the pipeline defaults with package-specific settings:
-
-| Variable | Purpose |
-|----------|---------|
-| `ob_sdl_apiscan_enabled` | Enable/disable APIScan for this job (`true`) |
-| `ob_sdl_apiscan_softwareFolder` | Path to signed DLLs for scanning |
-| `ob_sdl_apiscan_symbolsFolder` | Path to PDBs for scanning |
-| `ob_sdl_apiscan_softwarename` | Package name (e.g., `Microsoft.Data.SqlClient.Internal.Logging`) |
-| `ob_sdl_apiscan_versionNumber` | Assembly file version |
-
-Each job copies its signed DLLs and PDBs to a package-specific folder under `$(Build.SourcesDirectory)/apiScan//` after ESRP DLL signing, ensuring APIScan analyzes the correct signed binaries for each package.
-
-> **PRC Compliance**: The Official pipeline hardcodes `OneBranch.Official.CrossPlat.yml` (not parameterized) to satisfy Production Readiness Check static verification requirements.
-
----
-
-## 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_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.
-
----
-
-## 10. Trigger Configuration
-
-### Official Pipeline (`dotnet-sqlclient-official-pipeline.yml`)
-
-```yaml
-trigger:
- branches:
- include:
- - internal/main
- paths:
- include:
- - .azuredevops
- - .config
- - doc
- - eng/pipelines
- - src
- - tools
- - azurepipelines-coverage.yml
- - build.proj
- - NuGet.config
-
-schedules:
- - cron: '30 4 * * Mon' # Weekly Sunday 9:30 PM (UTC-7)
- branches: { include: [internal/main] }
- always: true
- - cron: '30 3 * * Mon-Fri' # Weekday 8:30 PM (UTC-7)
- branches: { include: [internal/main] }
-```
-
-- **CI trigger**: Runs on pushes to `internal/main` when relevant paths change
-- **Scheduled**: Weekly full build (Sundays) + weekday builds (Mon–Fri)
-- **No PR trigger**: Official pipeline should not run on PRs (separate PR pipelines exist)
-
-### Non-Official Pipeline (`dotnet-sqlclient-non-official-pipeline.yml`)
-
-```yaml
-trigger: none
-pr: none
-```
-
-- **Manual only**: Queued on-demand for validation/test builds
-
----
-
-## 11. Infrastructure
-
-| Concern | Implementation |
-|---------|---------------|
-| **Pipeline template** | OneBranch governed templates (`OneBranch.Pipelines/GovernedTemplates`) |
-| **Build agents** | OneBranch-managed Windows containers (`WindowsHostVersion: 1ESWindows2022`) |
-| **.NET SDK** | Pinned via `global.json` (with `useGlobalJson: true` in install steps) |
-| **Code signing** | ESRP v2 with federated identity (Azure Key Vault backed) |
-| **Symbol publishing** | Optional, controlled by `publishSymbols` parameter; uses `Symbols publishing` variable group (aliases `SymbolServer`/`SymbolTokenUri` defined in `common-variables.yml`) |
-
----
-
-## 12. Key Design Decisions
-
-1. **Single pipeline, multiple stages** — avoids managing 6 separate pipelines while keeping clear separation of concerns.
-2. **Official + Non-Official variants** — hardcoded OneBranch templates (no parameterized `oneBranchType`) for PRC compliance; Non-Official variant allows manual validation builds.
-3. **Parallel jobs within stages** — minimizes total wall-clock time; only waits where dependencies demand it.
-4. **Pipeline artifacts over Universal Packages** — faster, ephemeral, scoped to the run; appropriate for build-time dependency resolution.
-5. **ESRP-based code signing** — all DLLs and NuGet packages are signed in-pipeline using ESRP with federated identity; no secrets in YAML.
-6. **Centralized version management** — all 6 package versions (GA + preview) defined once in `libraries/common-variables.yml`; `isPreview` toggle selects the active set.
-7. **Dependency-aware stage ordering** — ensures packages are always built after their dependencies, guaranteeing consistent, reproducible builds.
-8. **Validation in parallel with Stage 3** — MDS package validation runs alongside AKV Provider build (both depend on Stage 2), reducing total pipeline duration.
-9. **Selective on-demand release** — 6 boolean parameters control which packages are published; the release stage is entirely skipped when none are selected, keeping normal CI builds unaffected.
-10. **ADO Environment approval gate** — two environments: `NuGet-Production` (official, with configured approvals) and `NuGet-DryRun` (non-official, validation only). Both use `ob_release_environment` for OneBranch integration.
-11. **Compile-time conditional publish jobs** — `${{ if eq(parameters.releaseXxx, true) }}` template expansion ensures unselected publish jobs are excluded entirely from the pipeline run (not just skipped at runtime).
-12. **Mandatory dry-run for non-official** — the non-official variant hardcodes `dryRun: true` (no parameter), preventing accidental publication. The official variant defaults `releaseDryRun: true` for safety but allows override for actual releases.
-13. **Selective build parameters** — `buildSqlClient`, `buildSqlServerServer`, and `buildAKVProvider` allow building subsets of packages, with dependency-aware conditionals ensuring Logging builds when either SqlClient or AKV is needed.
+Defined in `stages/build-stages.yml`. Four build stages plus validation, ordered by dependency:
+
+- **`build_independent`** (Stage 1) — Logging and SqlServer.Server in parallel; no inter-package dependencies
+- **`build_abstractions`** (Stage 2) — Abstractions; `dependsOn: build_independent`; downloads Logging artifact
+- **`build_dependent`** (Stage 3) — SqlClient and Extensions.Azure in parallel; `dependsOn: build_abstractions`; downloads Abstractions + Logging artifacts
+- **`build_addons`** (Stage 4) — AKV Provider; `dependsOn: build_dependent`; downloads SqlClient + Abstractions + Logging artifacts
+- **`mds_package_validation`** — Validates signed SqlClient package; `dependsOn: build_dependent`; runs in parallel with Stage 4
+
+Each build job copies PDB files into `$(JOB_OUTPUT)/symbols/` so they are included in the auto-published pipeline artifact alongside the NuGet packages in `$(JOB_OUTPUT)/packages/`.
+
+Stage conditional rules:
+- Wrap stages/jobs in `${{ if }}` compile-time conditionals based on build parameters
+- `buildSqlClient` controls Stages 2, 3, validation, and Logging (when AKV is disabled)
+- `buildAKVProvider AND buildSqlClient` controls Stage 4
+- `buildSqlServerServer` controls SqlServer.Server job in Stage 1
+- Logging builds when `buildAKVProvider OR buildSqlClient` is true
+
+## Job Templates
+
+- **`build-signed-csproj-package-job.yml`** — Generic job for csproj-based packages (Logging, SqlServer.Server, Abstractions, Azure, AKV Provider). Flow: Build DLLs → ESRP DLL signing → NuGet pack (`NoBuild=true`) → ESRP NuGet signing → Copy PDBs to artifact
+- **`build-signed-sqlclient-package-job.yml`** — SqlClient-specific job (nuspec-based). Flow: Build all configurations → ESRP DLL signing (main + resource DLLs) → NuGet pack via nuspec → ESRP NuGet signing → Copy PDBs to artifact
+- **`validate-signed-package-job.yml`** — Validates signed MDS package (signature, strong names, folder structure, target frameworks)
+- **`publish-nuget-package-job.yml`** — Reusable release job using OneBranch `templateContext.type: releaseJob` with `inputs` for artifact download; pushes via `NuGetCommand@2`
+- **`publish-symbols-job.yml`** — Reusable symbols job: downloads a build artifact, locates PDBs under `symbols/`, and invokes `publish-symbols-step.yml`
+
+When adding a new csproj-based package:
+- Use `build-signed-csproj-package-job.yml` with appropriate `packageName`, `packageFullName`, `versionProperties`, and `downloadArtifacts`
+- Add build and pack targets to `build.proj`
+- Add version variables to `variables/common-variables.yml`
+- Add artifact name variable to `variables/onebranch-variables.yml`
+
+## Symbols Publishing Stage
+
+- Defined in `stages/publish-symbols-stage.yml`; produces stage `publish_symbols`
+- Entire stage excluded at compile time when `publishSymbols` is false
+- `dependsOn` is conditional based on which `build*` parameters are set, mirroring the build stage dependency graph
+- One job per package (`publish-symbols-job.yml`), each downloading its build artifact and publishing PDBs from `symbols/`
+- Each package's PDBs are published separately with unique artifact names and version information
+- Build jobs copy PDBs into `$(JOB_OUTPUT)/symbols/` so they are included in the auto-published artifact
+- The `publish-symbols-step.yml` accepts a `symbolsFolder` parameter to point at the downloaded PDB location
+- The publish step calls an extracted `publish-symbols.ps1` script with structured error handling and diagnostic logging
+- Symbols publishing credentials come from the `Symbols Publishing` variable group
+
+## Release Stage
+
+- Defined in `stages/release-stages.yml`; produces stage `release_production` (official) or `release_test` (non-official) via `stageNameSuffix` parameter
+- Entire stage excluded at compile time when no release parameters are true
+- `dependsOn` is conditional based on which release parameters are set
+- `releaseToProduction` parameter controls NuGet target feed:
+ - `true` → service connection `ADO Nuget Org Connection` (NuGet Production)
+ - `false` → service connection `ADO Nuget Org Test Connection` (NuGet Test)
+- Non-official pipeline always sets `releaseToProduction: false`
+- Environment gating:
+ - Official: `ob_release_environment: Production`, `ob_deploymentjob_environment: NuGet-Production`
+ - Non-official: `ob_release_environment: Test`, `ob_deploymentjob_environment: NuGet-DryRun`
+- Each publish job uses OneBranch deployment job syntax (`templateContext.type: releaseJob` with `inputs` for artifact download)
+
+## Parameters
+
+Build parameters (all boolean, default `true`):
+- `debug` — enable debug output (default `false`)
+- `isPreview` — use preview version numbers (default `false`)
+- `publishSymbols` — publish symbols to servers (default `false`)
+- `buildSqlServerServer` — build SqlServer.Server package
+- `buildSqlClient` — build SqlClient, Extensions.Azure, Abstractions, and Logging
+- `buildAKVProvider` — build AKV Provider (requires `buildSqlClient`)
+
+Release parameters (all boolean, default `false`):
+- `releaseSqlServerServer`, `releaseLogging`, `releaseAbstractions`, `releaseSqlClient`, `releaseAzure`, `releaseAKVProvider`
+
+Official-only parameter:
+- `releaseToProduction` — push to NuGet Production feed (default `false`)
+
+When `isPreview` is true, pipeline resolves `effective*Version` variables to preview versions; otherwise GA versions. All versions defined in `variables/common-variables.yml`.
+
+## Variables and Versions
+
+- Variable chain: pipeline YAML → `variables/onebranch-variables.yml` → `variables/common-variables.yml`
+- All package versions (GA, preview, assembly file) centralized in `variables/common-variables.yml`
+- `effective*Version` pipeline variables map to selected version set based on `isPreview`
+- Artifact name variables defined in `variables/onebranch-variables.yml` following `drop__` pattern
+- `assemblyBuildNumber` derived from first segment of `Build.BuildNumber` only (16-bit limit)
+- When adding a new package, add GA version, preview version, and assembly file version entries
+
+Variable groups:
+- `Symbols Publishing` — symbol publishing credentials (in `onebranch-variables.yml`)
+- `ESRP Federated Creds (AME)` — ESRP signing credentials (in `common-variables.yml`)
+
+## Code Signing (ESRP)
+
+- Uses ESRP v6 tasks (`EsrpMalwareScanning@6`, `EsrpCodeSigning@6`) with MSI/federated identity authentication
+- Signing only runs when `isOfficial: true` — non-official pipelines skip ESRP steps
+- csproj-based packages: sign DLLs first → pack with `NoBuild=true` → sign NuGet package (ensures NuGet contains signed DLLs)
+- SqlClient: sign DLLs (including resource DLLs) → nuspec pack → sign NuGet package
+- DLL signing uses keyCode `CP-230012` (Authenticode); NuGet signing uses keyCode `CP-401405`
+- All ESRP credentials come from variable groups — never hardcode secrets in YAML
+
+## SDL and Compliance
+
+- TSA: enabled only in official pipeline; disabled in non-official to avoid spurious alerts
+- ApiScan: enabled in both; currently `break: false` pending package registration
+- Each build job sets `ob_sdl_apiscan_softwareFolder` to `$(JOB_OUTPUT)/assemblies` and `ob_sdl_apiscan_symbolsFolder` to `$(JOB_OUTPUT)/symbols`
+- CodeQL, SBOM, Policheck (`break: true`): enabled in both pipelines
+- asyncSdl `enabled: false` in both; individual sub-tools (CredScan, BinSkim, Armory, Roslyn) configured underneath
+- Policheck exclusions: `$(REPO_ROOT)\.config\PolicheckExclusions.xml`
+- CredScan suppressions: `$(REPO_ROOT)/.config/CredScanSuppressions.json`
+
+## Artifact Conventions
+
+- `ob_outputDirectory` set to `$(JOB_OUTPUT)` (= `$(REPO_ROOT)/output`) — OneBranch auto-publishes this directory
+- Each published artifact uses subdirectories to separate file types:
+ - `assemblies/` — DLL assemblies for APIScan (preserving TFM folder structure)
+ - `packages/` — NuGet packages (`.nupkg`, `.snupkg`)
+ - `symbols/` — PDB symbol files (preserving TFM folder structure, shared by APIScan and symbol publishing)
+- Artifact names follow `drop__` — defined in `variables/onebranch-variables.yml`
+- Downstream jobs download artifacts via `DownloadPipelineArtifact@2` into `$(Build.SourcesDirectory)/packages`
+- Downloaded packages serve as a local NuGet source for `dotnet restore`
+- If stage or job names change, update artifact name variables in `onebranch-variables.yml`
+
+## Common Pitfalls
+
+- Do not use `PublishPipelineArtifacts` task — OneBranch auto-publishes from `ob_outputDirectory`
+- Do not add `NuGetToolInstaller@1` in OneBranch containers — NuGet is pre-installed
+- Variable templates are under `variables/` not `libraries/`
+- Always test parameter changes in the non-official pipeline first
+- When modifying stage names, update all `dependsOn` references and artifact name variables
+- Release jobs must use `templateContext.type: releaseJob` with `inputs` for artifact download — deployment jobs do not auto-download artifacts
diff --git a/eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml b/eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml
index 01d9b61da1..94e6438ef5 100644
--- a/eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml
+++ b/eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml
@@ -15,6 +15,29 @@
# signed DLLs, and finally ESRP signs the NuGet packages.
parameters:
+
+ # Signing Parameters -----------------------------------------------------
+
+ - name: signingAppRegistrationClientId
+ type: string
+
+ - name: signingAppRegistrationTenantId
+ type: string
+
+ - name: signingAuthAkvName
+ type: string
+
+ - name: signingAuthSignCertName
+ type: string
+
+ - name: signingEsrpClientId
+ type: string
+
+ - name: signingEsrpConnectedServiceName
+ type: string
+
+ # OTHERS +=====================================
+
# Short package name used in the job name, display strings, filesystem paths, and as a suffix for
# the default Build and Pack targets if those aren't specified.
- name: packageName
@@ -31,31 +54,23 @@ parameters:
- name: packageFullName
type: string
- # The version of the package. This is used for symbol publishing. It is not used for the DLL or
- # NuGet package versions since those are supplied via the versionProperties parameter.
- - name: packageVersion
- type: string
-
# The MSBuild build target in build.proj (e.g. BuildLogging). If not specified, defaults to
# Build.
- name: buildTarget
type: string
default: ""
+ # True to enable ESRP malware scanning and code signing steps, which should not be
+ # run on non-official pipelines as they access production resources.
+ - name: isOfficial
+ type: boolean
+
# The MSBuild pack target in build.proj (e.g. PackLogging). If not specified, defaults to
# Pack.
- name: packTarget
type: string
default: ""
- # The C# build configuration to build (e.g. Debug or Release).
- - name: buildConfiguration
- type: string
- values:
- - Debug
- - Release
- default: Release
-
# Additional MSBuild -p: arguments for version properties. These may include versions of
# packages this package depends on, or versions for this package itself.
- name: versionProperties
@@ -66,29 +81,6 @@ parameters:
- name: assemblyFileVersion
type: string
- # True to publish symbols to private and public servers.
- - name: publishSymbols
- type: boolean
-
- # Values required by ESRP tasks.
- - name: esrpConnectedServiceName
- type: string
-
- - name: esrpClientId
- type: string
-
- - name: appRegistrationClientId
- type: string
-
- - name: appRegistrationTenantId
- type: string
-
- - name: authAkvName
- type: string
-
- - 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.
@@ -103,15 +95,20 @@ jobs:
type: windows
variables:
- ob_outputDirectory: $(PACK_OUTPUT)
+ # Inform OneBranch that files put in this directory should be uploaded as artifacts.
+ ob_outputDirectory: $(JOB_OUTPUT)
+
# APIScan configuration for this Extension package
ob_sdl_apiscan_enabled: true
- ob_sdl_apiscan_softwareFolder: $(Build.SourcesDirectory)/apiScan/${{ parameters.packageName }}/dlls
- ob_sdl_apiscan_symbolsFolder: $(Build.SourcesDirectory)/apiScan/${{ parameters.packageName }}/pdbs
+ ob_sdl_apiscan_softwareFolder: $(JOB_OUTPUT)/assemblies
+ ob_sdl_apiscan_symbolsFolder: $(JOB_OUTPUT)/symbols
ob_sdl_apiscan_softwarename: ${{ parameters.packageFullName }}
ob_sdl_apiscan_versionNumber: ${{ parameters.assemblyFileVersion }}
+ # If parameters.buildTarget is not provided, default to "Build{parameters.packageName}"
buildTarget: ${{ coalesce(parameters.buildTarget, format('Build{0}', parameters.packageName)) }}
+
+ # If parameters.packTarget is not provided, default to "Pack{parameters.packageName}"
packTarget: ${{ coalesce(parameters.packTarget, format('Pack{0}', parameters.packageName)) }}
steps:
@@ -123,79 +120,97 @@ jobs:
displayName: Download ${{ artifact.displayName }}
inputs:
artifactName: ${{ artifact.artifactName }}
- targetPath: $(Build.SourcesDirectory)/packages
+ targetPath: $(JOB_INPUT)
# Install the .NET SDK.
- template: /eng/pipelines/steps/install-dotnet.yml@self
# Perform Roslyn analysis before building, since this step will clobber build output.
- - template: /eng/pipelines/onebranch/steps/code-analyze-step.yml@self
+ - template: /eng/pipelines/onebranch/steps/roslyn-analyzers-csproj-step.yml@self
parameters:
+ buildTarget: '${{ variables.buildTarget }}'
msBuildArguments: >-
- -t:$(buildTarget)
- -p:Configuration=${{ parameters.buildConfiguration }}
+ -p:Configuration=Release
-p:ReferenceType=Package
${{ parameters.versionProperties }}
# Build the package, producing DLLs only (no NuGet package yet).
- - template: /eng/pipelines/onebranch/steps/compound-build-csproj-step.yml@self
+ - template: /eng/pipelines/onebranch/steps/build-csproj-step.yml@self
parameters:
- buildTarget: $(buildTarget)
- buildConfiguration: ${{ parameters.buildConfiguration }}
+ buildTarget: '${{ variables.buildTarget }}'
versionProperties: ${{ parameters.versionProperties }}
- # ESRP sign the DLLs.
- - template: /eng/pipelines/onebranch/steps/compound-esrp-dll-signing-step.yml@self
- parameters:
- appRegistrationClientId: ${{ parameters.appRegistrationClientId }}
- appRegistrationTenantId: ${{ parameters.appRegistrationTenantId }}
- authAkvName: ${{ parameters.authAkvName }}
- authSignCertName: ${{ parameters.authSignCertName }}
- esrpClientId: ${{ parameters.esrpClientId }}
- esrpConnectedServiceName: ${{ parameters.esrpConnectedServiceName }}
- pattern: ${{ parameters.packageFullName }}.dll
-
- # Copy signed DLLs and PDBs to APIScan folders.
+ - ${{ if eq(parameters.isOfficial, true) }}:
+ # ESRP sign the DLLs.
+ - template: /eng/pipelines/onebranch/steps/esrp-dll-signing-step.yml@self
+ parameters:
+ appRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ appRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ authAkvName: '${{ parameters.signingAuthAkvName }}'
+ authSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ esrpClientId: '${{ parameters.signingEsrpClientId }}'
+ esrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+ # Minimatch pattern (multi-line, one pattern per line).
+ # **/ matches any nested directory (e.g. net8.0/, netstandard2.0/fr/).
+ #
+ # Matches: net8.0/.dll
+ # netstandard2.0/fr/.resources.dll
+ pattern: |
+ **/${{ parameters.packageFullName }}.dll
+ **/${{ parameters.packageFullName }}.resources.dll
+
+ # Copy DLLs to the assemblies/ subdirectory for APIScan.
- task: CopyFiles@2
displayName: Copy DLLs for APIScan
inputs:
SourceFolder: $(BUILD_OUTPUT)/Package/bin
- Contents: "**/${{ parameters.packageFullName }}.dll"
- TargetFolder: $(ob_sdl_apiscan_softwareFolder)
+ # Matches: .dll (main assembly) across all TFM subdirs
+ # .resources.dll (localized satellite assemblies in locale subdirs, if any)
+ Contents: |
+ **/${{ parameters.packageFullName }}.dll
+ **/${{ parameters.packageFullName }}.resources.dll
+ TargetFolder: $(JOB_OUTPUT)/assemblies
# 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,
# etc.), and we need to keep those separate for APIScan to work correctly.
flattenFolders: false
+ # Copy PDBs into the output directory so they are included in the published pipeline
+ # artifact. The symbols publishing stage will download this artifact and publish PDBs
+ # for this package using the files under symbols/.
- task: CopyFiles@2
- displayName: Copy PDBs for APIScan
+ displayName: Copy PDBs for APIScan and Symbols Publishing
inputs:
SourceFolder: $(BUILD_OUTPUT)/Package/bin
- Contents: "**/${{ parameters.packageFullName }}.pdb"
- TargetFolder: $(ob_sdl_apiscan_symbolsFolder)
+ # Matches: .pdb across all TFM subdirs.
+ # Note: Resource DLLs are resource-only satellite assemblies and do not produce PDBs.
+ Contents: '**/${{ parameters.packageFullName }}.pdb'
+ TargetFolder: $(JOB_OUTPUT)/symbols
flattenFolders: false
# Pack the signed DLLs into NuGet package (NoBuild=true).
- - template: /eng/pipelines/onebranch/steps/compound-pack-csproj-step.yml@self
+ - template: /eng/pipelines/onebranch/steps/pack-csproj-step.yml@self
parameters:
- packTarget: $(packTarget)
- buildConfiguration: ${{ parameters.buildConfiguration }}
+ packTarget: ${{ variables.packTarget }}
versionProperties: ${{ parameters.versionProperties }}
- # ESRP sign the NuGet package.
- - template: /eng/pipelines/onebranch/steps/compound-esrp-nuget-signing-step.yml@self
- parameters:
- appRegistrationClientId: ${{ parameters.appRegistrationClientId }}
- appRegistrationTenantId: ${{ parameters.appRegistrationTenantId }}
- authAkvName: ${{ parameters.authAkvName }}
- authSignCertName: ${{ parameters.authSignCertName }}
- esrpClientId: ${{ parameters.esrpClientId }}
- esrpConnectedServiceName: ${{ parameters.esrpConnectedServiceName }}
- pattern: '${{ parameters.packageFullName }}.*nupkg'
-
- # Publish symbols to servers
- - ${{ if eq(parameters.publishSymbols, true) }}:
- - template: /eng/pipelines/onebranch/steps/publish-symbols-step.yml@self
+ - ${{ if eq(parameters.isOfficial, true) }}:
+ # ESRP sign the NuGet package.
+ - template: /eng/pipelines/onebranch/steps/esrp-nuget-signing-step.yml@self
parameters:
- packageFullName: ${{ parameters.packageFullName }}
- packageVersion: ${{ parameters.packageVersion }}
+ appRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ appRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ authAkvName: '${{ parameters.signingAuthAkvName }}'
+ authSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ esrpClientId: '${{ parameters.signingEsrpClientId }}'
+ esrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+ searchPath: $(JOB_OUTPUT)/packages
+ # Minimatch pattern with extglob.
+ # [0-9] matches a single digit, anchoring to the version segment so
+ # similarly-prefixed package names are not matched.
+ # ?(s) is an extglob that optionally matches 's'.
+ #
+ # Matches: .1.0.0.nupkg
+ # .1.0.0-preview.1.snupkg
+ # Excludes: .SomeOther.1.0.0.nupkg
+ searchPattern: '${{ parameters.packageFullName }}.[0-9]*.?(s)nupkg'
diff --git a/eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml b/eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml
index 98f5c811aa..83ac9325e6 100644
--- a/eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml
+++ b/eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml
@@ -4,135 +4,177 @@
# See the LICENSE file in the project root for more information. #
#################################################################################
-# This file is only included in MDS OneBranch Official pipelines.
+# Job that performs a build of Microsoft.Data.SqlClient using the build2.proj file.
parameters:
- # True to publish symbols to public and private feeds after the build completes.
- - name: publishSymbols
+ # Whether this build is for an "official" OneBranch pipeline. This is used to enable ESRP signing
+ # on the artifacts of this job.
+ - name: isOfficial
type: boolean
- # True if this is a preview build, which uses the preview version numbers from
- # common-variables.yml.
- - name: isPreview
- type: boolean
+ - name: signingAppRegistrationClientId
+ type: string
+
+ - name: signingAppRegistrationTenantId
+ type: string
+
+ - name: signingAuthAkvName
+ type: string
+
+ - name: signingAuthSignCertName
+ type: string
+
+ - name: signingEsrpClientId
+ type: string
+
+ - name: signingEsrpConnectedServiceName
+ type: string
+
+ # Package Parameters
+ - name: abstractionsArtifactName
+ type: string
+
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: loggingArtifactName
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientAssemblyFileVersion
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
jobs:
-- job: build_package_SqlClient
- displayName: 'Build Microsoft.Data.SqlClient'
- pool:
- type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs
-
- variables:
- ob_outputDirectory: $(PACK_OUTPUT)
- # APIScan configuration for this Extension package
- ob_sdl_apiscan_enabled: true
- ob_sdl_apiscan_softwareFolder: $(Build.SourcesDirectory)/apiScan/SqlClient/dlls
- ob_sdl_apiscan_symbolsFolder: $(Build.SourcesDirectory)/apiScan/SqlClient/pdbs
- ob_sdl_apiscan_softwarename: Microsoft.Data.SqlClient
- ob_sdl_apiscan_versionNumber: $(assemblyBuildNumber)
-
- ${{ if parameters.isPreview }}:
- abstractionsPackageVersion: $(abstractionsPackagePreviewVersion)
- loggingPackageVersion: $(loggingPackagePreviewVersion)
- mdsPackageVersion: $(mdsPackagePreviewVersion)
-
- steps:
- - script: SET
- displayName: 'Print Environment Variables'
-
- # Download the Abstractions and Logging packages from the previous stage into
- # packages/ so that they're available via the local NuGet feed when restoring MDS.
- # MDS depends on both Extensions.Abstractions and Internal.Logging.
- - 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
-
- # Build our tooling, which is required by the analysis step below, but
- # shouldn't be analyzed itself.
- - task: MSBuild@1
- displayName: 'Build Tooling'
- inputs:
- solution: '**/build.proj'
- configuration: Release
- msbuildArguments: -t:BuildTools
-
- # Perform analysis before building, since this step will clobber build output.
- - template: /eng/pipelines/onebranch/steps/code-analyze-step.yml@self
-
- # Build MDS, producing signed DLLs.
- - template: /eng/pipelines/onebranch/steps/build-all-configurations-signed-dlls-step.yml@self
- parameters:
- # These variables are sourced from common-variables.yml.
- abstractionsAssemblyFileVersion: $(abstractionsAssemblyFileVersion)
- abstractionsPackageVersion: $(abstractionsPackageVersion)
- loggingAssemblyFileVersion: $(loggingAssemblyFileVersion)
- loggingPackageVersion: $(loggingPackageVersion)
- mdsAssemblyFileVersion: $(mdsAssemblyFileVersion)
- mdsPackageVersion: $(mdsPackageVersion)
-
- - template: /eng/pipelines/onebranch/steps/esrp-code-signing-step.yml@self
- parameters:
- artifactType: dll
- sourceRoot: $(BUILD_OUTPUT)
- dllPattern: 'Microsoft.Data.SqlClient.dll'
-
- - template: /eng/pipelines/onebranch/steps/esrp-code-signing-step.yml@self
- parameters:
- artifactType: dll
- sourceRoot: $(BUILD_OUTPUT)
- dllPattern: 'Microsoft.Data.SqlClient.resources.dll'
-
- - template: /eng/pipelines/common/templates/steps/generate-nuget-package-step.yml@self
- parameters:
- buildConfiguration: Release
- displayName: 'Create MDS NuGet Package'
- generateSymbolsPackage: true
- installNuget: false
- nuspecPath: $(nuspecPath)
- outputDirectory: $(PACK_OUTPUT)
- packageVersion: $(mdsPackageVersion)
- properties: 'AbstractionsPackageVersion=$(abstractionsPackageVersion);LoggingPackageVersion=$(loggingPackageVersion)'
- referenceType: Package
-
- - template: /eng/pipelines/onebranch/steps/esrp-code-signing-step.yml@self
- parameters:
- artifactType: pkg
- nupkgPattern: 'Microsoft.Data.SqlClient.$(mdsPackageVersion).*nupkg'
-
- # Copy signed DLLs and PDBs to APIScan folders.
- - task: CopyFiles@2
- displayName: Copy DLLs for APIScan
- inputs:
- SourceFolder: $(BUILD_OUTPUT)/Package/bin
- Contents: '**/Microsoft.Data.SqlClient.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,
- # etc.), and we need to keep those separate for APIScan to work correctly.
- flattenFolders: false
-
- - task: CopyFiles@2
- displayName: Copy PDBs for APIScan
- inputs:
- SourceFolder: $(BUILD_OUTPUT)/Package/bin
- Contents: '**/Microsoft.Data.SqlClient.pdb'
- TargetFolder: $(ob_sdl_apiscan_symbolsFolder)
- flattenFolders: false
-
- # Publish symbols to servers
- - ${{ if eq(parameters.publishSymbols, true) }}:
- - template: /eng/pipelines/onebranch/steps/publish-symbols-step.yml@self
- parameters:
- packageFullName: Microsoft.Data.SqlClient
- packageVersion: $(mdsPackageVersion)
+ - job: build_package_SqlClient
+ displayName: 'Build Microsoft.Data.SqlClient'
+ pool:
+ type: windows
+
+ variables:
+ ob_outputDirectory: '$(JOB_OUTPUT)'
+ ob_sdl_apiscan_softwareFolder: $(JOB_OUTPUT)/assemblies
+ ob_sdl_apiscan_symbolsFolder: $(JOB_OUTPUT)/symbols
+ ob_sdl_apiscan_softwarename: 'Microsoft.Data.SqlClient'
+ ob_sdl_apiscan_versionNumber: ${{ parameters.sqlClientAssemblyFileVersion }}
+
+ steps:
+ # Dump environment and parameters
+ - template: /eng/pipelines/onebranch/steps/script-output-environment-variables-step.yml@self
+
+ - powershell: |
+ $jsonParams = '${{ convertToJson(parameters) }}' -replace '\\', '\\'
+ $jsonParams | ConvertFrom-Json | Format-List
+ displayName: 'Output Job Parameters'
+
+ # Download Abstractions and Logging packages from previous stages into /packages/ so they
+ # are available via the local NuGet feed when restoring.
+ # @TODO: With the new build2.proj pack targets, this technically is not necessary.
+ - task: DownloadPipelineArtifact@2
+ displayName: Download Microsoft.Data.SqlClient.Extensions.Abstractions Artifact
+ inputs:
+ artifactName: '${{ parameters.abstractionsArtifactName }}'
+ targetPath: '$(JOB_INPUT)'
+
+ - task: DownloadPipelineArtifact@2
+ displayName: Download Microsoft.Data.SqlClient.Extensions.Logging Artifact
+ inputs:
+ artifactName: '${{ parameters.loggingArtifactName }}'
+ targetPath: '$(JOB_INPUT)'
+
+ # 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/onebranch/steps/roslyn-analyzers-sqlclient-step.yml@self
+ parameters:
+ abstractionsPackageVersion: '${{ parameters.abstractionsPackageVersion }}'
+ loggingPackageVersion: '${{ parameters.loggingPackageVersion }}'
+ sqlClientPackageVersion: '${{ parameters.sqlClientPackageVersion }}'
+
+ # Perform the actual build
+ - template: /eng/pipelines/onebranch/steps/build-sqlclient-step.yml@self
+ parameters:
+ abstractionsPackageVersion: '${{ parameters.abstractionsPackageVersion }}'
+ loggingPackageVersion: '${{ parameters.loggingPackageVersion }}'
+ sqlClientPackageVersion: '${{ parameters.sqlClientPackageVersion }}'
+
+ # Sign the DLLs
+ - ${{ if parameters.isOfficial }}:
+ - template: /eng/pipelines/onebranch/steps/esrp-dll-signing-step.yml@self
+ parameters:
+ appRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ appRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ authAkvName: '${{ parameters.signingAuthAkvName }}'
+ authSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ esrpClientId: '${{ parameters.signingEsrpClientId }}'
+ esrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+ # Minimatch pattern (multi-line, one pattern per line).
+ # **/ matches any nested directory (e.g. net8.0/, net462/fr/).
+ #
+ # Matches: net8.0/Microsoft.Data.SqlClient.dll
+ # net462/fr/Microsoft.Data.SqlClient.resources.dll
+ # Excludes: net8.0/Microsoft.Data.SqlClient.SNI.dll (no ** path matches)
+ pattern: |
+ **/Microsoft.Data.SqlClient.dll
+ **/Microsoft.Data.SqlClient.resources.dll
+
+ # Copy DLLs to the assemblies/ subdirectory for APIScan.
+ - task: CopyFiles@2
+ displayName: Copy DLLs for APIScan
+ inputs:
+ SourceFolder: '$(BUILD_OUTPUT)/Microsoft.Data.SqlClient/Package-Release'
+ # Matches: Microsoft.Data.SqlClient.dll (main assembly)
+ # Microsoft.Data.SqlClient.resources.dll (localized satellite assemblies in locale subdirs)
+ # Excludes: Microsoft.Data.SqlClient.SNI*.dll (native SNI — not part of this package)
+ Contents: |
+ **/Microsoft.Data.SqlClient.dll
+ **/Microsoft.Data.SqlClient.resources.dll
+ TargetFolder: '$(JOB_OUTPUT)/assemblies'
+ flattenFolders: false
+
+ # Copy PDBs into the output directory so they are included in the published pipeline
+ # artifact. The symbols publishing stage will download this artifact and publish PDBs
+ # for this package using the files under symbols/.
+ - task: CopyFiles@2
+ displayName: Copy PDBs for APIScan and Symbols Publishing
+ inputs:
+ SourceFolder: '$(BUILD_OUTPUT)/Microsoft.Data.SqlClient/Package-Release'
+ # Matches: Microsoft.Data.SqlClient.pdb (main assembly symbols)
+ # Excludes: Microsoft.Data.SqlClient.SNI*.pdb (native SNI — symbols published separately)
+ # Note: Resource DLLs are resource-only satellite assemblies and do not produce PDBs.
+ Contents: '**/Microsoft.Data.SqlClient.pdb'
+ TargetFolder: '$(JOB_OUTPUT)/symbols'
+ flattenFolders: false
+
+ # Package the build output into a NuGet package
+ - template: /eng/pipelines/onebranch/steps/pack-sqlclient-step.yml@self
+ parameters:
+ abstractionsPackageVersion: '${{ parameters.abstractionsPackageVersion }}'
+ loggingPackageVersion: '${{ parameters.loggingPackageVersion }}'
+ sqlClientPackageVersion: '${{ parameters.sqlClientPackageVersion }}'
+
+ # Sign the NuGet packages
+ - ${{ if parameters.isOfficial }}:
+ - template: /eng/pipelines/onebranch/steps/esrp-nuget-signing-step.yml@self
+ parameters:
+ appRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ appRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ authAkvName: '${{ parameters.signingAuthAkvName }}'
+ authSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ esrpClientId: '${{ parameters.signingEsrpClientId }}'
+ esrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+ searchPath: '$(JOB_OUTPUT)/packages'
+ # Minimatch pattern with extglob.
+ # [0-9] matches a single digit, anchoring to the version segment so
+ # names like Microsoft.Data.SqlClient.SNI are not matched.
+ # ?(s) is an extglob that optionally matches 's'.
+ #
+ # Matches: Microsoft.Data.SqlClient.6.1.0.nupkg
+ # Microsoft.Data.SqlClient.6.1.0.snupkg
+ # Excludes: Microsoft.Data.SqlClient.SNI.6.0.0.nupkg
+ searchPattern: 'Microsoft.Data.SqlClient.[0-9]*.?(s)nupkg'
diff --git a/eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml b/eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml
index c04a2eceef..21d36b9640 100644
--- a/eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml
+++ b/eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml
@@ -38,15 +38,18 @@ parameters:
# artifact. For example, if we're publishing the SqlClient package, and the build job publishes a
# pipeline artifact with the following structure:
#
- # drop_BuildAndTest_PackageReference/
- # ├── Microsoft.Data.SqlClient.5.0.0.nupkg
- # ├── Microsoft.Data.SqlClient.5.0.0.snupkg
- # ├── Microsoft.Data.SqlClient.Extensions.Abstractions.1.0.0.nupkg
- # └── other-file.txt
+ # drop_build_independent_build_logging/
+ # ├── packages/
+ # │ ├── Microsoft.Data.SqlClient.5.0.0.nupkg
+ # │ └── Microsoft.Data.SqlClient.5.0.0.snupkg
+ # └── symbols/
+ # └── ...
#
- # Then the packagePath should be 'Microsoft.Data.SqlClient.5.0.0.nupkg'.
+ # Then the packagePath should be 'packages/Microsoft.Data.SqlClient.5.0.0.nupkg'.
#
- # Defaults to '${{ parameters.packageName }}.*.nupkg' to match any version of the package.
+ # Defaults to 'packages/${{ parameters.packageName }}.*.nupkg' to match any version of the
+ # package. Only .nupkg files are pushed; .snupkg files are included automatically by NuGet
+ # when they exist alongside the .nupkg in the same directory.
#
- name: packagePath
type: string
@@ -65,13 +68,13 @@ jobs:
variables:
- name: ob_outputDirectory
- value: $(Build.SourcesDirectory)/output
+ value: $(JOB_OUTPUT)
- name: artifactPath
value: $(Pipeline.Workspace)/${{ parameters.artifactName }}
- name: packageToPush
- value: $(artifactPath)/${{ coalesce(parameters.packagePath, format('{0}.*.nupkg', parameters.packageName)) }}
+ value: $(artifactPath)/${{ coalesce(parameters.packagePath, format('packages/{0}.*.nupkg', parameters.packageName)) }}
# Template context inputs are used to pass parameters to the deployment job since it doesn't
# automatically download pipeline artifacts.
diff --git a/eng/pipelines/onebranch/jobs/publish-symbols-job.yml b/eng/pipelines/onebranch/jobs/publish-symbols-job.yml
new file mode 100644
index 0000000000..21b20476cd
--- /dev/null
+++ b/eng/pipelines/onebranch/jobs/publish-symbols-job.yml
@@ -0,0 +1,95 @@
+#################################################################################
+# 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. #
+#################################################################################
+
+# Reusable job template for publishing symbols for a single package. Downloads the pipeline
+# artifact produced by a build job, then invokes publish-symbols-step.yml to upload and publish
+# the PDB files to the internal and public symbol servers.
+#
+# Each package's PDBs are published separately to maintain unique naming and versioning.
+# PDBs are expected to be located under the 'symbols/' directory within the downloaded
+# artifact.
+
+parameters:
+ # The pipeline artifact name to download (OneBranch naming: drop__).
+ - name: artifactName
+ type: string
+
+ # Short package name used in the job name (e.g. Logging, SqlServer, SqlClient).
+ - name: packageName
+ type: string
+
+ # The full NuGet package name (e.g. Microsoft.Data.SqlClient.Internal.Logging).
+ - name: packageFullName
+ type: string
+
+ # The package version, used for symbol versioning.
+ - name: packageVersion
+ type: string
+
+ # Pattern to use to search for PDB files to upload/publish, relative to the symbols folder.
+ - name: searchPattern
+ type: string
+
+ # Symbols Publishing Parameters ------------------------------------------
+
+ - name: symbolsAzureSubscription
+ type: string
+
+ - name: symbolsPublishProjectName
+ type: string
+
+ - name: symbolsPublishServer
+ type: string
+
+ - name: symbolsPublishTokenUri
+ type: string
+
+ - name: symbolsUploadAccount
+ type: string
+
+jobs:
+ - job: publish_symbols_${{ parameters.packageName }}
+ displayName: 'Publish Symbols: ${{ parameters.packageFullName }}'
+ pool:
+ type: windows
+
+ variables:
+ # OneBranch requires ob_outputDirectory to be set, even if this job produces no artifacts.
+ ob_outputDirectory: $(JOB_OUTPUT)
+
+ # Disable SDL scanning — this job only uploads/publishes PDBs and produces no
+ # assemblies to scan. APIScan and BinSkim are handled by the build jobs.
+ ob_sdl_apiscan_enabled: false
+ ob_sdl_binskim_break: false
+ ob_sdl_binskim_enabled: false
+
+ # Path where the downloaded artifact will be placed.
+ artifactPath: $(Pipeline.Workspace)/${{ parameters.artifactName }}
+
+ # Path to the PDB files within the downloaded artifact.
+ symbolsPath: $(Pipeline.Workspace)/${{ parameters.artifactName }}/symbols
+
+ steps:
+ - task: DownloadPipelineArtifact@2
+ displayName: 'Download ${{ parameters.packageFullName }} Artifact'
+ inputs:
+ artifactName: '${{ parameters.artifactName }}'
+ targetPath: '$(artifactPath)'
+
+ - template: /eng/pipelines/onebranch/steps/publish-symbols-step.yml@self
+ parameters:
+ artifactName: '${{ parameters.packageFullName }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.packageVersion }}_$(System.TimelineId)_$(System.JobAttempt)'
+ azureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ packageName: '${{ parameters.packageFullName }}'
+ publishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ publishServer: '${{ parameters.symbolsPublishServer }}'
+ publishToInternal: true
+ publishToPublic: true
+ publishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ searchPattern: '${{ parameters.searchPattern }}'
+ symbolsFolder: '$(symbolsPath)'
+ uploadAccount: '${{ parameters.symbolsUploadAccount }}'
+ version: '${{ parameters.packageVersion }}'
diff --git a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml
index 656ea8f181..a99b46d45f 100644
--- a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml
+++ b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml
@@ -4,278 +4,354 @@
# See the LICENSE file in the project root for more information. #
#################################################################################
parameters:
-
- # The name of the pipeline artifacts to download prior to building the tests.
+ # The name of the pipeline artifact to download that contains the SqlClient NuGet package.
- name: artifactName
type: string
- # True if this build is a preview.
- - name: isPreview
+ # List of versions of dotnet that are *allowed to exist* in the NuGet package. Separators do not
+ # matter as the folders in lib, runtime, etc are simply checked to see if they exist in this
+ # string.
+ - name: expectedDotnetVersions
+ type: string
+ default: 'net462;net8.0;net9.0;netstandard2.0'
+
+ # Expected file version of the assemblies within the package. This should be of the form:
+ # (major).(minor).(patch).(buildNumber)
+ - name: expectedFileVersion
+ type: string
+
+ # List of folders that are *allowed to exist* in the NuGet package. Separators do not matter as
+ # the folders are simply checked to see if they exist in this string.
+ - name: expectedFolderNames
+ type: string
+ default: 'lib;ref;runtimes'
+
+ # Expected NuGet package version. Used to build the installation path. This should be of the
+ # form: (major).(minor).(patch)[-preview(preview_number)]
+ - name: expectedPackageVersion
+ type: string
+
+ # True if this build is an official build. This will be used to gate some checks
+ # that only apply to official builds, such as signature verification.
+ - name: isOfficial
type: boolean
jobs:
-- job: validate_signed_package
- displayName: 'Verify signed package'
-
- pool:
- type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs
- isCustom: true
- name: ADO-1ES-Pool
- vmImage: 'ADO-MMS22-SQL19'
-
- variables: # More settings at https://aka.ms/obpipelines/yaml/jobs
- - template: /eng/pipelines/onebranch/variables/sqlclient-validation-variables.yml@self
-
- - name: pathToDownloadedNuget # path to the downloaded nuget files
- value: $(Pipeline.Workspace)\${{parameters.artifactName }}
-
- - ${{ if parameters.isPreview }}:
- - name: extractedNugetPath
- value: $(extractedNugetRootPath).$(mdsPackagePreviewVersion)
- - name: mdsPackageVersion
- value: $(mdsPackagePreviewVersion)
-
- steps:
- - script: SET
- displayName: 'Print Environment Variables'
-
- - task: NuGetToolInstaller@1
- displayName: 'Use NuGet'
-
- - powershell: |
- # Displays the paths of all the local cache directories
- nuget locals all -List
-
- #Clears all files from all local cache directories
- nuget locals all -Clear
- displayName: 'Clear local cache'
-
- - download: current
- artifact: ${{parameters.artifactName}}
- patterns: '**/*.*nupkg'
- displayName: 'Download NuGet Package'
-
- - powershell: |
- # Install nuget package
- Install-Package -Name "Microsoft.Data.SqlClient" -Destination "$(TempFolderName)" -Force -Source $(pathToDownloadedNuget) -SkipDependencies
-
- Write-Host "--------------------------------------------------"
- Write-Host '$(TempFolderName)'
- ls $(TempFolderName)
- Write-Host "--------------------------------------------------"
- displayName: 'Extract Nuget in temp folder'
-
- - powershell: |
- Write-Host "--------------------------------------------------"
- Write-Host "This will verify the artifact signature" -ForegroundColor Green
- Write-Host "--------------------------------------------------"
-
- nuget verify -All $(pathToDownloadedNuget)\*.nupkg
- nuget verify -All $(pathToDownloadedNuget)\*.snupkg
- displayName: 'Verify nuget signature'
-
- - powershell: |
- # Recursively find all .dll files in TempFolder (installed nuget folder)
- # Microsoft.Data.SqlClient.dll and Microsoft.Data.SqlClient.resources.dll (in localized folders) should have strong name
- $dllFiles = Get-ChildItem -Path $(TempFolderName) -Recurse -Filter *.dll
- $badDlls = @()
- foreach ($file in $dllFiles)
- {
- # Run sn.exe to verify the strong name on each dll
- $result = & "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe" -vf $file.FullName
- Write-OutPut $result
-
- # if the dll is not valid, it would be delay signed or test-signed which is not meant for production
- if($result[$result.Length-1] -notlike "* is valid")
- {
- $badDlls += $result[$result.Length-1]
- }
- }
- if($badDlls.Count -gt 0)
- {
- Write-OutPut "Error: Invalid dlls are detected. Check the list below:"
- foreach($dll in $badDlls)
- {
- Write-Output $dll
- }
- Exit -1
- }
- Write-Host "Strong name has been verified for all dlls"
- displayName: 'Verify assembly strong names'
-
- - powershell: |
- # Checks the expected folder names such as lib, ref, runtimes
- Get-ChildItem -Path $(extractedNugetPath) -Directory | select Name | foreach {
- if('$(expectedFolderNames)'.contains($_.Name)){
- Write-Host expected folder name verfied: $_.Name
+ - job: validate_nuget_package
+ displayName: "Validate NuGet package"
+
+ pool:
+ type: windows # read more about custom job pool types at https://aka.ms/obpipelines/yaml/jobs
+ isCustom: true
+ name: ADO-1ES-Pool
+ vmImage: "ADO-MMS22-SQL19"
+
+ variables: # More settings at https://aka.ms/obpipelines/yaml/jobs
+
+ # Path within the downloaded artifact where NuGet packages are located.
+ - name: packagesPath
+ value: '$(Pipeline.Workspace)\${{ parameters.artifactName }}\packages'
+
+ # Path to the SqlClient NuGet package after installation. This path will only exist once the package
+ # been installed.
+ - name: nugetPackageInstallPath
+ value: '$(Pipeline.Workspace)\nugetPackageInstalls\Microsoft.Data.SqlClient.${{ parameters.expectedPackageVersion }}'
+
+ # Root folder where NuGet package will be installed locally
+ - name: nugetPackageInstallRoot
+ value: '$(Pipeline.Workspace)\nugetPackageInstalls'
+
+ steps:
+ - template: '/eng/pipelines/onebranch/steps/script-output-environment-variables-step.yml@self'
+
+ - task: NuGetToolInstaller@1
+ displayName: "Install NuGet"
+
+ - powershell: |
+ echo "> 1. List all local cache directory paths"
+ nuget locals all -List
+
+ echo "> 2. Clear all files from local cache directories"
+ nuget locals all -Clear
+ displayName: "Clear local cache"
+
+ # Download NuGet packages from the specified build artifact.
+ - download: current
+ artifact: ${{ parameters.artifactName }}
+ patterns: "**/*.*nupkg"
+ displayName: "Download NuGet Package"
+
+ # Verify secure signatures on the NuGet packages.
+ # NOTE: Packages will only be signed if the build is official.
+ - ${{ if eq(parameters.isOfficial, true) }}:
+ - powershell: |
+ # Propagate parameters to PS variables #######################
+ $packagesPath = "${{ variables.packagesPath }}"
+ echo "packagesPath= $packagesPath"
+
+ # Verify package signatures ##################################
+ echo "> 1. Verify signature of source package(s)"
+ nuget verify -All $packagesPath\*.nupkg
+
+ echo "> 2. Verify signature of symbols package(s)"
+ nuget verify -All $packagesPath\*.snupkg
+ displayName: "Verify nuget signature"
+
+ # Install NuGet package to the temporary directory
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $packagesPath = "${{ variables.packagesPath }}"
+ echo "packagesPath= $packagesPath"
+
+ $nugetPackageInstallRoot = "${{ variables.nugetPackageInstallRoot }}"
+ echo "nugetPackageInstallRoot= $nugetPackageInstallRoot"
+
+ # Install NuGet Package ##########################################
+ echo "> 1. Installing Microsoft.Data.SqlClient NuGet package..."
+ Install-Package `
+ -Name "Microsoft.Data.SqlClient" `
+ -Source "$packagesPath" `
+ -Destination $nugetPackageInstallRoot `
+ -Force `
+ -SkipDependencies
+
+ echo "> 2. Listing contents of installed Microsoft.Data.SqlClient NuGet package:"
+ Write-Host $nugetPackageInstallRoot
+ Get-ChildItem $nugetPackageInstallRoot
+ Write-Host "$packagesPath"
+ Get-ChildItem "$packagesPath"
+ displayName: "Install NuGet Package"
+
+ # Find all DLL files in the installed NuGet package, verify each is signed with a strong name
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
+
+ # Verify strong name signing #####################################
+ echo "> 1. Verifying strong name signing of DLLs ..."
+
+ # @TODO: This path seems brittle to VS upgrades, can we make it more flexible?
+ $snPath = "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe"
+
+ $dllFiles = Get-ChildItem -Path $nugetPackageInstallPath -Recurse -Filter *.dll
+ $badDlls = @()
+ foreach ($file in $dllFiles)
+ {
+ # Run sn.exe to verify the strong name on each dll
+ $result = & $snPath -vf $file.FullName
+ Write-OutPut $result
+
+ # if the dll is not valid, it would be delay signed or test-signed which is not meant for production
+ if($result[$result.Length-1] -notlike "* is valid")
+ {
+ $badDlls += $result[$result.Length-1]
+ }
}
- }
- displayName: 'Check expected folder names'
-
- - powershell: |
- # Checks the version of DotNetFramework and DotNet
- $countErr = 0
- $countPass = 0
- $excludNamesFromRuntimeFolder = 'lib','win','unix'
-
- Get-ChildItem -Path $(extractedNugetPath) -Directory | foreach {
- $parentname=$_.Name
- Write-Host $_.FullName -ForegroundColor yellow
-
- if($_.Name -ne 'runtimes') {
- Get-ChildItem -Path $_.FullName -Directory | select Name | foreach {
- if('$(expectedDotnetVersions)'.Contains($_.Name)){
- Write-Host "`tExpected version verified in $parentname": $_.Name -ForegroundColor green
- $countPass += 1
+ if($badDlls.Count -gt 0)
+ {
+ Write-OutPut "Error: Invalid dlls are detected. Check the list below:"
+ foreach($dll in $badDlls)
+ {
+ Write-Output $dll
}
- else{
- Write-Host "`tUnexpected version detected in $parentname": $_.Name
- $countErr += 1
+ Exit -1
+ }
+ Write-Host "Strong name has been verified for all dlls"
+ displayName: "Verify assembly strong names"
+
+ # Validate that the folders in the nuget are expected
+ # @TODO: This does not verify we are not missing any folders, only that the folders that
+ # exist are expected to exist.
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $expectedFolderNames = "${{ parameters.expectedFolderNames }}"
+ echo "expectedFolderNames= $expectedFolderNames"
+
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
+
+ # Verify folders are expected ####################################
+ Get-ChildItem -Path $nugetPackageInstallPath -Directory | select Name | foreach {
+ if($expectedFolderNames.contains($_.Name)){
+ Write-Host expected folder name verfied: $_.Name
}
}
- }
+ displayName: "Verify NuGet Root Folder Structure"
+
+ # Validate that the folders within the root folders of the nuget are expected
+ # @TODO: This does not verify we are not missing any folders, only that the folders that
+ # exist are expected to exist.
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $expectedDotnetVersions = "${{ parameters.expectedDotnetVersions }}"
+ echo "expectedDotnetVersions= $expectedDotnetVersions"
+
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
+
+ # Verify folders are expected ####################################
+ # Checks the version of DotNetFramework and DotNet
+ $countErr = 0
+ $countPass = 0
+ $excludNamesFromRuntimeFolder = 'lib','win','unix'
+
+ Get-ChildItem -Path $nugetPackageInstallPath -Directory | foreach {
+ $parentname=$_.Name
+ Write-Host $_.FullName -ForegroundColor yellow
+
+ if($_.Name -ne 'runtimes') {
+ Get-ChildItem -Path $_.FullName -Directory | select Name | foreach {
+ if($expectedDotnetVersions.Contains($_.Name)){
+ Write-Host "`tExpected version verified in $parentname": $_.Name -ForegroundColor green
+ $countPass += 1
+ }
+ else{
+ Write-Host "`tUnexpected version detected in $parentname": $_.Name
+ $countErr += 1
+ }
+ }
+ }
- elseif ($_.Name -eq 'runtimes'){
- Get-ChildItem -Depth 3 -Path $_.FullName -Exclude $excludNamesFromRuntimeFolder -Directory | foreach{
- if('$(expectedDotnetVersions)'.Contains($_.Name)){
- Write-Host "`tExpected version verfied in $parentname": $_.Name
- $countPass += 1
+ elseif ($_.Name -eq 'runtimes'){
+ Get-ChildItem -Depth 3 -Path $_.FullName -Exclude $excludNamesFromRuntimeFolder -Directory | foreach{
+ if('${{ parameters.expectedDotnetVersions }}'.Contains($_.Name)){
+ Write-Host "`tExpected version verfied in $parentname": $_.Name
+ $countPass += 1
+ }
+ else{
+ Write-Host "`tUnexpected version detected": $_.Name -ForegroundColor Red
+ $countErr += 1
+ }
+ }
}
else{
- Write-Host "`tUnexpected version detected": $_.Name -ForegroundColor Red
- $countErr += 1
+ Write-Host "`tUnknown folder " $_.Name -ForegroundColor Red
+ Exit -1
}
}
- }
- else{
- Write-Host "`tUnknown folder " $_.Name -ForegroundColor Red
- Exit -1
- }
- }
-
- Write-Host "_______________"
- Write-Host "Expected: $countPass"
- Write-Host "Unexpected: $countErr"
- Write-Host "_______________"
- if ($countErr -ne 0)
- {
- Write-Host "Unexpected versions are detected!" -ForegroundColor Red
- Exit -1
- }
- displayName: 'Check Expected framework'
-
- - powershell: |
- # list all the child items of created temp folder
-
- #Verify all DLLs unzipped match "expected" hierarchy
-
- foreach( $folderName in (Get-ChildItem -Path $(extractedNugetPath) -Directory).Name)
- {
- # List all Childerns of the Path
- Get-ChildItem -Path $(extractedNugetPath)\$folderName -Recurse -File
- $subFiles = Get-ChildItem -Path $(extractedNugetPath)\$folderName -Recurse -File
-
- foreach($file in $subFiles)
- {
- if($subFiles[0].Name -like "*.dll" )
+
+ Write-Host "_______________"
+ Write-Host "Expected: $countPass"
+ Write-Host "Unexpected: $countErr"
+ Write-Host "_______________"
+ if ($countErr -ne 0)
{
- Write-Host $subFiles[0].Name -ForegroundColor Green
- Write-Host $subFiles[1].Name -ForegroundColor Green
- if(($folderName -eq 'lib') -or ($folderName -eq 'ref'))
+ Write-Host "Unexpected versions are detected!" -ForegroundColor Red
+ Exit -1
+ }
+ displayName: "Verify NuGet DotNet Versions "
+
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
+
+ # Verify DLL Hierarchy ###########################################
+ foreach( $folderName in (Get-ChildItem -Path $nugetPackageInstallPath -Directory).Name)
+ {
+ # List all Childerns of the Path
+ Get-ChildItem -Path $nugetPackageInstallPath\$folderName -Recurse -File
+ $subFiles = Get-ChildItem -Path $nugetPackageInstallPath\$folderName -Recurse -File
+
+ foreach($file in $subFiles)
{
- if($subFiles[2].Name -like "*.dll")
+ if($subFiles[0].Name -like "*.dll" )
{
- Write-Host $subFiles[2].Name -ForegroundColor Green
+ Write-Host $subFiles[0].Name -ForegroundColor Green
+ Write-Host $subFiles[1].Name -ForegroundColor Green
+ if(($folderName -eq 'lib') -or ($folderName -eq 'ref'))
+ {
+ if($subFiles[2].Name -like "*.dll")
+ {
+ Write-Host $subFiles[2].Name -ForegroundColor Green
+ }
+ else
+ {
+ $subFiles[2].Name
+ Write-Host "Expected file pattern for localization did not match to *.dll" -ForegroundColor Red
+ Exit -1
+ }
+ }
}
else
{
- $subFiles[2].Name
- Write-Host "Expected file pattern for localization did not match to *.dll" -ForegroundColor Red
+ $subFiles[0].Name
+ $subFiles[1].Name
+ Write-Host "Expected file pattern did not match to *.dll" -ForegroundColor Red
Exit -1
}
}
}
- else
- {
- $subFiles[0].Name
- $subFiles[1].Name
- Write-Host "Expected file pattern did not match to *.dll" -ForegroundColor Red
- Exit -1
- }
- }
- }
- displayName: 'Verify all DLLs unzipped match "expected" hierarchy'
- - powershell: |
- # Verify all dlls status are Valid
-
- $dlls = Get-ChildItem -Path $(extractedNugetPath) -Recurse -Include *.dll
- foreach ($status in $dlls | Get-AuthenticodeSignature)
- {
- if ($status.Status -eq "Valid")
- {
- Write-Host $status.Status $status.Path
- }
- else
- {
- Write-Host "dll status of '$status.Path' is not valid!" -ForegroundColor Red
- $status
- Exit -1
- }
- }
- displayName: 'Verify all dlls status are Valid'
+ displayName: 'Verify all DLLs unzipped match "expected" hierarchy'
+
+ # Verify that all DLLs are authenticode signed
+ # NOTE: This signing is only performed on official builds.
+ - ${{ if eq(parameters.isOfficial, true) }}:
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
+
+ # Verify authenticode signature of DLLs ##########################
+ $dlls = Get-ChildItem -Path $nugetPackageInstallPath -Recurse -Include *.dll
+ foreach ($status in $dlls | Get-AuthenticodeSignature)
+ {
+ if ($status.Status -eq "Valid")
+ {
+ Write-Host $status.Status $status.Path
+ }
+ else
+ {
+ Write-Host "dll status of '$status.Path' is not valid!" -ForegroundColor Red
+ $status
+ Exit -1
+ }
+ }
+ displayName: "Verify all dlls status are Valid"
- - powershell: |
- # This will check each DLL's ProductVersion and FileVersion against
- # expected values.
- $failed = 0
+ - powershell: |
+ # Propagate pipeline to PS variables #############################
+ $expectedFileVersion = "${{ parameters.expectedFileVersion }}"
+ echo "expectedFileVersion= $expectedFileVersion"
- foreach ( $pVersion in Get-ChildItem *.dll -Path $(extractedNugetPath) -Recurse | ForEach-Object versioninfo )
- {
- if ($pVersion.ProductVersion -Like '$(mdsPackageVersion)*')
- {
- Write-Host -ForegroundColor Green "Correct ProductVersion detected for $($pVersion.FileName): $($pVersion.ProductVersion)"
- }
- else
- {
- Write-Host -ForegroundColor Red "Wrong ProductVersion detected for $($pVersion.FileName); expected: $(mdsPackageVersion); found: $($pVersion.ProductVersion)"
- $failed = 1
- }
+ $expectedPackageVersion = "${{ parameters.expectedPackageVersion }}"
+ echo "expectedPackageVersion= $expectedPackageVersion"
+
+ $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}"
+ echo "nugetPackageInstallPath= $nugetPackageInstallPath"
- if ($pVersion.FileVersion -eq '$(mdsAssemblyFileVersion)')
+ # Validate ProductVersion and FileVersion fields #################
+ $failed = 0
+ foreach ( $pVersion in Get-ChildItem *.dll -Path $nugetPackageInstallPath -Recurse | ForEach-Object versioninfo )
{
- Write-Host -ForegroundColor Green "Correct FileVersion detected for $($pVersion.FileName): $($pVersion.FileVersion)"
+ if ($pVersion.ProductVersion -Like $expectedPackageVersion + '*')
+ {
+ Write-Host -ForegroundColor Green "Correct ProductVersion detected for $($pVersion.FileName): $($pVersion.ProductVersion)"
+ }
+ else
+ {
+ Write-Host -ForegroundColor Red "Wrong ProductVersion detected for $($pVersion.FileName); expected: $expectedPackageVersion; found: $($pVersion.ProductVersion)"
+ $failed = 1
+ }
+
+ if ($pVersion.FileVersion -eq $expectedFileVersion)
+ {
+ Write-Host -ForegroundColor Green "Correct FileVersion detected for $($pVersion.FileName): $($pVersion.FileVersion)"
+ }
+ else
+ {
+ Write-Host -ForegroundColor Red "Wrong FileVersion detected for $($pVersion.FileName); expected $expectedFileVersion; found: $($pVersion.FileVersion)"
+ $failed = 1
+ }
+
+ # @TODO: We should do a check for assembly version here.
}
- else
+
+ if ($failed -ne 0)
{
- Write-Host -ForegroundColor Red "Wrong FileVersion detected for $($pVersion.FileName); expected $(mdsAssemblyFileVersion); found: $($pVersion.FileVersion)"
- $failed = 1
+ Exit -1
}
- }
-
- if ($failed -ne 0)
- {
- Exit -1
- }
-
- Get-ChildItem *.dll -Path $(extractedNugetPath) -Recurse | ForEach-Object VersionInfo | Format-List
- displayName: 'Verify "File Version" matches expected values for DLLs'
-
- - powershell: |
- # Check assembly versions.
- #
- # GOTCHA: This expects the Versions.props file having XML elements in a
- # certain order. If the order changes, this check will fail!
- #
- # TODO: This also isn't checking the versions of the actual assemblies in
- # the package, so it isn't terribly useful.
-
- [Xml] $versionprops = Get-Content -Path "tools/props/Versions.props"
- $AssemblyFileVersion = $versionprops.Project.PropertyGroup[2].AssemblyFileVersion
- $AssemblyVersion = $versionprops.Project.PropertyGroup[2].AssemblyVersion
-
- if($AssemblyFileVersion -eq $AssemblyVersion)
- {
- Write-Host AssemblyFileVersion: $AssemblyFileVersion should not be equal to: $AssemblyVersion
- Exit -1
- }
- displayName: 'Check "AssemblyFileVersion" is not same as "AssemblyVersion" in version.props'
+
+ Get-ChildItem *.dll -Path $nugetPackageInstallPath -Recurse | ForEach-Object VersionInfo | Format-List
+ displayName: 'Verify "File Version" matches expected values for DLLs'
diff --git a/eng/pipelines/onebranch/scripts/publish-symbols.ps1 b/eng/pipelines/onebranch/scripts/publish-symbols.ps1
new file mode 100644
index 0000000000..aeaa665a92
--- /dev/null
+++ b/eng/pipelines/onebranch/scripts/publish-symbols.ps1
@@ -0,0 +1,236 @@
+<#
+.SYNOPSIS
+ Publishes symbols to the Microsoft symbol publishing service (SymWeb/MSDL).
+
+.DESCRIPTION
+ This script is Step 2 of the two-step symbols publishing process. It requests
+ the Symbols Publishing Pipeline to publish previously uploaded PDB files to
+ internal (SymWeb) and/or public (MSDL) Microsoft symbol servers.
+
+ The two-step process:
+ Step 1 (PublishSymbols@2 task in publish-symbols-step.yml):
+ Uploads PDB files to the Azure DevOps symbol store under a unique
+ artifact name (SymbolsArtifactName). This stores the symbols but does
+ NOT make them available on SymWeb or MSDL.
+
+ Step 2 (this script):
+ Calls the Symbols Publishing Pipeline REST API to request that the
+ uploaded symbols be published to the symbol servers.
+
+ Step 2 depends on Step 1: the -ArtifactName parameter MUST match the
+ SymbolsArtifactName used by the PublishSymbols@2 upload task so that
+ both steps reference the same uploaded artifact.
+
+ This script performs four sub-steps:
+ 1. Acquires a bearer token from Azure CLI for the symbol publishing service.
+ 2. Registers a unique request name with the publishing service.
+ 3. Submits the request to publish symbols to the specified servers.
+ 4. Queries the publishing status for confirmation.
+
+ For more details on the Symbols Publishing Pipeline, see:
+ https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL
+
+.PARAMETER PublishServer
+ The hostname prefix of the symbol publishing service. This value is prepended to
+ '.trafficmanager.net' to construct the service base URL.
+
+.PARAMETER PublishTokenUri
+ The resource URI used to acquire a bearer token from Azure CLI
+ (via 'az account get-access-token --resource ').
+
+.PARAMETER PublishProjectName
+ The project name registered with the symbol publishing service (decided during onboarding).
+
+.PARAMETER ArtifactName
+ The name of the publishing request. This must match the SymbolsArtifactName used by
+ the PublishSymbols@2 upload task so that upload and publish reference the same artifact.
+
+.PARAMETER PublishToInternal
+ Whether to publish symbols to the internal symbol server. Defaults to $true.
+
+.PARAMETER PublishToPublic
+ Whether to publish symbols to the public symbol server. Defaults to $true.
+
+.EXAMPLE
+ .\publish-symbols.ps1 `
+ -PublishServer "mysymbolserver" `
+ -PublishTokenUri "https://login.microsoftonline.com/..." `
+ -PublishProjectName "Microsoft.Data.SqlClient.SNI" `
+ -ArtifactName "mds_symbols_MyProject_dotnet-sqlclient_main_7.0.0_abc123_1"
+
+ Publishes symbols to both internal and public servers using the specified parameters.
+
+.EXAMPLE
+ .\publish-symbols.ps1 `
+ -PublishServer "mysymbolserver" `
+ -PublishTokenUri "https://login.microsoftonline.com/..." `
+ -PublishProjectName "Microsoft.Data.SqlClient.SNI" `
+ -ArtifactName "mds_symbols_MyProject_dotnet-sqlclient_main_7.0.0_abc123_2" `
+ -PublishToPublic $false
+
+ Publishes symbols to the internal server only (retry attempt 2).
+
+.NOTES
+ File Name : publish-symbols.ps1
+ Requires : Azure CLI (az) must be installed and authenticated.
+ Called by : publish-symbols-step.yml (Azure Pipelines template)
+
+ Publishing status codes returned by the service:
+
+ PublishingStatus:
+ 0 - NotRequested: The request has not been requested to publish.
+ 1 - Submitted: The request is submitted to be published.
+ 2 - Processing: The request is still being processed.
+ 3 - Completed: Processing finished. Check PublishingResult for details.
+
+ PublishingResult:
+ 0 - Pending: The request has not completed or has not been requested.
+ 1 - Succeeded: The request published successfully.
+ 2 - Failed: The request failed to publish.
+ 3 - Cancelled: The request was cancelled.
+#>
+
+[CmdletBinding()]
+param(
+ [Parameter(Mandatory = $true, HelpMessage = "Hostname prefix of the symbol publishing service (prepended to .trafficmanager.net).")]
+ [ValidateNotNullOrEmpty()]
+ [string]$PublishServer,
+
+ [Parameter(Mandatory = $true, HelpMessage = "Resource URI for acquiring a bearer token via Azure CLI.")]
+ [ValidateNotNullOrEmpty()]
+ [string]$PublishTokenUri,
+
+ [Parameter(Mandatory = $true, HelpMessage = "Project name registered with the symbol publishing service.")]
+ [ValidateNotNullOrEmpty()]
+ [string]$PublishProjectName,
+
+ [Parameter(Mandatory = $true, HelpMessage = "Artifact name for the publishing request (must match PublishSymbols@2 SymbolsArtifactName).")]
+ [ValidateNotNullOrEmpty()]
+ [string]$ArtifactName,
+
+ [Parameter(Mandatory = $false, HelpMessage = "Publish symbols to the internal symbol server.")]
+ [bool]$PublishToInternal = $true,
+
+ [Parameter(Mandatory = $false, HelpMessage = "Publish symbols to the public symbol server.")]
+ [bool]$PublishToPublic = $true
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = "Stop"
+
+# --- Log input parameters ---
+Write-Host "=== Publish Symbols Parameters ==="
+Write-Host "PublishServer: ${PublishServer}"
+Write-Host "PublishTokenUri: ${PublishTokenUri}"
+Write-Host "PublishProjectName: ${PublishProjectName}"
+Write-Host "ArtifactName: ${ArtifactName}"
+Write-Host "PublishToInternal: ${PublishToInternal}"
+Write-Host "PublishToPublic: ${PublishToPublic}"
+Write-Host "=================================="
+
+# --- Build request name and URLs ---
+$requestName = ${ArtifactName}
+$baseUrl = "https://${PublishServer}.trafficmanager.net/projects/${PublishProjectName}"
+$registerUrl = "${baseUrl}/requests"
+$requestUrl = "${baseUrl}/requests/${requestName}"
+
+Write-Host "=== Constructed URLs ==="
+Write-Host "Request Name: ${requestName}"
+Write-Host "Base URL: ${baseUrl}"
+Write-Host "Register URL: ${registerUrl}"
+Write-Host "Request URL: ${requestUrl}"
+Write-Host "========================"
+
+# --- Step 1: Acquire token ---
+Write-Host "> 1. Acquiring symbol publishing token..."
+$symbolPublishingToken = az account get-access-token --resource ${PublishTokenUri} --query accessToken -o tsv
+if ($LASTEXITCODE -ne 0) {
+ throw "Failed to acquire symbol publishing token via Azure CLI (exit code: ${LASTEXITCODE})."
+}
+if ($null -ne $symbolPublishingToken) {
+ $symbolPublishingToken = $symbolPublishingToken.Trim()
+}
+if ([string]::IsNullOrWhiteSpace($symbolPublishingToken)) {
+ throw "Failed to acquire symbol publishing token via Azure CLI: received an empty or whitespace-only access token."
+}
+Write-Host "> 1. Symbol publishing token acquired."
+
+$authHeaders = @{ Authorization = "Bearer ${symbolPublishingToken}" }
+
+# --- Step 2: Register request name ---
+Write-Host "> 2. Registering request name..."
+$requestNameRegistrationBody = @{ requestName = $requestName } | ConvertTo-Json -Compress
+try {
+ Invoke-RestMethod -Method POST -Uri ${registerUrl} -Headers ${authHeaders} -ContentType "application/json" -Body ${requestNameRegistrationBody}
+} catch {
+ throw "Failed to register request name. URI: ${registerUrl} | Body: ${requestNameRegistrationBody} | Error: $_"
+}
+Write-Host "> 2. Request name registered successfully."
+
+# --- Step 3: Publish symbols ---
+Write-Host "> 3. Submitting request to publish symbols..."
+$publishSymbolsBody = @{
+ publishToInternalServer = $PublishToInternal
+ publishToPublicServer = $PublishToPublic
+} | ConvertTo-Json -Compress
+Write-Host "Publishing symbols request body: ${publishSymbolsBody}"
+try {
+ Invoke-RestMethod -Method POST -Uri ${requestUrl} -Headers ${authHeaders} -ContentType "application/json" -Body ${publishSymbolsBody}
+} catch {
+ throw "Failed to publish symbols. URI: ${requestUrl} | Body: ${publishSymbolsBody} | Error: $_"
+}
+Write-Host "> 3. Request to publish symbols submitted successfully."
+
+# --- Step 4: Check status ---
+Write-Host "> 4. Checking the status of the request..."
+try {
+ $status = Invoke-RestMethod -Method GET -Uri ${requestUrl} -Headers ${authHeaders} -ContentType "application/json"
+ $status
+} catch {
+ throw "Failed to check request status. URI: ${requestUrl} | Error: $_"
+}
+
+# Validate publishing results — fail the task when the service reports a terminal failure.
+# PublishingResult: 0=Pending, 1=Succeeded, 2=Failed, 3=Cancelled
+$resultLabels = @{ 0 = 'Pending'; 1 = 'Succeeded'; 2 = 'Failed'; 3 = 'Cancelled' }
+$failures = @()
+
+if ($PublishToInternal) {
+ $internalResult = $status.publishToInternalServerResult
+ if ($null -ne $internalResult -and $internalResult -ge 2) {
+ $label = if ($resultLabels.ContainsKey([int]$internalResult)) { $resultLabels[[int]$internalResult] } else { "Unknown($internalResult)" }
+ $failures += "Internal server publishing result: ${label} (${internalResult})"
+ }
+}
+
+if ($PublishToPublic) {
+ $publicResult = $status.publishToPublicServerResult
+ if ($null -ne $publicResult -and $publicResult -ge 2) {
+ $label = if ($resultLabels.ContainsKey([int]$publicResult)) { $resultLabels[[int]$publicResult] } else { "Unknown($publicResult)" }
+ $failures += "Public server publishing result: ${label} (${publicResult})"
+ }
+}
+
+if ($failures.Count -gt 0) {
+ $failureMessage = $failures -join '; '
+ throw "Symbol publishing reported a terminal failure. ${failureMessage}. URI: ${requestUrl}"
+}
+
+Write-Host "> 4. Status check completed - no terminal failures detected."
+
+Write-Host ""
+Write-Host "Use below tables to interpret the xxxServerStatus and xxxServerResult fields from the response."
+Write-Host ""
+Write-Host "PublishingStatus"
+Write-Host "-----------------"
+Write-Host "0 NotRequested - The request has not been requested to publish."
+Write-Host "1 Submitted - The request is submitted to be published."
+Write-Host "2 Processing - The request is still being processed."
+Write-Host "3 Completed - Processing finished. Check PublishingResult for details."
+Write-Host ""
+Write-Host "PublishingResult"
+Write-Host "-----------------"
+Write-Host "0 Pending - The request has not completed or has not been requested."
+Write-Host "1 Succeeded - The request published successfully."
+Write-Host "2 Failed - The request failed to publish."
+Write-Host "3 Cancelled - The request was cancelled."
diff --git a/eng/pipelines/onebranch/scripts/tests/README.md b/eng/pipelines/onebranch/scripts/tests/README.md
new file mode 100644
index 0000000000..447dda5d32
--- /dev/null
+++ b/eng/pipelines/onebranch/scripts/tests/README.md
@@ -0,0 +1,43 @@
+# Publish-Symbols Tests
+
+Pester tests for the `publish-symbols.ps1` script used by the symbol publishing pipeline step.
+
+## Prerequisites
+
+- PowerShell 5.1+ or PowerShell 7+
+- [Pester v5](https://pester.dev/) (`Install-Module Pester -MinimumVersion 5.0 -Scope CurrentUser`)
+
+## Running the Tests
+
+From this directory:
+
+```powershell
+Invoke-Pester ./publish-symbols.Tests.ps1
+```
+
+Or from the repository root:
+
+```powershell
+Invoke-Pester ./eng/pipelines/onebranch/scripts/tests/
+```
+
+For detailed output:
+
+```powershell
+Invoke-Pester ./publish-symbols.Tests.ps1 -Output Detailed
+```
+
+## Test Coverage
+
+| Area | What's tested |
+| --------------------- | ---------------------------------------------------------------- |
+| Parameter validation | Empty strings rejected for all mandatory parameters |
+| URL construction | Base URL, register URL, request URL built from parameters |
+| Request bodies | Registration body, default publish flags, flag overrides |
+| Error handling | Token failure, registration failure, publish failure, status failure — all verify expanded URI in error message |
+| Status validation | Detects Failed/Cancelled results, respects PublishToInternal/PublishToPublic flags, passes on Succeeded/Pending |
+
+## Notes
+
+- All external calls (`az`, `Invoke-RestMethod`) are mocked — no network access or Azure credentials are required.
+- Tests validate the script at `../publish-symbols.ps1` relative to this directory.
diff --git a/eng/pipelines/onebranch/scripts/tests/publish-symbols.Tests.ps1 b/eng/pipelines/onebranch/scripts/tests/publish-symbols.Tests.ps1
new file mode 100644
index 0000000000..4d16d54e96
--- /dev/null
+++ b/eng/pipelines/onebranch/scripts/tests/publish-symbols.Tests.ps1
@@ -0,0 +1,356 @@
+<#
+.SYNOPSIS
+ Pester tests for publish-symbols.ps1
+#>
+
+BeforeAll {
+ $scriptPath = Join-Path $PSScriptRoot '..' 'publish-symbols.ps1'
+}
+
+AfterAll {
+ # Clean up global variables used by mocks
+ Remove-Variable -Name 'restCalls' -Scope Global -ErrorAction SilentlyContinue
+ Remove-Variable -Name 'mockCallCount' -Scope Global -ErrorAction SilentlyContinue
+}
+
+Describe 'publish-symbols.ps1 Parameter Validation' {
+
+ It 'Should reject an empty PublishServer' {
+ { & $scriptPath -PublishServer '' -PublishTokenUri 'https://token' -PublishProjectName 'proj' -ArtifactName 'art' } |
+ Should -Throw
+ }
+
+ It 'Should reject an empty PublishTokenUri' {
+ { & $scriptPath -PublishServer 'server' -PublishTokenUri '' -PublishProjectName 'proj' -ArtifactName 'art' } |
+ Should -Throw
+ }
+
+ It 'Should reject an empty PublishProjectName' {
+ { & $scriptPath -PublishServer 'server' -PublishTokenUri 'https://token' -PublishProjectName '' -ArtifactName 'art' } |
+ Should -Throw
+ }
+
+ It 'Should reject an empty ArtifactName' {
+ { & $scriptPath -PublishServer 'server' -PublishTokenUri 'https://token' -PublishProjectName 'proj' -ArtifactName '' } |
+ Should -Throw
+ }
+}
+
+Describe 'publish-symbols.ps1 URL Construction' {
+
+ BeforeAll {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token-12345' }
+
+ $global:restCalls = @()
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:restCalls += @{
+ Method = $Method
+ Uri = $Uri
+ Body = $Body
+ }
+ return @{ publishToInternalServerStatus = 0; publishToPublicServerStatus = 0; publishToInternalServerResult = 0; publishToPublicServerResult = 0 }
+ }
+ }
+
+ BeforeEach {
+ $global:restCalls = @()
+ }
+
+ It 'Should construct the correct base URL from PublishServer and PublishProjectName' {
+ & $scriptPath `
+ -PublishServer 'myserver' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'My.Project' `
+ -ArtifactName 'test_artifact'
+
+ $global:restCalls.Count | Should -Be 3
+
+ # Registration call
+ $global:restCalls[0].Uri | Should -Be 'https://myserver.trafficmanager.net/projects/My.Project/requests'
+ $global:restCalls[0].Method | Should -Be 'POST'
+
+ # Publish call
+ $global:restCalls[1].Uri | Should -Be 'https://myserver.trafficmanager.net/projects/My.Project/requests/test_artifact'
+ $global:restCalls[1].Method | Should -Be 'POST'
+
+ # Status call
+ $global:restCalls[2].Uri | Should -Be 'https://myserver.trafficmanager.net/projects/My.Project/requests/test_artifact'
+ $global:restCalls[2].Method | Should -Be 'GET'
+ }
+
+ It 'Should use ArtifactName directly as the request name' {
+ & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'myartifact_3'
+
+ $global:restCalls[1].Uri | Should -BeLike '*myartifact_3'
+ $global:restCalls[2].Uri | Should -BeLike '*myartifact_3'
+ }
+}
+
+Describe 'publish-symbols.ps1 Request Bodies' {
+
+ BeforeAll {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token-12345' }
+
+ $global:restCalls = @()
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:restCalls += @{
+ Method = $Method
+ Uri = $Uri
+ Body = $Body
+ }
+ return @{ publishToInternalServerStatus = 0; publishToPublicServerStatus = 0; publishToInternalServerResult = 0; publishToPublicServerResult = 0 }
+ }
+ }
+
+ BeforeEach {
+ $global:restCalls = @()
+ }
+
+ It 'Should send the correct request name in the registration body' {
+ & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'my_artifact_1'
+
+ $body = $global:restCalls[0].Body | ConvertFrom-Json
+ $body.requestName | Should -Be 'my_artifact_1'
+ }
+
+ It 'Should default to publishing to both internal and public servers' {
+ & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art'
+
+ $body = $global:restCalls[1].Body | ConvertFrom-Json
+ $body.publishToInternalServer | Should -Be $true
+ $body.publishToPublicServer | Should -Be $true
+ }
+
+ It 'Should respect PublishToInternal=false' {
+ & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' `
+ -PublishToInternal $false
+
+ $body = $global:restCalls[1].Body | ConvertFrom-Json
+ $body.publishToInternalServer | Should -Be $false
+ $body.publishToPublicServer | Should -Be $true
+ }
+
+ It 'Should respect PublishToPublic=false' {
+ & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' `
+ -PublishToPublic $false
+
+ $body = $global:restCalls[1].Body | ConvertFrom-Json
+ $body.publishToInternalServer | Should -Be $true
+ $body.publishToPublicServer | Should -Be $false
+ }
+}
+
+Describe 'publish-symbols.ps1 Error Handling' {
+
+ It 'Should throw when token acquisition fails' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 1; return '' }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*token*'
+ }
+
+ It 'Should throw when token is empty' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return ' ' }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*empty*'
+ }
+
+ It 'Should throw with URI details when registration fails' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ Mock -CommandName 'Invoke-RestMethod' -MockWith { throw "Connection refused" }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*Failed to register*'
+ }
+
+ It 'Should throw with URI details when publish fails' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -eq 1) { return @{} }
+ throw "Service unavailable"
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*Failed to publish*'
+ }
+
+ It 'Should throw with URI details when status check fails' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ throw "Timeout"
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*Failed to check*'
+ }
+}
+
+Describe 'publish-symbols.ps1 Status Failure Detection' {
+
+ It 'Should throw when internal server result is Failed (2)' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 2; publishToPublicServerResult = 0 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*terminal failure*Internal server*Failed*'
+ }
+
+ It 'Should throw when public server result is Cancelled (3)' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 1; publishToPublicServerResult = 3 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*terminal failure*Public server*Cancelled*'
+ }
+
+ It 'Should throw when both servers report failure' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 2; publishToPublicServerResult = 3 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Throw '*terminal failure*Internal server*Public server*'
+ }
+
+ It 'Should not throw when both servers report Succeeded (1)' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 1; publishToPublicServerResult = 1 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Not -Throw
+ }
+
+ It 'Should not throw when results are Pending (0)' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 0; publishToPublicServerResult = 0 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' } |
+ Should -Not -Throw
+ }
+
+ It 'Should not check internal result when PublishToInternal is false' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 2; publishToPublicServerResult = 1 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' `
+ -PublishToInternal $false } |
+ Should -Not -Throw
+ }
+
+ It 'Should not check public result when PublishToPublic is false' {
+ Mock -CommandName 'az' -MockWith { $global:LASTEXITCODE = 0; return 'fake-token' }
+ $global:mockCallCount = 0
+ Mock -CommandName 'Invoke-RestMethod' -MockWith {
+ $global:mockCallCount++
+ if ($global:mockCallCount -le 2) { return @{} }
+ return @{ publishToInternalServerResult = 1; publishToPublicServerResult = 2 }
+ }
+
+ { & $scriptPath `
+ -PublishServer 'srv' `
+ -PublishTokenUri 'https://token-uri' `
+ -PublishProjectName 'proj' `
+ -ArtifactName 'art' `
+ -PublishToPublic $false } |
+ Should -Not -Throw
+ }
+}
diff --git a/eng/pipelines/onebranch/sqlclient-non-official.yml b/eng/pipelines/onebranch/sqlclient-non-official.yml
index 2274d8cccf..4ae301020f 100644
--- a/eng/pipelines/onebranch/sqlclient-non-official.yml
+++ b/eng/pipelines/onebranch/sqlclient-non-official.yml
@@ -45,7 +45,7 @@ parameters:
default: true
# Build the Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider package.
- - name: buildAKVProvider
+ - name: buildAkvProvider
displayName: Build Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
type: boolean
default: true
@@ -84,41 +84,17 @@ parameters:
default: false
# Release the Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider package.
- - name: releaseAKVProvider
+ - name: releaseAkvProvider
displayName: Release Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
type: boolean
default: false
variables:
+ - template: /eng/pipelines/onebranch/variables/common-variables.yml@self
- template: /eng/pipelines/onebranch/variables/onebranch-variables.yml@self
-
- # Define the effective versions for all of the packages we build and release.
- - ${{ if parameters.isPreview }}:
- - name: effectiveSqlServerVersion
- value: $(sqlServerPackagePreviewVersion)
- - name: effectiveLoggingVersion
- value: $(loggingPackagePreviewVersion)
- - name: effectiveAbstractionsVersion
- value: $(abstractionsPackagePreviewVersion)
- - name: effectiveSqlClientVersion
- value: $(mdsPackagePreviewVersion)
- - name: effectiveAzureVersion
- value: $(azurePackagePreviewVersion)
- - name: effectiveAkvProviderVersion
- value: $(akvPackagePreviewVersion)
- - ${{ else }}:
- - name: effectiveSqlServerVersion
- value: $(sqlServerPackageVersion)
- - name: effectiveLoggingVersion
- value: $(loggingPackageVersion)
- - name: effectiveAbstractionsVersion
- value: $(abstractionsPackageVersion)
- - name: effectiveSqlClientVersion
- value: $(mdsPackageVersion)
- - name: effectiveAzureVersion
- value: $(azurePackageVersion)
- - name: effectiveAkvProviderVersion
- value: $(akvPackageVersion)
+ - template: /eng/pipelines/onebranch/variables/package-variables.yml@self
+ parameters:
+ isPreview: ${{ parameters.isPreview }}
resources:
repositories:
@@ -130,63 +106,130 @@ resources:
extends:
# See: https://aka.ms/obpipelines/templates
template: /v2/OneBranch.NonOfficial.CrossPlat.yml@templates
+
parameters:
- release:
- # This indicates the pipeline category to deploy Box products. See:
- # https://eng.ms/docs/products/onebranch/release/yamlreleasepipelines/deployboxproducts
- category: NonAzure
featureFlags:
EnableCDPxPAT: false
WindowsHostVersion: 1ESWindows2022
+
+ release:
+ # This indicates the pipeline category to deploy Box products. See:
+ # https://eng.ms/docs/products/onebranch/release/yamlreleasepipelines/deployboxproducts
+ category: NonAzure
+
# See: https://aka.ms/obpipelines/sdl
globalSdl:
- tsa:
- # We disable TSA for non-official pipelines. This inhibits spurious TSA alerts and ADO
- # task creation, since non-official builds are often done against development branches.
- enabled: false
apiscan:
+ # APIScan "software name" and version parameters are set on a per-job basis with via
+ # ob_sdl_apiscan_* variables.
enabled: true
break: false
- # Other ApiScan options are set by the jobs via ob_sdl_apiscan_* variables.
+
+ armory:
+ enabled: true
+
+ asyncSdl:
+ # Disabling this as it complicates the build process with minimal gain
+ enabled: false
+
+ binskim:
+ enabled: true
+
codeql:
- compiled:
enabled: true
- sbom:
+ compiled:
+
+ credscan:
enabled: true
- packageName: Microsoft.Data.SqlClient
- packageVersion: $(mdsPackageVersion)
+ suppressionsFile: '$(REPO_ROOT)/.config/CredScanSuppressions.json'
+
+ eslint:
+ # Only useful for repos with ECMAscript - which we do not have.
+ enabled: false
+
policheck:
enabled: true
- break: true
- exclusionsFile: $(REPO_ROOT)\.config\PolicheckExclusions.xml
- asyncSdl:
+ exclusionsFile: '$(REPO_ROOT)\.config\PolicheckExclusions.xml'
+
+ roslyn:
+ # Note, requires RoslynAnalyzers task to be added as a separate step
+ enabled: true
+
+ publishLogs:
+ enabled: true
+
+ sbom:
+ enabled: true
+ packageName: 'Microsoft.Data.SqlClient'
+ packageVersion: '$(Build.BuildNumber)'
+
+ tsa:
+ # We disable TSA for non-official pipelines. This inhibits spurious TSA alerts and ADO task
+ # creation, since non-official builds are often done against development branches. This also
+ # forces all SDL tasks into "break" build mode.
enabled: false
- credscan:
- enabled: true
- suppressionsFile: $(REPO_ROOT)/.config/CredScanSuppressions.json
- binskim:
- enabled: true
- armory:
- enabled: true
- break: true
- eslint:
- enabled: false
- roslyn:
- enabled: true
- break: true
- publishLogs:
- enabled: true
- tsaOptionsPath: $(REPO_ROOT)\.config\tsaoptions.json
- disableLegacyManifest: true
+ configFile: '$(REPO_ROOT)/.config/tsaoptions.json'
+
stages:
- template: /eng/pipelines/onebranch/stages/build-stages.yml@self
parameters:
- debug: ${{ parameters.debug }}
- isPreview: ${{ parameters.isPreview }}
+ isOfficial: false # This is a non-official pipeline.
+ buildSqlServerServer: ${{ parameters.buildSqlServerServer }}
+ buildSqlClient: ${{ parameters.buildSqlClient }}
+ buildAkvProvider: ${{ parameters.buildAkvProvider }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsFileVersion: '${{ variables.abstractionsFileVersion }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderFileVersion: '${{ variables.akvProviderFileVersion }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azureFileVersion: '${{ variables.azureFileVersion }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingFileVersion: '${{ variables.loggingFileVersion }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientFileVersion: '${{ variables.sqlClientFileVersion }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerFileVersion: '${{ variables.sqlServerFileVersion }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
+ signingAppRegistrationClientId: '$(SigningAppRegistrationClientId)'
+ signingAppRegistrationTenantId: '$(SigningAppRegistrationTenantId)'
+ signingAuthAkvName: '$(SigningAuthAkvName)'
+ signingAuthSignCertName: '$(SigningAuthSignCertName)'
+ signingEsrpClientId: '$(SigningEsrpClientId)'
+ signingEsrpConnectedServiceName: '$(SigningEsrpConnectedServiceName)'
+
+ - template: /eng/pipelines/onebranch/stages/publish-symbols-stage.yml@self
+ parameters:
publishSymbols: ${{ parameters.publishSymbols }}
buildSqlServerServer: ${{ parameters.buildSqlServerServer }}
buildSqlClient: ${{ parameters.buildSqlClient }}
- buildAKVProvider: ${{ parameters.buildAKVProvider }}
+ buildAkvProvider: ${{ parameters.buildAkvProvider }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
+ symbolsAzureSubscription: '$(SymbolsAzureSubscription)'
+ symbolsPublishProjectName: '$(SymbolsPublishProjectNameSqlClient)'
+ # Non-Official pipelines must publish to the PPE symbol server.
+ symbolsPublishServer: '$(SymbolsPublishServerPPE)'
+ symbolsPublishTokenUri: '$(SymbolsPublishTokenUriPPE)'
+ symbolsUploadAccount: '$(SymbolsUploadAccount)'
- template: /eng/pipelines/onebranch/stages/release-stages.yml@self
parameters:
@@ -196,9 +239,25 @@ extends:
# This is _not_ an official pipeline.
isOfficial: false
stageNameSuffix: test
+
+ publishSymbols: ${{ parameters.publishSymbols }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
releaseSqlServerServer: ${{ parameters.releaseSqlServerServer }}
releaseLogging: ${{ parameters.releaseLogging }}
releaseAbstractions: ${{ parameters.releaseAbstractions }}
releaseSqlClient: ${{ parameters.releaseSqlClient }}
releaseAzure: ${{ parameters.releaseAzure }}
- releaseAKVProvider: ${{ parameters.releaseAKVProvider }}
+ releaseAkvProvider: ${{ parameters.releaseAkvProvider }}
diff --git a/eng/pipelines/onebranch/sqlclient-official.yml b/eng/pipelines/onebranch/sqlclient-official.yml
index c9548b25d6..a2902f1e21 100644
--- a/eng/pipelines/onebranch/sqlclient-official.yml
+++ b/eng/pipelines/onebranch/sqlclient-official.yml
@@ -66,7 +66,7 @@ parameters:
default: true
# Build the Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider package.
- - name: buildAKVProvider
+ - name: buildAkvProvider
displayName: Build Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
type: boolean
default: true
@@ -105,41 +105,17 @@ parameters:
default: false
# Release the Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider package.
- - name: releaseAKVProvider
+ - name: releaseAkvProvider
displayName: Release Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
type: boolean
default: false
variables:
+ - template: /eng/pipelines/onebranch/variables/common-variables.yml@self
- template: /eng/pipelines/onebranch/variables/onebranch-variables.yml@self
-
- # Define the effective versions for all of the packages we build and release.
- - ${{ if parameters.isPreview }}:
- - name: effectiveSqlServerVersion
- value: $(sqlServerPackagePreviewVersion)
- - name: effectiveLoggingVersion
- value: $(loggingPackagePreviewVersion)
- - name: effectiveAbstractionsVersion
- value: $(abstractionsPackagePreviewVersion)
- - name: effectiveSqlClientVersion
- value: $(mdsPackagePreviewVersion)
- - name: effectiveAzureVersion
- value: $(azurePackagePreviewVersion)
- - name: effectiveAkvProviderVersion
- value: $(akvPackagePreviewVersion)
- - ${{ else }}:
- - name: effectiveSqlServerVersion
- value: $(sqlServerPackageVersion)
- - name: effectiveLoggingVersion
- value: $(loggingPackageVersion)
- - name: effectiveAbstractionsVersion
- value: $(abstractionsPackageVersion)
- - name: effectiveSqlClientVersion
- value: $(mdsPackageVersion)
- - name: effectiveAzureVersion
- value: $(azurePackageVersion)
- - name: effectiveAkvProviderVersion
- value: $(akvPackageVersion)
+ - template: /eng/pipelines/onebranch/variables/package-variables.yml@self
+ parameters:
+ isPreview: ${{ parameters.isPreview }}
resources:
repositories:
@@ -150,68 +126,138 @@ resources:
extends:
# See: https://aka.ms/obpipelines/templates
- template: /v2/OneBranch.Official.CrossPlat.yml@templates
+ template: '/v2/OneBranch.Official.CrossPlat.yml@templates'
+
parameters:
- release:
- # This indicates the pipeline category to deploy Box products. See:
- # https://eng.ms/docs/products/onebranch/release/yamlreleasepipelines/deployboxproducts
- category: NonAzure
featureFlags:
EnableCDPxPAT: false
WindowsHostVersion: 1ESWindows2022
+
+ release:
+ # This indicates the pipeline category to deploy Box products. See:
+ # https://eng.ms/docs/products/onebranch/release/yamlreleasepipelines/deployboxproducts
+ category: NonAzure
+
# See: https://aka.ms/obpipelines/sdl
globalSdl:
- tsa:
- # The OneBranch template will set 'break' to false for the other SDL tools when TSA is
- # enabled. This allows TSA to gather the results and publish them for downstream analysis.
- enabled: true
apiscan:
+ # APIScan "software name" and version parameters are set on a per-job basis with via
+ # ob_sdl_apiscan_* variables.
enabled: true
# TODO(https://sqlclientdrivers.visualstudio.com/ADO.Net/_workitems/edit/42858):
# We have temporarily disabled breaking the build on ApiScan results until we can:
# - Register our new packages with API Scan, and/or
# - Publish MSDN/Learn/etc documentation for the new packages.
break: false
- # Other ApiScan options are set by the jobs via ob_sdl_apiscan_* variables.
+
+ armory:
+ enabled: true
+ break: true
+
+ asyncSdl:
+ # Disabling this as it complicates the build process with minimal gain
+ enabled: false
+
+ binskim:
+ enabled: true
+ break: true
+
codeql:
- compiled:
enabled: true
- sbom:
+ compiled:
+
+ credscan:
enabled: true
- packageName: Microsoft.Data.SqlClient
- packageVersion: $(mdsPackageVersion)
+ suppressionsFile: '$(REPO_ROOT)/.config/CredScanSuppressions.json'
+
+ eslint:
+ # Only useful for repos with ECMAscript - which we do not have.
+ enabled: false
+
policheck:
enabled: true
break: true
- exclusionsFile: $(REPO_ROOT)\.config\PolicheckExclusions.xml
- asyncSdl:
- enabled: false
- credscan:
- enabled: true
- suppressionsFile: $(REPO_ROOT)/.config/CredScanSuppressions.json
- binskim:
- enabled: true
- armory:
- enabled: true
- break: true
- eslint:
- enabled: false
- roslyn:
- enabled: true
- break: true
- publishLogs:
- enabled: true
- tsaOptionsPath: $(REPO_ROOT)\.config\tsaoptions.json
- disableLegacyManifest: true
+ exclusionsFile: '$(REPO_ROOT)\.config\PolicheckExclusions.xml'
+
+ roslyn:
+ # Note, requires RoslynAnalyzers task to be added as a separate step
+ enabled: true
+ break: true
+
+ publishLogs:
+ enabled: true
+
+ sbom:
+ enabled: true
+ packageName: 'Microsoft.Data.SqlClient'
+ packageVersion: '$(Build.BuildNumber)'
+
+ tsa:
+ # OneBranch publishes all sdl results to TSA. If TSA is disabled, all SDL tools will be
+ # forced into 'break' build mode.
+ enabled: true
+ configFile: '$(REPO_ROOT)/.config/tsaoptions.json'
+
stages:
- template: /eng/pipelines/onebranch/stages/build-stages.yml@self
parameters:
- debug: ${{ parameters.debug }}
- isPreview: ${{ parameters.isPreview }}
+ isOfficial: true # This is an official pipeline.
+ buildSqlServerServer: ${{ parameters.buildSqlServerServer }}
+ buildSqlClient: ${{ parameters.buildSqlClient }}
+ buildAkvProvider: ${{ parameters.buildAkvProvider }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsFileVersion: '${{ variables.abstractionsFileVersion }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderFileVersion: '${{ variables.akvProviderFileVersion }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azureFileVersion: '${{ variables.azureFileVersion }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingFileVersion: '${{ variables.loggingFileVersion }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientFileVersion: '${{ variables.sqlClientFileVersion }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerFileVersion: '${{ variables.sqlServerFileVersion }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
+ signingAppRegistrationClientId: '$(SigningAppRegistrationClientId)'
+ signingAppRegistrationTenantId: '$(SigningAppRegistrationTenantId)'
+ signingAuthAkvName: '$(SigningAuthAkvName)'
+ signingAuthSignCertName: '$(SigningAuthSignCertName)'
+ signingEsrpClientId: '$(SigningEsrpClientId)'
+ signingEsrpConnectedServiceName: '$(SigningEsrpConnectedServiceName)'
+
+ - template: /eng/pipelines/onebranch/stages/publish-symbols-stage.yml@self
+ parameters:
publishSymbols: ${{ parameters.publishSymbols }}
buildSqlServerServer: ${{ parameters.buildSqlServerServer }}
buildSqlClient: ${{ parameters.buildSqlClient }}
- buildAKVProvider: ${{ parameters.buildAKVProvider }}
+ buildAkvProvider: ${{ parameters.buildAkvProvider }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
+ symbolsAzureSubscription: '$(SymbolsAzureSubscription)'
+ symbolsPublishProjectName: '$(SymbolsPublishProjectNameSqlClient)'
+ # Official pipelines must publish to the Production symbol server.
+ symbolsPublishServer: '$(SymbolsPublishServerProd)'
+ symbolsPublishTokenUri: '$(SymbolsPublishTokenUriProd)'
+ symbolsUploadAccount: '$(SymbolsUploadAccount)'
- template: /eng/pipelines/onebranch/stages/release-stages.yml@self
parameters:
@@ -220,9 +266,25 @@ extends:
# This is an official pipeline.
isOfficial: true
stageNameSuffix: production
+
+ publishSymbols: ${{ parameters.publishSymbols }}
+
+ abstractionsArtifactsName: '${{ variables.abstractionsArtifactsName }}'
+ abstractionsPackageVersion: '${{ variables.abstractionsPackageVersion }}'
+ akvProviderArtifactsName: '${{ variables.akvProviderArtifactsName }}'
+ akvProviderPackageVersion: '${{ variables.akvProviderPackageVersion }}'
+ azureArtifactsName: '${{ variables.azureArtifactsName }}'
+ azurePackageVersion: '${{ variables.azurePackageVersion }}'
+ loggingArtifactsName: '${{ variables.loggingArtifactsName }}'
+ loggingPackageVersion: '${{ variables.loggingPackageVersion }}'
+ sqlClientArtifactsName: '${{ variables.sqlClientArtifactsName }}'
+ sqlClientPackageVersion: '${{ variables.sqlClientPackageVersion }}'
+ sqlServerArtifactsName: '${{ variables.sqlServerArtifactsName }}'
+ sqlServerPackageVersion: '${{ variables.sqlServerPackageVersion }}'
+
releaseSqlServerServer: ${{ parameters.releaseSqlServerServer }}
releaseLogging: ${{ parameters.releaseLogging }}
releaseAbstractions: ${{ parameters.releaseAbstractions }}
releaseSqlClient: ${{ parameters.releaseSqlClient }}
releaseAzure: ${{ parameters.releaseAzure }}
- releaseAKVProvider: ${{ parameters.releaseAKVProvider }}
+ releaseAkvProvider: ${{ parameters.releaseAkvProvider }}
diff --git a/eng/pipelines/onebranch/stages/build-stages.yml b/eng/pipelines/onebranch/stages/build-stages.yml
index 0b6962f1af..252f63fb0a 100644
--- a/eng/pipelines/onebranch/stages/build-stages.yml
+++ b/eng/pipelines/onebranch/stages/build-stages.yml
@@ -12,31 +12,14 @@
# - build_independent: builds packages with no cross-package dependencies (Logging, SqlServer)
# - build_abstractions: builds the Abstractions package, which depends on Logging
# - build_dependent: builds packages with dependencies on Abstractions (SqlClient, Azure)
-# - build_addons: builds add-on packages with dependencies on the core packages (AKV Provider)
-#
-# This template depends on the following runtime (i.e. macro expansion) variables being defined:
-#
-# - effectiveSqlServerVersion
-# - effectiveLoggingVersion
-# - effectiveAbstractionsVersion
-# - effectiveSqlClientVersion
-# - effectiveAzureVersion
-# - effectiveAkvProviderVersion
+# - build_addons: builds add-on packages with dependencies on the core packages (Akv Provider)
parameters:
# ── General parameters ─────────────────────────────────────────────────
- # True to enable debug information and steps.
- - name: debug
- type: boolean
-
- # True if this is a preview build, which uses the preview version numbers from
- # common-variables.yml.
- - name: isPreview
- type: boolean
-
- # True to publish symbols to public and private servers.
- - name: publishSymbols
+ # True if this is an official build, which runs additional ESRP malware scanning
+ # and codesigning steps.
+ - name: isOfficial
type: boolean
# ── Build parameters ───────────────────────────────────────────────────
@@ -47,9 +30,85 @@ parameters:
- name: buildSqlClient
type: boolean
- - name: buildAKVProvider
+ - name: buildAkvProvider
type: boolean
+ # Package Parameters -----------------------------------------------------
+
+ - name: abstractionsArtifactsName
+ type: string
+
+ - name: abstractionsFileVersion
+ type: string
+
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: akvProviderArtifactsName
+ type: string
+
+ - name: akvProviderFileVersion
+ type: string
+
+ - name: akvProviderPackageVersion
+ type: string
+
+ - name: azureArtifactsName
+ type: string
+
+ - name: azureFileVersion
+ type: string
+
+ - name: azurePackageVersion
+ type: string
+
+ - name: loggingArtifactsName
+ type: string
+
+ - name: loggingFileVersion
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientArtifactsName
+ type: string
+
+ - name: sqlClientFileVersion
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+ - name: sqlServerArtifactsName
+ type: string
+
+ - name: sqlServerFileVersion
+ type: string
+
+ - name: sqlServerPackageVersion
+ type: string
+
+ # Signing Parameters -----------------------------------------------------
+
+ - name: signingAppRegistrationClientId
+ type: string
+
+ - name: signingAppRegistrationTenantId
+ type: string
+
+ - name: signingAuthAkvName
+ type: string
+
+ - name: signingAuthSignCertName
+ type: string
+
+ - name: signingEsrpClientId
+ type: string
+
+ - name: signingEsrpConnectedServiceName
+ type: string
+
stages:
# ====================================================================
# Stage 1: Independent packages (no cross-package dependencies)
@@ -59,41 +118,42 @@ stages:
displayName: "Build Independent Packages"
jobs:
- - ${{ if or(eq(parameters.buildAKVProvider, true), eq(parameters.buildSqlClient, true)) }}:
+ - ${{ if or(eq(parameters.buildAkvProvider, true), eq(parameters.buildSqlClient, true)) }}:
- template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
parameters:
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+
+ isOfficial: ${{ parameters.isOfficial }}
packageName: Logging
packageFullName: Microsoft.Data.SqlClient.Internal.Logging
- packageVersion: $(effectiveLoggingVersion)
versionProperties: >-
- -p:LoggingPackageVersion=$(effectiveLoggingVersion)
- -p:LoggingAssemblyFileVersion=$(loggingAssemblyFileVersion)
- assemblyFileVersion: $(loggingAssemblyFileVersion)
- publishSymbols: ${{ parameters.publishSymbols }}
- esrpConnectedServiceName: $(ESRPConnectedServiceName)
- esrpClientId: $(ESRPClientId)
- appRegistrationClientId: $(AppRegistrationClientId)
- appRegistrationTenantId: $(AppRegistrationTenantId)
- authAkvName: $(AuthAKVName)
- authSignCertName: $(AuthSignCertName)
+ -p:LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
+ -p:LoggingAssemblyFileVersion=${{ parameters.loggingFileVersion }}
+ assemblyFileVersion: '${{ parameters.loggingFileVersion }}'
+
- ${{ if eq(parameters.buildSqlServerServer, true) }}:
- template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
parameters:
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+
+ isOfficial: ${{ parameters.isOfficial }}
packageName: SqlServer
packageFullName: Microsoft.SqlServer.Server
- packageVersion: $(effectiveSqlServerVersion)
versionProperties: >-
- -p:SqlServerAssemblyFileVersion=$(sqlServerAssemblyFileVersion)
- -p:SqlServerPackageVersion=$(effectiveSqlServerVersion)
- assemblyFileVersion: $(sqlServerAssemblyFileVersion)
- publishSymbols: ${{ parameters.publishSymbols }}
- esrpConnectedServiceName: $(ESRPConnectedServiceName)
- esrpClientId: $(ESRPClientId)
- appRegistrationClientId: $(AppRegistrationClientId)
- appRegistrationTenantId: $(AppRegistrationTenantId)
- authAkvName: $(AuthAKVName)
- authSignCertName: $(AuthSignCertName)
+ -p:SqlServerAssemblyFileVersion=${{ parameters.sqlServerFileVersion }}
+ -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }}
+ assemblyFileVersion: '${{ parameters.sqlServerFileVersion }}'
# ====================================================================
# Stage 2: Abstractions package (depends on Logging from Stage 1)
@@ -101,120 +161,132 @@ stages:
# dependency on Internal.Logging.
# ====================================================================
- ${{ if eq(parameters.buildSqlClient, true) }}:
- - stage: build_abstractions
- displayName: "Build Abstractions Package"
- dependsOn: build_independent
+ - stage: build_abstractions
+ displayName: "Build Abstractions Package"
+ dependsOn: build_independent
- jobs:
- - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
- parameters:
- packageName: Abstractions
- packageFullName: Microsoft.Data.SqlClient.Extensions.Abstractions
- packageVersion: $(effectiveAbstractionsVersion)
- versionProperties: >-
- -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion)
- -p:AbstractionsAssemblyFileVersion=$(abstractionsAssemblyFileVersion)
- -p:LoggingPackageVersion=$(effectiveLoggingVersion)
- assemblyFileVersion: $(abstractionsAssemblyFileVersion)
- publishSymbols: ${{ parameters.publishSymbols }}
- esrpConnectedServiceName: $(ESRPConnectedServiceName)
- esrpClientId: $(ESRPClientId)
- appRegistrationClientId: $(AppRegistrationClientId)
- appRegistrationTenantId: $(AppRegistrationTenantId)
- authAkvName: $(AuthAKVName)
- authSignCertName: $(AuthSignCertName)
- downloadArtifacts:
- - artifactName: $(loggingArtifactsName)
- displayName: Logging Package
+ jobs:
+ - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
+ parameters:
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+
+ isOfficial: ${{ parameters.isOfficial }}
+ packageName: Abstractions
+ packageFullName: Microsoft.Data.SqlClient.Extensions.Abstractions
+ versionProperties: >-
+ -p:AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }}
+ -p:AbstractionsAssemblyFileVersion=${{ parameters.abstractionsFileVersion }}
+ -p:LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
+ assemblyFileVersion: '${{ parameters.abstractionsFileVersion }}'
+ downloadArtifacts:
+ - artifactName: '${{ parameters.loggingArtifactsName }}'
+ displayName: 'Logging Package'
# ====================================================================
# Stage 3: Core packages (depend on Abstractions)
- # MDS and Extensions.Azure build in parallel after Abstractions.
+ # SqlClient 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_abstractions
+ - stage: build_dependent
+ displayName: "Build Core Packages"
+ dependsOn: build_abstractions
- jobs:
- - template: /eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml@self
- parameters:
- publishSymbols: ${{ parameters.publishSymbols }}
- isPreview: ${{ parameters.isPreview }}
- # TODO: This job should use the effective versions for Abstractions, Logging,
- # SqlServer, and SqlClient.
+ jobs:
+ - template: /eng/pipelines/onebranch/jobs/build-signed-sqlclient-package-job.yml@self
+ parameters:
+ isOfficial: ${{ parameters.isOfficial }}
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
- - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
- parameters:
- packageName: Azure
- packageFullName: Microsoft.Data.SqlClient.Extensions.Azure
- packageVersion: $(effectiveAzureVersion)
- versionProperties: >-
- -p:AzurePackageVersion=$(effectiveAzureVersion)
- -p:AzureAssemblyFileVersion=$(azureAssemblyFileVersion)
- -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion)
- -p:LoggingPackageVersion=$(effectiveLoggingVersion)
- assemblyFileVersion: $(azureAssemblyFileVersion)
- publishSymbols: ${{ parameters.publishSymbols }}
- esrpConnectedServiceName: $(ESRPConnectedServiceName)
- esrpClientId: $(ESRPClientId)
- appRegistrationClientId: $(AppRegistrationClientId)
- appRegistrationTenantId: $(AppRegistrationTenantId)
- authAkvName: $(AuthAKVName)
- authSignCertName: $(AuthSignCertName)
- downloadArtifacts:
- - artifactName: $(abstractionsArtifactsName)
- displayName: Abstractions Package
- - artifactName: $(loggingArtifactsName)
- displayName: Logging Package
+ abstractionsArtifactName: '${{ parameters.abstractionsArtifactsName }}'
+ abstractionsPackageVersion: '${{ parameters.abstractionsPackageVersion }}'
+ loggingArtifactName: '${{ parameters.loggingArtifactsName }}'
+ loggingPackageVersion: '${{ parameters.loggingPackageVersion }}'
+ sqlClientAssemblyFileVersion: '${{ parameters.sqlClientFileVersion }}'
+ sqlClientPackageVersion: '${{ parameters.sqlClientPackageVersion }}'
+
+ - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
+ parameters:
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+
+ isOfficial: ${{ parameters.isOfficial }}
+ packageName: Azure
+ packageFullName: Microsoft.Data.SqlClient.Extensions.Azure
+ versionProperties: >-
+ -p:AzurePackageVersion=${{ parameters.azurePackageVersion }}
+ -p:AzureAssemblyFileVersion=${{ parameters.azureFileVersion }}
+ -p:AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }}
+ -p:LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
+ assemblyFileVersion: '${{ parameters.azureFileVersion }}'
+ downloadArtifacts:
+ - artifactName: '${{ parameters.abstractionsArtifactsName }}'
+ displayName: Abstractions Package
+ - artifactName: '${{ parameters.loggingArtifactsName }}'
+ displayName: Logging Package
# ====================================================================
# Stage 4: Add-on packages (depend on core packages)
- # AKV Provider builds after MDS completes.
+ # Akv Provider builds after SqlClient completes.
# ====================================================================
- - ${{ if and(eq(parameters.buildAKVProvider, true), eq(parameters.buildSqlClient, true)) }}:
- - stage: build_addons
- displayName: "Build Add-on Packages"
- dependsOn: build_dependent
+ - ${{ if and(eq(parameters.buildAkvProvider, true), eq(parameters.buildSqlClient, true)) }}:
+ - stage: build_addons
+ displayName: "Build Add-on Packages"
+ dependsOn: build_dependent
- jobs:
- - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
- parameters:
- packageName: AkvProvider
- packageFullName: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
- packageVersion: $(effectiveAkvProviderVersion)
- versionProperties: >-
- -p:AkvPackageVersion=$(effectiveAkvProviderVersion)
- -p:AkvAssemblyFileVersion=$(akvAssemblyFileVersion)
- -p:MdsPackageVersion=$(effectiveSqlClientVersion)
- -p:LoggingPackageVersion=$(effectiveLoggingVersion)
- -p:AbstractionsPackageVersion=$(effectiveAbstractionsVersion)
- assemblyFileVersion: $(akvAssemblyFileVersion)
- publishSymbols: ${{ parameters.publishSymbols }}
- esrpConnectedServiceName: $(ESRPConnectedServiceName)
- esrpClientId: $(ESRPClientId)
- appRegistrationClientId: $(AppRegistrationClientId)
- appRegistrationTenantId: $(AppRegistrationTenantId)
- authAkvName: $(AuthAKVName)
- authSignCertName: $(AuthSignCertName)
- downloadArtifacts:
- - artifactName: $(sqlClientArtifactsName)
- displayName: SqlClient Package
- - artifactName: $(abstractionsArtifactsName)
- displayName: Abstractions Package
- - artifactName: $(loggingArtifactsName)
- displayName: Logging Package
+ jobs:
+ - template: /eng/pipelines/onebranch/jobs/build-signed-csproj-package-job.yml@self
+ parameters:
+ signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
+ signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
+ signingAuthAkvName: '${{ parameters.signingAuthAkvName }}'
+ signingAuthSignCertName: '${{ parameters.signingAuthSignCertName }}'
+ signingEsrpClientId: '${{ parameters.signingEsrpClientId }}'
+ signingEsrpConnectedServiceName: '${{ parameters.signingEsrpConnectedServiceName }}'
+
+ isOfficial: ${{ parameters.isOfficial }}
+ packageName: AkvProvider
+ packageFullName: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
+ versionProperties: >-
+ -p:AkvPackageVersion=${{ parameters.akvProviderPackageVersion }}
+ -p:AkvAssemblyFileVersion=${{ parameters.akvProviderFileVersion }}
+ -p:MdsPackageVersion=${{ parameters.sqlClientPackageVersion }}
+ -p:LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
+ -p:AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }}
+ assemblyFileVersion: '${{ parameters.akvProviderFileVersion }}'
+ downloadArtifacts:
+ - artifactName: '${{ parameters.sqlClientArtifactsName }}'
+ displayName: SqlClient Package
+ - artifactName: '${{ parameters.abstractionsArtifactsName }}'
+ displayName: Abstractions Package
+ - artifactName: '${{ parameters.loggingArtifactsName }}'
+ displayName: Logging Package
# ====================================================================
# Validation
# ====================================================================
- ${{ if eq(parameters.buildSqlClient, true) }}:
- - stage: mds_package_validation
- displayName: "MDS Package Validation"
- dependsOn: build_dependent
- jobs:
- - template: /eng/pipelines/onebranch/jobs/validate-signed-package-job.yml@self
- parameters:
- artifactName: $(sqlClientArtifactsName)
- isPreview: ${{ parameters.isPreview }}
+ - stage: sqlclient_package_validation
+ displayName: "SqlClient Package Validation"
+ dependsOn: build_dependent
+ jobs:
+ - template: /eng/pipelines/onebranch/jobs/validate-signed-package-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.sqlClientArtifactsName }}'
+ expectedFileVersion: '${{ parameters.sqlClientFileVersion }}'
+ expectedPackageVersion: '${{ parameters.sqlClientPackageVersion }}'
+ isOfficial: ${{ parameters.isOfficial }}
diff --git a/eng/pipelines/onebranch/stages/publish-symbols-stage.yml b/eng/pipelines/onebranch/stages/publish-symbols-stage.yml
new file mode 100644
index 0000000000..e716d2255d
--- /dev/null
+++ b/eng/pipelines/onebranch/stages/publish-symbols-stage.yml
@@ -0,0 +1,222 @@
+#################################################################################
+# 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. #
+#################################################################################
+
+# Unified symbols publishing stage template for sqlclient OneBranch pipelines.
+# Consumed by both the official and non-official pipeline definitions.
+#
+# This stage publishes PDB symbol files to the internal and public symbol servers.
+# Each package's PDBs are published in a separate job to maintain unique naming and
+# versioning information per package.
+#
+# PDBs are expected to be located under the 'symbols/' directory at the root of
+# each build artifact, with target framework subdirectories preserved by the build
+# job's CopyFiles step. The publish-symbols job consumes that 'symbols' folder directly.
+#
+# Note that none of the resource DLLs we build produce PDBs, so there are no patterns below that
+# match them.
+#
+# The stage is excluded at compile time when publishSymbols is false.
+
+parameters:
+ # ── General parameters ─────────────────────────────────────────────────
+
+ # True to publish symbols (controls whether this stage is emitted at all).
+ - name: publishSymbols
+ type: boolean
+
+ # ── Build parameters (used to conditionally include per-package jobs) ───
+
+ - name: buildSqlServerServer
+ type: boolean
+
+ - name: buildSqlClient
+ type: boolean
+
+ - name: buildAkvProvider
+ type: boolean
+
+ # ── Package Parameters ─────────────────────────────────────────────────
+
+ - name: abstractionsArtifactsName
+ type: string
+
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: akvProviderArtifactsName
+ type: string
+
+ - name: akvProviderPackageVersion
+ type: string
+
+ - name: azureArtifactsName
+ type: string
+
+ - name: azurePackageVersion
+ type: string
+
+ - name: loggingArtifactsName
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientArtifactsName
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+ - name: sqlServerArtifactsName
+ type: string
+
+ - name: sqlServerPackageVersion
+ type: string
+
+ # ── Symbols Publishing Parameters ──────────────────────────────────────
+
+ - name: symbolsAzureSubscription
+ type: string
+
+ - name: symbolsPublishProjectName
+ type: string
+
+ - name: symbolsPublishServer
+ type: string
+
+ - name: symbolsPublishTokenUri
+ type: string
+
+ - name: symbolsUploadAccount
+ type: string
+
+stages:
+ # Stage is emitted whenever publishSymbols is true. If no packages were
+ # built, only the no-op placeholder job runs and the stage succeeds
+ # immediately — keeping the dependency graph simple for downstream stages.
+ - ${{ if eq(parameters.publishSymbols, true) }}:
+ - stage: publish_symbols
+ displayName: "Publish Symbols"
+
+ # Depend on whichever build stages produced artifacts we need to publish.
+ dependsOn:
+ - ${{ if or(parameters.buildSqlServerServer, parameters.buildSqlClient, parameters.buildAkvProvider) }}:
+ - build_independent
+ - ${{ if parameters.buildSqlClient }}:
+ - build_abstractions
+ - build_dependent
+ - ${{ if and(parameters.buildAkvProvider, parameters.buildSqlClient) }}:
+ - build_addons
+
+ jobs:
+ # ── No-op placeholder ──────────────────────────────────────────
+ # When no packages were built, this job keeps the stage valid
+ # (ADO requires at least one job per stage) and succeeds instantly.
+ - ${{ if not(or(parameters.buildSqlServerServer, parameters.buildSqlClient, parameters.buildAkvProvider)) }}:
+ - job: publish_symbols_noop
+ displayName: "No symbols to publish"
+ pool:
+ type: linux
+ steps:
+ - script: echo "No packages were built — nothing to publish."
+ displayName: Skip
+
+ # ── Logging ────────────────────────────────────────────────────
+ - ${{ if or(parameters.buildAkvProvider, parameters.buildSqlClient) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.loggingArtifactsName }}'
+ packageName: Logging
+ packageFullName: Microsoft.Data.SqlClient.Internal.Logging
+ packageVersion: '${{ parameters.loggingPackageVersion }}'
+ # Matches: Microsoft.Data.SqlClient.Internal.Logging.pdb across all TFM subdirs.
+ searchPattern: '**/Microsoft.Data.SqlClient.Internal.Logging.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
+
+ # ── SqlServer.Server ───────────────────────────────────────────
+ - ${{ if eq(parameters.buildSqlServerServer, true) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.sqlServerArtifactsName }}'
+ packageName: SqlServer
+ packageFullName: Microsoft.SqlServer.Server
+ packageVersion: '${{ parameters.sqlServerPackageVersion }}'
+ # Matches: Microsoft.SqlServer.Server.pdb across all TFM subdirs.
+ searchPattern: '**/Microsoft.SqlServer.Server.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
+
+ # ── Abstractions ───────────────────────────────────────────────
+ - ${{ if eq(parameters.buildSqlClient, true) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.abstractionsArtifactsName }}'
+ packageName: Abstractions
+ packageFullName: Microsoft.Data.SqlClient.Extensions.Abstractions
+ packageVersion: '${{ parameters.abstractionsPackageVersion }}'
+ # Matches: Microsoft.Data.SqlClient.Extensions.Abstractions.pdb across all TFM subdirs.
+ searchPattern: '**/Microsoft.Data.SqlClient.Extensions.Abstractions.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
+
+ # ── SqlClient ──────────────────────────────────────────────────
+ - ${{ if eq(parameters.buildSqlClient, true) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.sqlClientArtifactsName }}'
+ packageName: SqlClient
+ packageFullName: Microsoft.Data.SqlClient
+ packageVersion: '${{ parameters.sqlClientPackageVersion }}'
+ # Matches: Microsoft.Data.SqlClient.pdb across all OS/TFM subdirs.
+ # Excludes: Microsoft.Data.SqlClient.SNI*.pdb (native SNI — symbols published separately).
+ searchPattern: '**/Microsoft.Data.SqlClient.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
+
+ # ── Azure ──────────────────────────────────────────────────────
+ - ${{ if eq(parameters.buildSqlClient, true) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.azureArtifactsName }}'
+ packageName: Azure
+ packageFullName: Microsoft.Data.SqlClient.Extensions.Azure
+ packageVersion: '${{ parameters.azurePackageVersion }}'
+ # Matches: Microsoft.Data.SqlClient.Extensions.Azure.pdb across all TFM subdirs.
+ searchPattern: '**/Microsoft.Data.SqlClient.Extensions.Azure.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
+
+ # ── AKV Provider ───────────────────────────────────────────────
+ - ${{ if and(eq(parameters.buildAkvProvider, true), eq(parameters.buildSqlClient, true)) }}:
+ - template: /eng/pipelines/onebranch/jobs/publish-symbols-job.yml@self
+ parameters:
+ artifactName: '${{ parameters.akvProviderArtifactsName }}'
+ packageName: AkvProvider
+ packageFullName: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
+ packageVersion: '${{ parameters.akvProviderPackageVersion }}'
+ # Matches: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.pdb across all TFM subdirs.
+ searchPattern: '**/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.pdb'
+ symbolsAzureSubscription: '${{ parameters.symbolsAzureSubscription }}'
+ symbolsPublishProjectName: '${{ parameters.symbolsPublishProjectName }}'
+ symbolsPublishServer: '${{ parameters.symbolsPublishServer }}'
+ symbolsPublishTokenUri: '${{ parameters.symbolsPublishTokenUri }}'
+ symbolsUploadAccount: '${{ parameters.symbolsUploadAccount }}'
diff --git a/eng/pipelines/onebranch/stages/release-stages.yml b/eng/pipelines/onebranch/stages/release-stages.yml
index 51eea6e5f0..6ee3fbc88e 100644
--- a/eng/pipelines/onebranch/stages/release-stages.yml
+++ b/eng/pipelines/onebranch/stages/release-stages.yml
@@ -23,15 +23,6 @@
# - false → NuGet Test feed (via NuGetServiceConnectionTest).
#
# This template depends on stages defined by the build-stages.yml template.
-#
-# This template depends on the following runtime (i.e. macro expansion) variables being defined:
-#
-# - effectiveSqlServerVersion
-# - effectiveLoggingVersion
-# - effectiveAbstractionsVersion
-# - effectiveSqlClientVersion
-# - effectiveAzureVersion
-# - effectiveAkvProviderVersion
parameters:
# ── General parameters ─────────────────────────────────────────────────
@@ -60,6 +51,52 @@ parameters:
- production
- test
+ # Package Parameters -----------------------------------------------------
+
+ - name: abstractionsArtifactsName
+ type: string
+
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: akvProviderArtifactsName
+ type: string
+
+ - name: akvProviderPackageVersion
+ type: string
+
+ - name: azureArtifactsName
+ type: string
+
+ - name: azurePackageVersion
+ type: string
+
+ - name: loggingArtifactsName
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientArtifactsName
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+ - name: sqlServerArtifactsName
+ type: string
+
+ - name: sqlServerPackageVersion
+ type: string
+
+ # ── Symbols publishing parameter ───────────────────────────────────────
+ # When true, the release stage will depend on publish_symbols so that
+ # symbol publishing completes before packages are released.
+
+ - name: publishSymbols
+ type: boolean
+ default: false
+
# ── Release parameters ─────────────────────────────────────────────────
- name: releaseSqlServerServer
@@ -77,7 +114,7 @@ parameters:
- name: releaseAzure
type: boolean
- - name: releaseAKVProvider
+ - name: releaseAkvProvider
type: boolean
stages:
@@ -94,7 +131,7 @@ stages:
# true → NuGet Production feed.
# false → NuGet Test feed.
# ====================================================================
- - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging, parameters.releaseAbstractions, parameters.releaseSqlClient, parameters.releaseAzure, parameters.releaseAKVProvider) }}:
+ - ${{ if or(parameters.releaseSqlServerServer, parameters.releaseLogging, parameters.releaseAbstractions, parameters.releaseSqlClient, parameters.releaseAzure, parameters.releaseAkvProvider) }}:
- stage: release_${{ parameters.stageNameSuffix }}
${{ if eq(parameters.releaseToProduction, true) }}:
displayName: Release to NuGet Production
@@ -107,9 +144,11 @@ stages:
- build_abstractions
- ${{ if or(parameters.releaseSqlClient, parameters.releaseAzure) }}:
- build_dependent
- - mds_package_validation
- - ${{ if parameters.releaseAKVProvider }}:
+ - sqlclient_package_validation
+ - ${{ if parameters.releaseAkvProvider }}:
- build_addons
+ - ${{ if parameters.publishSymbols }}:
+ - publish_symbols
variables:
- name: onebranchReleaseEnvironment
@@ -153,8 +192,8 @@ stages:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.SqlServer.Server
- artifactName: drop_build_independent_build_package_SqlServer
- packagePath: Microsoft.SqlServer.Server.$(effectiveSqlServerVersion).nupkg
+ artifactName: '${{ parameters.sqlServerArtifactsName }}'
+ packagePath: 'packages/Microsoft.SqlServer.Server.${{ parameters.sqlServerPackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
@@ -163,8 +202,8 @@ stages:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.Data.SqlClient.Internal.Logging
- artifactName: drop_build_independent_build_package_Logging
- packagePath: Microsoft.Data.SqlClient.Internal.Logging.$(effectiveLoggingVersion).nupkg
+ artifactName: '${{ parameters.loggingArtifactsName }}'
+ packagePath: 'packages/Microsoft.Data.SqlClient.Internal.Logging.${{ parameters.loggingPackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
@@ -173,8 +212,8 @@ stages:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.Data.SqlClient.Extensions.Abstractions
- artifactName: drop_build_abstractions_build_package_Abstractions
- packagePath: Microsoft.Data.SqlClient.Extensions.Abstractions.$(effectiveAbstractionsVersion).nupkg
+ artifactName: '${{ parameters.abstractionsArtifactsName }}'
+ packagePath: 'packages/Microsoft.Data.SqlClient.Extensions.Abstractions.${{ parameters.abstractionsPackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
@@ -183,8 +222,8 @@ stages:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.Data.SqlClient
- artifactName: drop_build_dependent_build_package_SqlClient
- packagePath: Microsoft.Data.SqlClient.$(effectiveSqlClientVersion).nupkg
+ artifactName: '${{ parameters.sqlClientArtifactsName }}'
+ packagePath: 'packages/Microsoft.Data.SqlClient.${{ parameters.sqlClientPackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
@@ -193,18 +232,18 @@ stages:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.Data.SqlClient.Extensions.Azure
- artifactName: drop_build_dependent_build_package_Azure
- packagePath: Microsoft.Data.SqlClient.Extensions.Azure.$(effectiveAzureVersion).nupkg
+ artifactName: '${{ parameters.azureArtifactsName }}'
+ packagePath: 'packages/Microsoft.Data.SqlClient.Extensions.Azure.${{ parameters.azurePackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
- - ${{ if eq(parameters.releaseAKVProvider, true) }}:
+ - ${{ if eq(parameters.releaseAkvProvider, true) }}:
- template: /eng/pipelines/onebranch/jobs/publish-nuget-package-job.yml@self
parameters:
packageName: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider
- artifactName: drop_build_addons_build_package_AkvProvider
- packagePath: Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.$(effectiveAkvProviderVersion).nupkg
+ artifactName: '${{ parameters.akvProviderArtifactsName }}'
+ packagePath: 'packages/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.${{ parameters.akvProviderPackageVersion }}.nupkg'
nugetServiceConnection: ${{ variables.nugetServiceConnection }}
isProduction: ${{ parameters.isOfficial }}
displaySuffix: ${{ variables.nugetTargetSuffix }}
diff --git a/eng/pipelines/onebranch/steps/build-all-configurations-signed-dlls-step.yml b/eng/pipelines/onebranch/steps/build-all-configurations-signed-dlls-step.yml
deleted file mode 100644
index b1429e1fd3..0000000000
--- a/eng/pipelines/onebranch/steps/build-all-configurations-signed-dlls-step.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-#################################################################################
-# Licensed to the .NET Foundation under one or more agreements. #
-# The .NET Foundation licenses this file to you under the MIT license. #
-# See the LICENSE file in the project root for more information. #
-#################################################################################
-parameters:
-
- # The assembly file version to apply to the Abstractions package.
- - name: abstractionsAssemblyFileVersion
- type: string
-
- # The version to apply to the Abstractions package.
- - name: abstractionsPackageVersion
- type: string
-
- # The assembly file version to apply to the Logging package.
- - name: loggingAssemblyFileVersion
- type: string
-
- # The version to apply to the Logging package.
- - name: loggingPackageVersion
- type: string
-
- # The assembly file version to apply to the Mds package.
- - name: mdsAssemblyFileVersion
- type: string
-
- # The version to apply to the Mds package.
- - name: mdsPackageVersion
- type: string
-
-steps:
- # Download our signing key.
- - task: DownloadSecureFile@1
- displayName: 'Download Key Pair'
- inputs:
- secureFile: netfxKeypair.snk
- name: keyFile
-
- # Install the .NET SDK.
- - template: /eng/pipelines/steps/install-dotnet.yml@self
-
- - task: MSBuild@1
- displayName: 'BuildAllConfigurations using build.proj'
- inputs:
- solution: '**/build.proj'
- configuration: Release
- msbuildArguments: >-
- -t:BuildAllConfigurations
- -p:ReferenceType=Package
- -p:GenerateNuget=false
- -p:SigningKeyPath=$(keyFile.secureFilePath)
- -p:AssemblyFileVersion=${{ parameters.mdsAssemblyFileVersion }}
- -p:MdsPackageVersion=${{ parameters.mdsPackageVersion }}
- -p:AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }}
- -p:AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }}
- -p:LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
- -p:LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }}
diff --git a/eng/pipelines/onebranch/steps/compound-build-csproj-step.yml b/eng/pipelines/onebranch/steps/build-csproj-step.yml
similarity index 69%
rename from eng/pipelines/onebranch/steps/compound-build-csproj-step.yml
rename to eng/pipelines/onebranch/steps/build-csproj-step.yml
index 1f1fee00c4..a4a38b9fc3 100644
--- a/eng/pipelines/onebranch/steps/compound-build-csproj-step.yml
+++ b/eng/pipelines/onebranch/steps/build-csproj-step.yml
@@ -7,7 +7,7 @@
# Generic build step for csproj-based packages. Each project uses a build.proj target that runs
# Build only and produces assemblies within $(BUILD_OUTPUT). Downstream ESRP DLL signing must
# locate the assemblies within $(BUILD_OUTPUT) for all target frameworks that the csproj targets.
-# NuGet packaging is done separately via compound-pack-csproj-step.yml after DLL signing.
+# NuGet packaging is done separately via pack-csproj-step.yml after DLL signing.
parameters:
# The MSBuild build target in build.proj (e.g. BuildLogging, BuildAbstractions,
@@ -15,13 +15,6 @@ parameters:
- name: buildTarget
type: string
- # Build Configuration.
- - name: buildConfiguration
- type: string
- values:
- - Debug
- - Release
-
# Additional MSBuild arguments for version properties, e.g.
# -p:LoggingPackageVersion=1.0.0 -p:LoggingAssemblyFileVersion=1.0.123
- name: versionProperties
@@ -36,15 +29,15 @@ steps:
name: keyFile
- task: MSBuild@1
- displayName: Build.proj - ${{ parameters.buildTarget }}
+ displayName: 'Build.proj - ${{ parameters.buildTarget }}'
inputs:
- solution: $(REPO_ROOT)/build.proj
- configuration: ${{ parameters.buildConfiguration }}
+ solution: '$(REPO_ROOT)/build.proj'
+ configuration: 'Release'
msbuildArguments: >-
- -t:${{ parameters.buildTarget }}
- -p:ReferenceType=Package
- -p:SigningKeyPath=$(keyFile.secureFilePath)
- ${{ parameters.versionProperties }}
+ -t:${{ parameters.buildTarget }}
+ -p:ReferenceType=Package
+ -p:SigningKeyPath=$(keyFile.secureFilePath)
+ ${{ parameters.versionProperties }}
- script: tree /a /f $(BUILD_OUTPUT)
- displayName: List Build Output Tree
+ displayName: Output Build Output Tree
diff --git a/eng/pipelines/onebranch/steps/build-sqlclient-step.yml b/eng/pipelines/onebranch/steps/build-sqlclient-step.yml
new file mode 100644
index 0000000000..390d17fc34
--- /dev/null
+++ b/eng/pipelines/onebranch/steps/build-sqlclient-step.yml
@@ -0,0 +1,41 @@
+#################################################################################
+# 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. #
+#################################################################################
+
+# This collection of steps builds Microsoft.Data.SqlClient via build2.proj
+
+parameters:
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+steps:
+ - task: DownloadSecureFile@1
+ displayName: 'Download Signing Key'
+ inputs:
+ secureFile: 'netfxKeypair.snk'
+ name: keyFile
+
+ - task: MSBuild@1
+ displayName: 'Build2.proj - Build SqlClient'
+ inputs:
+ solution: '$(REPO_ROOT)/build2.proj'
+ configuration: 'Release'
+ msbuildArguments: >-
+ -t:BuildMds
+ -p:BuildNumber="$(Build.BuildNumber)"
+ -p:PackageVersionAbstractions="${{ parameters.abstractionsPackageVersion }}"
+ -p:PackageVersionLogging="${{ parameters.loggingPackageVersion }}"
+ -p:PackageVersionMds="${{ parameters.sqlClientPackageVersion }}"
+ -p:ReferenceType=Package
+ -p:SigningKeyPath="$(keyFile.secureFilePath)"
+
+ - script: tree /a /f $(BUILD_OUTPUT)
+ displayName: Output Build Output Tree
diff --git a/eng/pipelines/onebranch/steps/compound-nuget-pack-step.yml b/eng/pipelines/onebranch/steps/compound-nuget-pack-step.yml
deleted file mode 100644
index ef1f3b946a..0000000000
--- a/eng/pipelines/onebranch/steps/compound-nuget-pack-step.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-#################################################################################
-# Licensed to the .NET Foundation under one or more agreements. #
-# The .NET Foundation licenses this file to you under the MIT license. #
-# See the LICENSE file in the project root for more information. #
-#################################################################################
-
-parameters:
- # The C# build configuration to use (e.g. Debug or Release).
- - name: buildConfiguration
- type: string
- values:
- - Debug
- - Release
-
- - name: generateSymbolsPackage
- type: boolean
-
- - name: packageVersion
- type: string
-
- - name: nuspecPath
- type: string
-
- - name: outputDirectory
- type: string
-
- # The C# project reference type to use when building and packing the packages.
- - name: referenceType
- type: string
- values:
- # Reference sibling packages as NuGet packages.
- - Package
- # Reference sibling packages as C# projects.
- - Project
-
- # Semi-colon separated properties to pass to nuget via the -properties argument.
- - name: properties
- type: string
- default: ''
-
-steps:
- # This tool is failing on OneBranch pipelines, possibly due to new
- # network isolation rules:
- #
- # ERR:Client network socket disconnected before secure TLS connection was established
- #
- # Our AKV Official build uses this 1ES image:
- #
- # Image: 1ES-OB-2022-D8-Netlock-V2_westus2_1_image
- #
- # An ICM for this issue exists:
- #
- # https://portal.microsofticm.com/imp/v5/incidents/details/690355343/summary
- #
- # Recommendation is to remove this step since NuGet is already present on
- # the 1ES images.
- #
- # - task: NuGetToolInstaller@1
- # displayName: 'Install Latest Nuget'
- # inputs:
- # checkLatest: true
-
- - ${{ if parameters.generateSymbolsPackage }}:
- - task: NuGetCommand@2
- displayName: 'Generate NuGet Package and Symbols Package'
- inputs:
- command: custom
- arguments: >-
- pack
- ${{ parameters.nuspecPath }}
- -Symbols
- -SymbolPackageFormat snupkg
- -Version ${{ parameters.packageVersion }}
- -OutputDirectory ${{ parameters.outputDirectory }}
- -Properties "COMMITID=$(Build.SourceVersion);Configuration=${{ parameters.buildConfiguration }};ReferenceType=${{ parameters.referenceType }};${{ parameters.properties }}"
- - ${{ else }}:
- - task: NuGetCommand@2
- displayName: 'Generate NuGet Package'
- inputs:
- command: custom
- arguments: >-
- pack
- ${{ parameters.nuspecPath }}
- -Version ${{ parameters.packageVersion }}
- -OutputDirectory ${{ parameters.outputDirectory }}
- -Properties "COMMITID=$(Build.SourceVersion);Configuration=${{ parameters.buildConfiguration }};ReferenceType=${{ parameters.referenceType }};${{ parameters.properties }}"
diff --git a/eng/pipelines/onebranch/steps/compound-publish-symbols-step.yml b/eng/pipelines/onebranch/steps/compound-publish-symbols-step.yml
deleted file mode 100644
index 1b2e3cb3b9..0000000000
--- a/eng/pipelines/onebranch/steps/compound-publish-symbols-step.yml
+++ /dev/null
@@ -1,162 +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. #
-#################################################################################
-
-# For more details, see https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL
-
-parameters:
- # Name of the symbols artifact that will be published
- - name: artifactName
- type: string
-
- # Azure subscription where the publishing task will execute
- - name: azureSubscription
- type: string
-
- # Package name, typically the name of the nuget package being built
- - name: packageName
- type: string
-
- # Project that symbols will belong to (decided during symbols onboarding)
- - name: publishProjectName
- type: string
-
- # Where symbols publishing service is hosted, will be prepended to trafficmanager.net
- - name: publishServer
- type: string
-
- # Whether to publish the uploaded symbols to the internal symbols servers
- - name: publishToInternal
- type: boolean
-
- # Whether to publish the uploaded symbols to the public symbols servers
- - name: publishToPublic
- type: boolean
-
- # URI to use for requesting a bearer-token for publishing the symbols
- - name: publishTokenUri
- type: string
-
- # 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
-
- # Pattern to use to search for pdb symbols files to upload/publish
- - name: searchPattern
- type: string
-
- # Account/org where the symbols will be uploaded
- - name: uploadAccount
- type: string
-
- # Version of the symbols to publish, typically the same as the NuGet package version
- - name: version
- type: string
-
-steps:
- # Set variable for downstream tasks (allegedly).
- #
- # Note: Because variables cannot be set in top-level of template, this has to be done during
- # runtime.
- #
- - script: 'echo ##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{ parameters.uploadAccount }}'
- displayName: 'Set ArtifactServices.Symbol.AccountName to ${{ parameters.uploadAccount }}'
-
- - task: PublishSymbols@2
- displayName: 'Upload symbols to ${{ parameters.uploadAccount }} org'
- inputs:
- IndexSources: false
- Pat: '$(System.AccessToken)'
- SearchPattern: '${{ parameters.searchPattern }}'
- SymbolExpirationInDays: 1825 # 5 years
- SymbolServerType: 'TeamServices'
- SymbolsArtifactName: '${{ parameters.artifactName }}'
- SymbolsFolder: '$(BUILD_OUTPUT)/${{ parameters.referenceType }}/bin'
- SymbolsMaximumWaitTime: 60
- SymbolsProduct: '${{ parameters.packageName }}'
- SymbolsVersion: '${{ parameters.version }}'
-
- - task: AzureCLI@2
- displayName: 'Publish Symbols'
- inputs:
- azureSubscription: '${{ parameters.azureSubscription }}'
- scriptLocation: inlineScript
- scriptType: ps
- inlineScript: |
- # Propagate parameters to PS variables ################################################
- $artifactName = "${{ parameters.artifactName }}"
- echo "artifactName= $artifactName"
-
- $publishProjectName = "${{ parameters.publishProjectName }}"
- echo "publishProjectName= $publishProjectName"
-
- $publishToInternal = "${{ parameters.publishToInternal }}".ToLower()
- echo "publishToInternal= $publishToInternal"
-
- $publishToPublic = "${{ parameters.publishToPublic }}".ToLower()
- echo "publishToPublic= $publishToPublic"
-
- $publishServer = "${{ parameters.publishServer }}"
- echo "publishServer= $publishServer"
-
- $publishTokenUri = "${{ parameters.publishTokenUri }}"
- echo "publishTokenUri= $publishTokenUri"
-
- # Publish symbols #####################################################################
- # 1) Get the access token for the symbol publishing service
- echo "> 1.Acquiring symbol publishing token..."
- $symbolPublishingToken = az account get-access-token --resource $publishTokenUri --query accessToken -o tsv
- echo "> 1.Symbol publishing token acquired."
-
- # 2) Register the request name
- echo "> 2.Registering request name..."
- $requestNameRegistrationBody = "{'requestName': '$artifactName'}"
- Invoke-RestMethod `
- -Method POST `
- -Uri "https://$publishServer.trafficmanager.net/projects/$publishProjectName/requests" `
- -Headers @{ Authorization = "Bearer $symbolPublishingToken" } `
- -ContentType "application/json" `
- -Body $requestNameRegistrationBody
- echo "> 2.Request name registered successfully."
-
- # 3) Publish the symbols
- echo "> 3.Submitting request to publish symbols..."
- $publishSymbolsBody = "{'publishToInternalServer': $publishToInternal, 'publishToPublicServer': $publishToPublic}"
- Invoke-RestMethod `
- -Method POST `
- -Uri "https://$publishServer.trafficmanager.net/projects/$publishProjectName/requests/$artifactName" `
- -Headers @{ Authorization = "Bearer $symbolPublishingToken" } `
- -ContentType "application/json" `
- -Body $publishSymbolsBody
- echo "> 3.Request to publish symbols submitted successfully."
-
- # The following REST calls are used to check publishing status.
- echo "> 4.Checking the status of the request ..."
- Invoke-RestMethod `
- -Method GET `
- -Uri "https://$publishServer.trafficmanager.net/projects/$publishProjectName/requests/$artifactName" `
- -Headers @{ Authorization = "Bearer $symbolPublishingToken" } `
- -ContentType "application/json"
-
- echo "Use below tables to interpret the values of xxxServerStatus and xxxServerResult fields from the response."
-
- echo "PublishingStatus"
- echo "-----------------"
- echo "0 NotRequested; The request has not been requested to publish."
- echo "1 Submitted; The request is submitted to be published"
- echo "2 Processing; The request is still being processed"
- echo "3 Completed; The request has been completed processing. It can be failed or successful. Check PublishingResult to get more details"
-
- echo "PublishingResult"
- echo "-----------------"
- echo "0 Pending; The request has not completed or has not been requested."
- echo "1 Succeeded; The request has published successfully"
- echo "2 Failed; The request has failed to publish"
- echo "3 Cancelled; The request was cancelled"
diff --git a/eng/pipelines/onebranch/steps/esrp-code-signing-step.yml b/eng/pipelines/onebranch/steps/esrp-code-signing-step.yml
deleted file mode 100644
index 83053a8d29..0000000000
--- a/eng/pipelines/onebranch/steps/esrp-code-signing-step.yml
+++ /dev/null
@@ -1,166 +0,0 @@
-#################################################################################
-# Licensed to the .NET Foundation under one or more agreements. #
-# The .NET Foundation licenses this file to you under the MIT license. #
-# See the LICENSE file in the project root for more information. #
-#################################################################################
-parameters:
- - name: artifactType
- values:
- - dll
- - pkg
-
- - name: sourceRoot
- type: string
- default: $(REPO_ROOT)
-
- - name: dllPattern
- type: string
- default: 'Microsoft.Data.SqlClient*.dll'
-
- - name: nupkgPattern
- type: string
- default: '*.*nupkg'
-
- - name: artifactDirectory
- type: string
- default: $(PACK_OUTPUT)
-
- - name: ESRPConnectedServiceName
- type: string
- default: $(ESRPConnectedServiceName)
-
- - name: appRegistrationClientId
- type: string
- default: $(appRegistrationClientId)
-
- - name: appRegistrationTenantId
- type: string
- default: $(appRegistrationTenantId)
-
- - name: AuthAKVName
- type: string
- default: $(AuthAKVName)
-
- - name: AuthSignCertName
- type: string
- default: $(AuthSignCertName)
-
- - name: EsrpClientId
- type: string
- default: $(EsrpClientId)
-
-steps:
-- ${{ if eq(parameters.artifactType, 'dll') }}:
- # See: https://aka.ms/esrp.scantask
- - task: EsrpMalwareScanning@6
- displayName: 'ESRP MalwareScanning'
- inputs:
- ConnectedServiceName: '${{parameters.ESRPConnectedServiceName }}'
- AppRegistrationClientId: '${{parameters.appRegistrationClientId }}'
- AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}'
- EsrpClientId: '${{parameters.EsrpClientId }}'
- UseMSIAuthentication: true
- FolderPath: '${{parameters.sourceRoot }}'
- Pattern: '${{ parameters.dllPattern }}'
- CleanupTempStorage: 1
- VerboseLogin: 1
-
- # See: https://aka.ms/esrp.signtask
- - task: EsrpCodeSigning@6
- displayName: 'ESRP CodeSigning'
- inputs:
- ConnectedServiceName: '${{parameters.ESRPConnectedServiceName }}'
- AppRegistrationClientId: '${{parameters.appRegistrationClientId }}'
- AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}'
- EsrpClientId: '${{parameters.EsrpClientId }}'
- UseMSIAuthentication: true
- AuthAKVName: '${{parameters.AuthAKVName }}'
- AuthSignCertName: '${{parameters.AuthSignCertName }}'
- FolderPath: '${{parameters.sourceRoot }}'
- Pattern: '${{ parameters.dllPattern }}'
- signConfigType: inlineSignParams
- inlineOperation: |
- [
- {
- "keyCode": "CP-230012",
- "operationSetCode": "SigntoolSign",
- "parameters": [
- {
- "parameterName": "OpusName",
- "parameterValue": "Microsoft Data SqlClient Data Provider for SQL Server"
- },
- {
- "parameterName": "OpusInfo",
- "parameterValue": "http://www.microsoft.com"
- },
- {
- "parameterName": "FileDigest",
- "parameterValue": "/fd \"SHA256\""
- },
- {
- "parameterName": "PageHash",
- "parameterValue": "/NPH"
- },
- {
- "parameterName": "TimeStamp",
- "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
- }
- ],
- "toolName": "sign",
- "toolVersion": "1.0"
- },
- {
- "keyCode": "CP-230012",
- "operationSetCode": "SigntoolVerify",
- "parameters": [ ],
- "toolName": "sign",
- "toolVersion": "1.0"
- }
- ]
-
-- ${{ if eq(parameters.artifactType, 'pkg') }}:
- # See: https://aka.ms/esrp.scantask
- - task: EsrpMalwareScanning@6
- displayName: 'ESRP MalwareScanning Nuget Package'
- inputs:
- ConnectedServiceName: '${{parameters.ESRPConnectedServiceName }}'
- AppRegistrationClientId: '${{parameters.appRegistrationClientId }}'
- AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}'
- EsrpClientId: '${{parameters.EsrpClientId }}'
- UseMSIAuthentication: true
- FolderPath: '${{parameters.artifactDirectory }}'
- Pattern: '${{ parameters.nupkgPattern }}'
- CleanupTempStorage: 1
- VerboseLogin: 1
-
- # See: https://aka.ms/esrp.signtask
- - task: EsrpCodeSigning@6
- displayName: 'ESRP CodeSigning Nuget Package'
- inputs:
- ConnectedServiceName: '${{parameters.ESRPConnectedServiceName }}'
- AppRegistrationClientId: '${{parameters.appRegistrationClientId }}'
- AppRegistrationTenantId: '${{parameters.appRegistrationTenantId }}'
- EsrpClientId: '${{parameters.EsrpClientId }}'
- UseMSIAuthentication: true
- AuthAKVName: '${{parameters.AuthAKVName }}'
- AuthSignCertName: '${{parameters.AuthSignCertName }}'
- FolderPath: '${{parameters.artifactDirectory }}'
- Pattern: '${{ parameters.nupkgPattern }}'
- signConfigType: inlineSignParams
- inlineOperation: |
- [
- {
- "keyCode": "CP-401405",
- "operationSetCode": "NuGetSign",
- "parameters": [ ],
- "toolName": "sign",
- "toolVersion": "1.0"
- },
- {
- "keyCode": "CP-401405",
- "operationSetCode": "NuGetVerify",
- "parameters": [ ],
- "toolName": "sign",
- "toolVersion": "1.0"
- }
- ]
diff --git a/eng/pipelines/onebranch/steps/compound-esrp-dll-signing-step.yml b/eng/pipelines/onebranch/steps/esrp-dll-signing-step.yml
similarity index 76%
rename from eng/pipelines/onebranch/steps/compound-esrp-dll-signing-step.yml
rename to eng/pipelines/onebranch/steps/esrp-dll-signing-step.yml
index 44649f94aa..1398e81766 100644
--- a/eng/pipelines/onebranch/steps/compound-esrp-dll-signing-step.yml
+++ b/eng/pipelines/onebranch/steps/esrp-dll-signing-step.yml
@@ -30,8 +30,9 @@ parameters:
- name: esrpClientId
type: string
- # Globbing pattern for the files to sign. All files in $(BUILD_OUTPUT)/Package/bin
- # that match this pattern will be scanned and signed. This should end with ".dll".
+ # Minimatch pattern(s) for the files to sign. All files in $(BUILD_OUTPUT)
+ # that match will be scanned and signed. Supports multi-line patterns and
+ # negation (!pattern). See https://aka.ms/esrp.signtask for details.
- name: pattern
type: string
@@ -43,10 +44,11 @@ steps:
AppRegistrationClientId: ${{ parameters.appRegistrationClientId }}
AppRegistrationTenantId: ${{ parameters.appRegistrationTenantId }}
CleanupTempStorage: 1
- ConnectedServiceName: ${{ parameters.esrpConnectedServiceName }}
- EsrpClientId: ${{ parameters.esrpClientId }}
- FolderPath: $(BUILD_OUTPUT)/Package/bin
- Pattern: ${{ parameters.pattern }}
+ ConnectedServiceName: '${{ parameters.esrpConnectedServiceName }}'
+ EsrpClientId: '${{ parameters.esrpClientId }}'
+ FolderPath: '$(BUILD_OUTPUT)'
+ Pattern: '${{ parameters.pattern }}'
+ UseMinimatch: true
UseMSIAuthentication: true
VerboseLogin: 1
@@ -54,14 +56,15 @@ steps:
- task: EsrpCodeSigning@6
displayName: ESRP DLL Signing
inputs:
- AppRegistrationClientId: ${{ parameters.appRegistrationClientId }}
- AppRegistrationTenantId: ${{ parameters.appRegistrationTenantId }}
- AuthAKVName: ${{ parameters.authAkvName }}
- AuthSignCertName: ${{ parameters.authSignCertName }}
- ConnectedServiceName: ${{ parameters.esrpConnectedServiceName }}
- EsrpClientId: ${{ parameters.esrpClientId }}
- FolderPath: $(BUILD_OUTPUT)/Package/bin
- Pattern: ${{ parameters.pattern }}
+ AppRegistrationClientId: '${{ parameters.appRegistrationClientId }}'
+ AppRegistrationTenantId: '${{ parameters.appRegistrationTenantId }}'
+ AuthAKVName: '${{ parameters.authAkvName }}'
+ AuthSignCertName: '${{ parameters.authSignCertName }}'
+ ConnectedServiceName: '${{ parameters.esrpConnectedServiceName }}'
+ EsrpClientId: '${{ parameters.esrpClientId }}'
+ FolderPath: '$(BUILD_OUTPUT)'
+ Pattern: '${{ parameters.pattern }}'
+ UseMinimatch: true
signConfigType: inlineSignParams
UseMSIAuthentication: true
inlineOperation: |
diff --git a/eng/pipelines/onebranch/steps/compound-esrp-nuget-signing-step.yml b/eng/pipelines/onebranch/steps/esrp-nuget-signing-step.yml
similarity index 83%
rename from eng/pipelines/onebranch/steps/compound-esrp-nuget-signing-step.yml
rename to eng/pipelines/onebranch/steps/esrp-nuget-signing-step.yml
index e86964cf3d..6a6682d40f 100644
--- a/eng/pipelines/onebranch/steps/compound-esrp-nuget-signing-step.yml
+++ b/eng/pipelines/onebranch/steps/esrp-nuget-signing-step.yml
@@ -30,8 +30,13 @@ parameters:
- name: esrpClientId
type: string
- # Glob pattern to match NuGet packages for scanning and signing.
- - name: pattern
+ # Folder path to search for NuGet packages to sign
+ - name: searchPath
+ type: string
+
+ # Minimatch pattern(s) to search for NuGet packages. Supports multi-line
+ # patterns and negation (!pattern). Defaults to '*.*nupkg'.
+ - name: searchPattern
type: string
default: '*.*nupkg'
@@ -45,8 +50,9 @@ steps:
CleanupTempStorage: 1
ConnectedServiceName: '${{ parameters.esrpConnectedServiceName }}'
EsrpClientId: '${{ parameters.esrpClientId }}'
- FolderPath: '$(PACK_OUTPUT)'
- Pattern: '${{ parameters.pattern }}'
+ FolderPath: '${{ parameters.searchPath }}'
+ Pattern: '${{ parameters.searchPattern }}'
+ UseMinimatch: true
UseMSIAuthentication: true
VerboseLogin: 1
@@ -60,8 +66,9 @@ steps:
EsrpClientId: '${{ parameters.esrpClientId }}'
AuthAKVName: '${{ parameters.authAkvName }}'
AuthSignCertName: '${{ parameters.authSignCertName }}'
- FolderPath: '$(PACK_OUTPUT)'
- Pattern: '${{ parameters.pattern }}'
+ FolderPath: '${{ parameters.searchPath }}'
+ Pattern: '${{ parameters.searchPattern }}'
+ UseMinimatch: true
signConfigType: 'inlineSignParams'
UseMSIAuthentication: true
inlineOperation: |
diff --git a/eng/pipelines/onebranch/steps/compound-pack-csproj-step.yml b/eng/pipelines/onebranch/steps/pack-csproj-step.yml
similarity index 68%
rename from eng/pipelines/onebranch/steps/compound-pack-csproj-step.yml
rename to eng/pipelines/onebranch/steps/pack-csproj-step.yml
index db9b9a8237..535106a9d1 100644
--- a/eng/pipelines/onebranch/steps/compound-pack-csproj-step.yml
+++ b/eng/pipelines/onebranch/steps/pack-csproj-step.yml
@@ -14,13 +14,6 @@ parameters:
- name: packTarget
type: string
- # Build Configuration.
- - name: buildConfiguration
- type: string
- values:
- - Debug
- - Release
-
# Additional MSBuild arguments for version properties.
- name: versionProperties
type: string
@@ -28,15 +21,15 @@ parameters:
steps:
- task: MSBuild@1
- displayName: Build.proj - ${{ parameters.packTarget }}
+ displayName: 'Build.proj - ${{ parameters.packTarget }}'
inputs:
- solution: $(REPO_ROOT)/build.proj
- configuration: ${{ parameters.buildConfiguration }}
+ solution: '$(REPO_ROOT)/build.proj'
+ configuration: 'Release'
msbuildArguments: >-
- -t:${{ parameters.packTarget }}
- -p:ReferenceType=Package
- -p:PackagesDir=$(PACK_OUTPUT)/
- ${{ parameters.versionProperties }}
+ -t:${{ parameters.packTarget }}
+ -p:ReferenceType=Package
+ -p:PackagesDir=$(JOB_OUTPUT)/packages/
+ ${{ parameters.versionProperties }}
- - script: tree /a /f $(PACK_OUTPUT)
+ - script: tree /a /f $(JOB_OUTPUT)/packages
displayName: List Pack Output Tree After Pack
diff --git a/eng/pipelines/onebranch/steps/pack-sqlclient-step.yml b/eng/pipelines/onebranch/steps/pack-sqlclient-step.yml
new file mode 100644
index 0000000000..73229fe834
--- /dev/null
+++ b/eng/pipelines/onebranch/steps/pack-sqlclient-step.yml
@@ -0,0 +1,42 @@
+#################################################################################
+# Licensed to the .NET Foundation under one or more agreements. #
+# The .NET Foundation licenses this file to you under the MIT license. #
+# See the LICENSE file in the project root for more information. #
+#################################################################################
+
+parameters:
+ # Package version parameters ----
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+steps:
+ - task: MSBuild@1
+ displayName: 'Build2.proj - Pack SqlClient'
+ inputs:
+ solution: '$(REPO_ROOT)/build2.proj'
+ configuration: 'Release'
+ msbuildArguments: >-
+ -t:PackMds
+ -p:BuildNumber="$(Build.BuildNumber)"
+ -p:PackBuild=false
+ -p:PackageVersionAbstractions="${{ parameters.abstractionsPackageVersion }}"
+ -p:PackageVersionLogging="${{ parameters.loggingPackageVersion }}"
+ -p:PackageVersionMds="${{ parameters.sqlClientPackageVersion }}"
+ -p:ReferenceType=Package
+
+ - script: tree /a /f $(BUILD_OUTPUT)
+ displayName: Output Build Output Tree
+
+ - task: CopyFiles@2
+ displayName: 'Copy NuGet Packages to JOB_OUTPUT'
+ inputs:
+ contents: '**/Microsoft.Data.SqlClient*.*nupkg'
+ flattenFolders: true
+ sourceFolder: '$(BUILD_OUTPUT)/Microsoft.Data.SqlClient/'
+ targetFolder: '$(JOB_OUTPUT)/packages'
diff --git a/eng/pipelines/onebranch/steps/publish-symbols-step.yml b/eng/pipelines/onebranch/steps/publish-symbols-step.yml
index a23dbf4556..d06b3c73e5 100644
--- a/eng/pipelines/onebranch/steps/publish-symbols-step.yml
+++ b/eng/pipelines/onebranch/steps/publish-symbols-step.yml
@@ -1,119 +1,154 @@
-####################################################################################
-# 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. #
-# #
-# doc: https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL #
-####################################################################################
+#################################################################################
+# 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. #
+#################################################################################
+
+# Symbols Publishing Pipeline
+# ===========================
+# Canonical docs: https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL
+#
+# Publishing symbols to SymWeb (internal) and MSDL (public) is a two-step process:
+#
+# Step 1 - Upload: The PublishSymbols@2 task uploads PDB files to the Azure DevOps
+# symbol store under an artifact name (SymbolsArtifactName). This stores the
+# symbols but does NOT make them available on SymWeb or MSDL.
+#
+# Step 2 - Publish: The publish-symbols.ps1 script calls the Symbols Publishing Pipeline
+# REST API to request that the previously uploaded symbols be published to the
+# internal (SymWeb) and/or public (MSDL) symbol servers.
+#
+# IMPORTANT: Step 2 depends on Step 1. The ArtifactName parameter passed to the publish
+# script MUST match the SymbolsArtifactName used by PublishSymbols@2 so that both steps
+# reference the same uploaded artifact.
+
parameters:
+ # Name of the symbols artifact that will be published
+ - name: artifactName
+ type: string
+
+ # Azure subscription where the publishing task will execute
+ - name: azureSubscription
+ type: string
+
+ # Package name, typically the name of the nuget package being built
+ - name: packageName
+ type: string
+
+ # Project that symbols will belong to (decided during symbols onboarding)
+ - name: publishProjectName
+ type: string
+
+ # Where symbols publishing service is hosted, will be prepended to trafficmanager.net
+ - name: publishServer
+ type: string
+
+ # Whether to publish the uploaded symbols to the internal symbols servers
+ - name: publishToInternal
+ type: boolean
+
+ # Whether to publish the uploaded symbols to the public symbols servers
+ - name: publishToPublic
+ type: boolean
+
+ # URI to use for requesting a bearer-token for publishing the symbols
+ - name: publishTokenUri
+ type: string
+
+ # Pattern to use to search for pdb symbols files to upload/publish
+ - name: searchPattern
+ type: string
+
+ # Root folder to search for PDB files. When called from a build job this is typically
+ # $(BUILD_OUTPUT); when called from the dedicated symbols stage it points at the
+ # downloaded artifact path containing the PDBs.
+ - name: symbolsFolder
+ type: string
+ default: '$(BUILD_OUTPUT)'
+
+ # Account/org where the symbols will be uploaded
+ - name: uploadAccount
+ type: string
- # The full name of the package whose symbols are being published.
- - name: packageFullName
- type: string
-
- # The version of the package whose symbols are being published.
- - name: packageVersion
- type: string
-
- # Our symbols account name.
- - name: symbolsAccount
- type: string
- default: SqlClientDrivers
-
- # The symbols server to publish to.
- - name: symbolServer
- type: string
- default: $(SymbolServer)
-
- # The token URI for the symbol publishing service.
- - name: symbolTokenUri
- type: string
- default: $(SymbolTokenUri)
-
- # A pair of flags indicating whether to publish to the internal and public symbol servers. Both
- # default to true.
- - name: publishToServers
- type: object
- default:
- internal: true
- public: true
+ # Version of the symbols to publish, typically the same as the NuGet package version
+ - name: version
+ type: string
steps:
-- pwsh: 'Write-Host "##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{parameters.symbolsAccount}}"'
- displayName: 'Set ArtifactServices.Symbol.AccountName to ${{parameters.symbolsAccount}}'
-
-- pwsh: 'Write-Host "##vso[task.setvariable variable=symbolsArtifactName;]${{ parameters.packageFullName }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.packageVersion }}_$(System.TimelineId)"'
- displayName: 'Set symbolsArtifactName variable'
-
-- task: PublishSymbols@2
- displayName: 'Upload symbols to ${{parameters.symbolsAccount }} org'
- inputs:
- SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\Package\bin'
- SearchPattern: '**/*.pdb'
- IndexSources: false
- SymbolServerType: TeamServices
- SymbolsMaximumWaitTime: 60
- SymbolExpirationInDays: 1825 # 5 years
- SymbolsProduct: ${{ parameters.packageFullName }}
- SymbolsVersion: ${{ parameters.packageVersion }}
- SymbolsArtifactName: $(symbolsArtifactName)
- Pat: $(System.AccessToken)
-
-- task: AzureCLI@2
- displayName: 'Publish symbols'
- inputs:
- azureSubscription: 'Symbols publishing Workload Identity federation service-ADO.Net'
- scriptType: ps
- scriptLocation: inlineScript
- inlineScript: |
- $publishToInternalServer = "${{parameters.publishToServers.internal }}".ToLower()
- $publishToPublicServer = "${{parameters.publishToServers.public }}".ToLower()
-
- echo "Publishing request name: $(symbolsArtifactName)"
- echo "Publish to internal server: $publishToInternalServer"
- echo "Publish to public server: $publishToPublicServer"
-
- $symbolServer = "${{parameters.symbolServer }}"
- $tokenUri = "${{parameters.symbolTokenUri }}"
- # Registered project name in the symbol publishing pipeline: https://portal.microsofticm.com/imp/v3/incidents/incident/520844254/summary
- $projectName = "Microsoft.Data.SqlClient.SNI"
-
- # Get the access token for the symbol publishing service
- $symbolPublishingToken = az account get-access-token --resource $tokenUri --query accessToken -o tsv
-
- echo "> 1.Symbol publishing token acquired."
-
- echo "Registering the request name ..."
- $requestName = "$(symbolsArtifactName)"
- $requestNameRegistrationBody = "{'requestName': '$requestName'}"
- Invoke-RestMethod -Method POST -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json" -Body $requestNameRegistrationBody
-
- echo "> 2.Registration of request name succeeded."
-
- echo "Publishing the symbols ..."
- $publishSymbolsBody = "{'publishToInternalServer': $publishToInternalServer, 'publishToPublicServer': $publishToPublicServer}"
- echo "Publishing symbols request body: $publishSymbolsBody"
- Invoke-RestMethod -Method POST -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests/$requestName" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json" -Body $publishSymbolsBody
-
- echo "> 3.Request to publish symbols succeeded."
-
- # The following REST calls are used to check publishing status.
- echo "> 4.Checking the status of the request ..."
-
- Invoke-RestMethod -Method GET -Uri "https://$symbolServer.trafficmanager.net/projects/$projectName/requests/$requestName" -Headers @{ Authorization = "Bearer $symbolPublishingToken" } -ContentType "application/json"
-
- echo "Use below tables to interpret the values of xxxServerStatus and xxxServerResult fields from the response."
-
- echo "PublishingStatus"
- echo "-----------------"
- echo "0 NotRequested; The request has not been requested to publish."
- echo "1 Submitted; The request is submitted to be published"
- echo "2 Processing; The request is still being processed"
- echo "3 Completed; The request has been completed processing. It can be failed or successful. Check PublishingResult to get more details"
-
- echo "PublishingResult"
- echo "-----------------"
- echo "0 Pending; The request has not completed or has not been requested."
- echo "1 Succeeded; The request has published successfully"
- echo "2 Failed; The request has failed to publish"
- echo "3 Cancelled; The request was cancelled"
+ # Set variable for downstream tasks (allegedly).
+ #
+ # Note: Because variables cannot be set in top-level of template, this has to be done during
+ # runtime.
+ #
+ - script: 'echo ##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{ parameters.uploadAccount }}'
+ displayName: 'Set ArtifactServices.Symbol.AccountName to ${{ parameters.uploadAccount }}'
+
+ # Log the PDB files that match the search pattern so we can verify no
+ # unexpected files are included in the upload.
+ - pwsh: |
+ $folder = '${{ parameters.symbolsFolder }}'
+ $glob = '${{ parameters.searchPattern }}'
+ Write-Host "Symbols folder : $folder"
+ Write-Host "Search pattern : $glob"
+
+ # Convert the glob to a regex that can match against relative paths.
+ # ** → match any number of path segments (.*?)
+ # * → match within a single segment ([^/\\]*)
+ # ? → match a single non-separator char ([^/\\])
+ # . → literal dot
+ $regex = [regex]::Escape($glob)
+ $regex = $regex -replace '\\\*\\\*[/\\]?', '.*?' # ** or **/
+ $regex = $regex -replace '\\\*', '[^/\\]*' # single *
+ $regex = $regex -replace '\\\?', '[^/\\]' # single ?
+ $regex = '^' + $regex + '$'
+ Write-Host "Regex : $regex"
+ Write-Host ""
+
+ $allFiles = Get-ChildItem -Path $folder -Recurse -File
+ $matched = $allFiles | Where-Object {
+ $rel = $_.FullName.Substring($folder.Length).TrimStart('/\')
+ $rel -match $regex
+ }
+
+ if (-not $matched) {
+ Write-Host "##vso[task.logissue type=warning]No PDB files matched pattern '$glob' under '$folder'"
+ } else {
+ $count = @($matched).Count
+ Write-Host "Matched $count PDB file(s):"
+ $matched | ForEach-Object { Write-Host " $($_.FullName)" }
+ }
+ displayName: 'Log PDBs matching ${{ parameters.searchPattern }}'
+
+ # Step 1 - Upload: Push PDB files to the Azure DevOps symbol store.
+ # The SymbolsArtifactName set here is the key that links this upload to Step 2.
+ - task: PublishSymbols@2
+ displayName: 'Step 1: Upload symbols to ${{ parameters.uploadAccount }} org'
+ inputs:
+ IndexSources: false
+ Pat: '$(System.AccessToken)'
+ SearchPattern: '${{ parameters.searchPattern }}'
+ SymbolExpirationInDays: 1825 # 5 years
+ SymbolServerType: 'TeamServices'
+ SymbolsArtifactName: '${{ parameters.artifactName }}'
+ SymbolsFolder: '${{ parameters.symbolsFolder }}'
+ SymbolsMaximumWaitTime: 60
+ SymbolsProduct: '${{ parameters.packageName }}'
+ SymbolsVersion: '${{ parameters.version }}'
+
+ # Step 2 - Publish: Request the Symbols Publishing Pipeline to publish the uploaded
+ # symbols to SymWeb and/or MSDL. The -ArtifactName argument must match the
+ # SymbolsArtifactName from Step 1.
+ - task: AzureCLI@2
+ displayName: 'Step 2: Publish symbols to SymWeb/MSDL'
+ inputs:
+ azureSubscription: '${{ parameters.azureSubscription }}'
+ scriptType: pscore
+ scriptLocation: scriptPath
+ scriptPath: '$(Build.SourcesDirectory)/eng/pipelines/onebranch/scripts/publish-symbols.ps1'
+ arguments: >-
+ -PublishServer "${{ parameters.publishServer }}"
+ -PublishTokenUri "${{ parameters.publishTokenUri }}"
+ -PublishProjectName "${{ parameters.publishProjectName }}"
+ -ArtifactName "${{ parameters.artifactName }}"
+ -PublishToInternal $${{ parameters.publishToInternal }}
+ -PublishToPublic $${{ parameters.publishToPublic }}
diff --git a/eng/pipelines/onebranch/steps/code-analyze-step.yml b/eng/pipelines/onebranch/steps/roslyn-analyzers-csproj-step.yml
similarity index 68%
rename from eng/pipelines/onebranch/steps/code-analyze-step.yml
rename to eng/pipelines/onebranch/steps/roslyn-analyzers-csproj-step.yml
index c112493603..53b17d4bb9 100644
--- a/eng/pipelines/onebranch/steps/code-analyze-step.yml
+++ b/eng/pipelines/onebranch/steps/roslyn-analyzers-csproj-step.yml
@@ -5,42 +5,35 @@
#################################################################################
# This template defines a step to run Roslyn Analyzers against builds driven by
-# build.proj. It is used for both the full Microsoft.Data.SqlClient (MDS) build
+# build.proj. It is used for both the full Microsoft.Data.SqlClient (SqlClient) build
# and for individual extension packages; callers control the analyzed targets
# via the msBuildArguments parameter.
# It uses the RoslynAnalyzers@3 task from the Secure Development Team's SDL
# extension:
-#
# https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-mohanb/security-integration/guardian-wiki/sdl-azdo-extension/roslyn-analyzers-build-task
#
-# GOTCHA: This step will clobber any existing build output. It should be run
+# GOTCHA: This step will clobber any existing build output. It should be run
# _before_ any build steps that perform versioning or signing.
parameters:
- # Source Root.
- - name: sourceRoot
+ # Target to build from build.proj. This is separated from the rest of the msBuildArguments to
+ # provide a rich display name.
+ - name: buildTarget
type: string
- default: $(REPO_ROOT)
- # MSBuild arguments appended after the project file path. The default targets
- # BuildAllConfigurations for the full MDS build; override this when analyzing
- # individual extension packages.
+ # Additional build arguments to append to the end of the MSBuild command.
- name: msBuildArguments
type: string
- default: >-
- -t:BuildAllConfigurations
- -p:configuration=Release
- -p:GenerateNuget=false
- -p:BuildTools=false
steps:
- task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@3
- displayName: Roslyn Analyzers
+ displayName: 'Roslyn Analyzers: build.proj ${{ parameters.buildTarget }}'
inputs:
msBuildVersion: 17.0
msBuildArchitecture: x64
setupCommandLinePicker: vs2022
msBuildCommandLine: >-
msbuild
- ${{parameters.sourceRoot}}\build.proj
- ${{parameters.msBuildArguments}}
+ $(REPO_ROOT)\build.proj
+ -t:${{ parameters.buildTarget }}
+ ${{ parameters.msBuildArguments }}
diff --git a/eng/pipelines/onebranch/steps/roslyn-analyzers-sqlclient-step.yml b/eng/pipelines/onebranch/steps/roslyn-analyzers-sqlclient-step.yml
new file mode 100644
index 0000000000..ac515aa021
--- /dev/null
+++ b/eng/pipelines/onebranch/steps/roslyn-analyzers-sqlclient-step.yml
@@ -0,0 +1,40 @@
+#################################################################################
+# 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. #
+#################################################################################
+
+# This template defines a step to run Roslyn Analyzers on the SqlClient build. It uses the
+# RoslynAnalyzers@3 task from the Secure Development Team's SDL extension:
+#
+# https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-mohanb/security-integration/guardian-wiki/sdl-azdo-extension/roslyn-analyzers-build-task
+#
+# GOTCHA: This step will clobber any existing build output. It should be run _before_ any build
+# steps that perform versioning or signing.
+
+parameters:
+ - name: abstractionsPackageVersion
+ type: string
+
+ - name: loggingPackageVersion
+ type: string
+
+ - name: sqlClientPackageVersion
+ type: string
+
+steps:
+ - task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@3
+ displayName: 'Roslyn Analyzers: build2.proj Build SqlClient'
+ inputs:
+ msBuildArchitecture: x64
+ msBuildCommandLine: >-
+ msbuild
+ $(REPO_ROOT)/build2.proj
+ -t:BuildMds
+ -p:Configuration=Release
+ -p:PackageVersionAbstractions=${{ parameters.abstractionsPackageVersion }}
+ -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }}
+ -p:PackageVersionMds=${{ parameters.sqlClientPackageVersion }}
+ -p:ReferenceType=Package
+ msBuildVersion: 17.0
+ setupCommandLinePicker: vs2022
diff --git a/eng/pipelines/onebranch/variables/common-variables.yml b/eng/pipelines/onebranch/variables/common-variables.yml
index 35236f7ff6..3df1a6264f 100644
--- a/eng/pipelines/onebranch/variables/common-variables.yml
+++ b/eng/pipelines/onebranch/variables/common-variables.yml
@@ -7,181 +7,37 @@
# Common variables shared across all OneBranch Official pipelines.
variables:
- - group: Release Variables
-
- # Symbols publishing credentials
- - group: Symbols publishing
- # SymbolsAzureSubscription
- # SymbolsPublishProjectName
- # SymbolsPublishServer
- # SymbolsPublishTokenUri
- # SymbolsUploadAccount
-
- - group: ESRP Federated Creds (AME)
- # ESRPConnectedServiceName
- # ESRPClientId
- # AppRegistrationClientId
- # AppRegistrationTenantId
- # AuthAKVName
- # AuthSignCertName
-
- name: CommitHead
value: '' # the value will be extracted from the repo's head
- # Aliases required by compound step templates (compound-esrp-dll-signing-step,
- # compound-esrp-nuget-signing-step, compound-nuget-pack-step, etc.).
+ ##########################################################################
+ # "Well-Known" Variables that are ok to use directly, anywhere in the pipeline.
# The root of our repo.
- name: REPO_ROOT
value: $(Build.SourcesDirectory)
# This is where our C# projects place their build outputs (see Directory.Build.props
- # ). We exclude the reference type here since Official pipelines always use
+ # ). We exclude the reference type here since Official pipelines always use
# Package mode.
- name: BUILD_OUTPUT
value: $(REPO_ROOT)/artifacts
- # This is where our C# projects place their NuGet package outputs. This is intentionally
- # separate from packages/ (where downloaded pipeline artifacts go) so that ESRP signing and
- # OneBranch artifact publishing only operate on packages built by the current job.
- - name: PACK_OUTPUT
+ # Directory where downloaded pipeline artifacts (NuGet packages from earlier
+ # stages) are placed. Build jobs use this as a local NuGet package source so
+ # that downstream packages can resolve dependencies on packages built by
+ # upstream stages.
+ - name: JOB_INPUT
+ value: $(REPO_ROOT)/packages
+
+ # Root directory for all job output artifacts (NuGet packages, symbols, etc.).
+ # OneBranch auto-publishes everything under this directory. It is intentionally
+ # separated from packages/ (where downloaded pipeline artifacts go) so that ESRP
+ # signing and OneBranch artifact publishing only operate on the current job's output.
+ #
+ # Sub-directory layout:
+ # assemblies/ - DLL assemblies for APIScan (preserving TFM folder structure)
+ # packages/ - NuGet packages (.nupkg, .snupkg)
+ # symbols/ - PDB symbol files (preserving TFM folder structure)
+ - name: JOB_OUTPUT
value: $(REPO_ROOT)/output
-
- # C# assembly versions must be in the format: Major.Minor.Build.Revision, but
- # $(Build.BuildNumber) has the format XXX.YY. Additionally, each version part
- # must be a positive 16-bit integer less than 65535. Simply concatenating
- # both parts of $(Build.BuildNumber) could produce values larger than 65534,
- # so we must omit the second part entirely. Unfortunately, this may result
- # in multiple subsequent pipline builds using the same C# assembly versions.
- # The package versions will not be affected and will show the complete
- # $(Build.BuildNumber) values.
- - name: assemblyBuildNumber
- value: $[ split(variables['Build.BuildNumber'], '.')[0] ]
-
- # ----------------------------------------------------------------------------
- # Abstractions Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: abstractionsPackageVersion
- value: '1.0.0'
-
- # The NuGet package version for preview releases.
- - name: abstractionsPackagePreviewVersion
- value: 1.0.0-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the Abstractions package.
- - name: abstractionsAssemblyFileVersion
- value: 1.0.0.$(assemblyBuildNumber)
-
- # ----------------------------------------------------------------------------
- # MDS Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: mdsPackageVersion
- value: '7.0.1'
-
- # The NuGet package version for preview releases.
- #
- # Since we're on the release/7.0 branch, there will never be another legitimate preview release.
- # However, we routinely want to run preview builds to test other changes, so we continue to
- # maintain this variable such that these testing preview builds receive newer version numbers
- # than previous builds.
- - name: mdsPackagePreviewVersion
- value: 7.0.2-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the MDS package.
- - name: mdsAssemblyFileVersion
- value: 7.0.1.$(assemblyBuildNumber)
-
- # The path to the NuGet packaging specification file used to generate the MDS NuGet package.
- - name: nuspecPath
- value: '$(REPO_ROOT)/tools/specs/Microsoft.Data.SqlClient.nuspec'
-
- # ----------------------------------------------------------------------------
- # Logging Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: loggingPackageVersion
- value: '1.0.0'
-
- # The NuGet package version for preview releases.
- - name: loggingPackagePreviewVersion
- value: 1.0.0-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the Logging package.
- - name: loggingAssemblyFileVersion
- value: 1.0.0.$(assemblyBuildNumber)
-
- # ----------------------------------------------------------------------------
- # Azure Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: azurePackageVersion
- value: '1.0.0'
-
- # The NuGet package version for preview releases.
- - name: azurePackagePreviewVersion
- value: 1.0.0-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the Azure package.
- - name: azureAssemblyFileVersion
- value: 1.0.0.$(assemblyBuildNumber)
-
- # ----------------------------------------------------------------------------
- # SqlServer.Server Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: sqlServerPackageVersion
- value: '1.0.0'
-
- # The NuGet package version for preview releases.
- - name: sqlServerPackagePreviewVersion
- value: 1.0.0-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the SqlServer.Server package.
- - name: sqlServerAssemblyFileVersion
- value: 1.0.0.$(assemblyBuildNumber)
-
- # ----------------------------------------------------------------------------
- # AKV Provider Package Versions
- #
- # These are version values that will be used by the official build. They
- # should be updated after each release to reflect the next release's versions.
-
- # The NuGet package version for GA releases (non-preview).
- - name: akvPackageVersion
- value: '7.0.0'
-
- # The NuGet package version for preview releases.
- - name: akvPackagePreviewVersion
- value: 7.0.0-preview1.$(Build.BuildNumber)
-
- # The AssemblyFileVersion for all assemblies in the AKV Provider package.
- - name: akvAssemblyFileVersion
- value: 7.0.0.$(assemblyBuildNumber)
-
- # ----------------------------------------------------------------------------
- # MDS Symbols Publishing
- #
- # Alias variables for MDS publish-symbols-step.yml, which defaults to
- # $(SymbolServer) and $(SymbolTokenUri). These map to the values provided
- # by the "Symbols publishing" library group.
- - name: SymbolServer
- value: $(SymbolsPublishServer)
- - name: SymbolTokenUri
- value: $(SymbolsPublishTokenUri)
diff --git a/eng/pipelines/onebranch/variables/onebranch-variables.yml b/eng/pipelines/onebranch/variables/onebranch-variables.yml
index 9c60ff4cf0..b3bebb0a64 100644
--- a/eng/pipelines/onebranch/variables/onebranch-variables.yml
+++ b/eng/pipelines/onebranch/variables/onebranch-variables.yml
@@ -4,52 +4,41 @@
# See the LICENSE file in the project root for more information. #
#################################################################################
-# This file is only included in MDS OneBranch Official pipelines.
+# This file is only included in SqlClient OneBranch official/non-official pipelines.
variables:
- - template: /eng/pipelines/onebranch/variables/common-variables.yml@self
+ # Libraries ==============================================================
- # onebranch template variables
- - name: ob_sdl_binskim_break
- value: true # https://aka.ms/obpipelines/sdl
- - 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
-
- # OneBranch automatically publishes pipeline artifacts from all jobs. Use of the
- # PublishPipelineArtifacts task is prohibited. All content in the ob_outputDirectory is
- # published. The artifacts are named according to this pattern:
- #
- # drop__
+ # These variables are used for running ESRP signing tasks. All names start with "Signing" to make
+ # it clear that these variables are used for signing (as opposed to other msc tasks).
#
- # Downstream stages and jobs may download these artifacts via the DownloadPipelineArtifact task,
- # but they must know the artifact name.
+ # SigningAppRegistrationClientId
+ # SigningAppRegistrationTenantId
+ # SigningAuthAkvName
+ # SigningAuthSignCertName
+ # SigningEsrpClientId
+ # SigningEsrpConnectedServiceName
+ - group: 'esrp-variables-v2'
+
+ # These variables are used for running symbol publishing tasks. All names start with "Symbols" to
+ # make it clear that these variables are used for symbols (as opposed to other msc tasks).
#
- # Here we define the artifact names that our OneBranch pipelines produce to avoid hardcoding them
- # throughout the pipeline files. If any of the stage or job names change, we only need to update
- # the artifact names here.
-
- # The Abstractions package artifacts.
- - name: abstractionsArtifactsName
- value: drop_build_abstractions_build_package_Abstractions
+ # SymbolsAzureSubscription
+ # SymbolsPublishProjectNameSqlClient
+ # SymbolsPublishServerProd / SymbolsPublishServerPPE
+ # SymbolsPublishTokenUriProd / SymbolsPublishTokenUriPPE
+ # SymbolsUploadAccount
+ - group: 'Symbols Publishing'
- # The AKV Provider package artifacts.
- - name: akvArtifactsName
- value: drop_build_addons_build_package_AkvProvider
+ # OneBranch Template Variables ###########################################
- # The Azure package artifacts.
- - name: azureArtifactsName
- value: drop_build_dependent_build_package_Azure
-
- # The Logging package artifacts.
- - name: loggingArtifactsName
- value: drop_build_independent_build_package_Logging
+ # https://aka.ms/obpipelines/sdl
+ - name: ob_sdl_binskim_break
+ value: true
- # The SqlServer package artifacts.
- - name: sqlServerArtifactsName
- value: drop_build_independent_build_package_SqlServer
+ - name: Packaging.EnableSBOMSigning
+ value: true
- # The SqlClient package artifacts.
- - name: sqlClientArtifactsName
- value: drop_build_dependent_build_package_SqlClient
+ # Docker image which is used to build the project https://aka.ms/obpipelines/containers
+ - name: WindowsContainerImage
+ value: "onebranch.azurecr.io/windows/ltsc2022/vse2022:latest"
diff --git a/eng/pipelines/onebranch/variables/package-variables.yml b/eng/pipelines/onebranch/variables/package-variables.yml
new file mode 100644
index 0000000000..a07193bbe5
--- /dev/null
+++ b/eng/pipelines/onebranch/variables/package-variables.yml
@@ -0,0 +1,149 @@
+#################################################################################
+# 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. #
+#################################################################################
+
+# This file contains variables that relate to the various packages that are produced via the
+# OneBranch official/non-official pipelines. They are grouped by the packages they represent.
+#
+# The variables are defined as the following main types:
+# - *ArtifactsName
+# What the artifacts drop for the various stages of the pipeline will be named.
+#
+# OneBranch automatically publishes pipeline artifacts from all jobs. Use of the
+# PublishPipelineArtifacts task is prohibited. All content in the ob_outputDirectory is
+# automatically published. The artifacts are named according to this pattern:
+#
+# drop__
+#
+# Downstream stages and jobs may download these artifacts via the DownloadPipelineArtifact task,
+# but they must know the artifact name.
+#
+# - *FileVersion
+# Version to use for the FileVersion field in the assembly.
+#
+# - *PackageVersion
+# NuGet package versions releases. This is switched based on the isPreview parameter.
+
+# @TODO: Although defining the versions in source is a major improvement over depending on versions
+# coming from variable libraries, this is not the final form. Ideally, we want a single point for
+# versions to be defined and are moving towards doing so via the [PackageName]Versions.props
+# files. In the meantime, when doing a version bump (after a release), versions will need to be
+# updated here and in their corresponding *Versions.props file.
+
+parameters:
+ - name: isPreview
+ type: boolean
+
+variables:
+ # C# assembly versions must be in the format: Major.Minor.Build.Revision, but
+ # $(Build.BuildNumber) has the format XXX.YY. Additionally, each version part must be a positive
+ # 16-bit integer less than 65535. Simply concatenating both parts of $(Build.BuildNumber) could
+ # produce values larger than 65534, so we must omit the second part entirely. Unfortunately, this
+ # may result in multiple subsequent pipeline builds using the same C# assembly versions. The
+ # package versions will not be affected and will show the complete $(Build.BuildNumber) values.
+ - name: _assemblyBuildNumber
+ value: $[ split(variables['Build.BuildNumber'], '.')[0] ]
+
+ # ------------------------------------------------------------------------
+ # Abstractions Package
+ # Microsoft.Data.SqlClient.Extensions.Abstractions
+ - name: abstractionsArtifactsName
+ value: 'drop_build_abstractions_build_package_Abstractions'
+
+ - ${{ if parameters.isPreview }}:
+ - name: abstractionsFileVersion
+ value: '1.0.2.$(_assemblyBuildNumber)'
+ - name: abstractionsPackageVersion
+ value: '1.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: abstractionsFileVersion
+ value: '1.0.1.$(_assemblyBuildNumber)'
+ - name: abstractionsPackageVersion
+ value: '1.0.1'
+
+ # ------------------------------------------------------------------------
+ # AKV Provider Package
+ # Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVault
+ - name: akvProviderArtifactsName
+ value: 'drop_build_addons_build_package_AkvProvider'
+
+ - ${{ if parameters.isPreview }}:
+ - name: akvProviderFileVersion
+ value: '7.0.2.$(_assemblyBuildNumber)'
+ - name: akvProviderPackageVersion
+ value: '7.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: akvProviderFileVersion
+ value: '7.0.1.$(_assemblyBuildNumber)'
+ - name: akvProviderPackageVersion
+ value: '7.0.1'
+
+ # ------------------------------------------------------------------------
+ # Azure Package
+ # Microsoft.Data.SqlClient.Extensions.Azure
+ - name: azureArtifactsName
+ value: 'drop_build_dependent_build_package_Azure'
+
+ - ${{ if parameters.isPreview }}:
+ - name: azureFileVersion
+ value: '1.0.2.$(_assemblyBuildNumber)'
+ - name: azurePackageVersion
+ value: '1.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: azureFileVersion
+ value: '1.0.1.$(_assemblyBuildNumber)'
+ - name: azurePackageVersion
+ value: '1.0.1'
+
+ # ------------------------------------------------------------------------
+ # Logging Package
+ # Microsoft.Data.SqlClient.Internal.Logging
+ - name: loggingArtifactsName
+ value: 'drop_build_independent_build_package_Logging'
+
+ - ${{ if parameters.isPreview }}:
+ - name: loggingFileVersion
+ value: '1.0.2.$(_assemblyBuildNumber)'
+ - name: loggingPackageVersion
+ value: '1.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: loggingFileVersion
+ value: '1.0.1.$(_assemblyBuildNumber)'
+ - name: loggingPackageVersion
+ value: '1.0.1'
+
+ # ------------------------------------------------------------------------
+ # SqlClient Package
+ # Microsoft.Data.SqlClient
+ - name: sqlClientArtifactsName
+ value: 'drop_build_dependent_build_package_SqlClient'
+
+ - ${{ if parameters.isPreview }}:
+ - name: sqlClientFileVersion
+ value: '7.0.2.$(_assemblyBuildNumber)'
+ - name: sqlClientPackageVersion
+ value: '7.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: sqlClientFileVersion
+ value: '7.0.1.$(_assemblyBuildNumber)'
+ - name: sqlClientPackageVersion
+ value: '7.0.1'
+
+ # ------------------------------------------------------------------------
+ # SqlServer Package
+ # Microsoft.SqlServer.Server
+ - name: sqlServerArtifactsName
+ value: 'drop_build_independent_build_package_SqlServer'
+
+ - ${{ if parameters.isPreview }}:
+ - name: sqlServerFileVersion
+ value: '1.0.2.$(_assemblyBuildNumber)'
+ - name: sqlServerPackageVersion
+ value: '1.0.2-preview1.$(Build.BuildNumber)'
+ - ${{ else }}:
+ - name: sqlServerFileVersion
+ value: '1.0.1.$(_assemblyBuildNumber)'
+ - name: sqlServerPackageVersion
+ value: '1.0.1'
diff --git a/eng/pipelines/onebranch/variables/sqlclient-validation-variables.yml b/eng/pipelines/onebranch/variables/sqlclient-validation-variables.yml
deleted file mode 100644
index 75ad369dbc..0000000000
--- a/eng/pipelines/onebranch/variables/sqlclient-validation-variables.yml
+++ /dev/null
@@ -1,38 +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. #
-#################################################################################
-
-# This file is only included in MDS OneBranch Official pipelines.
-
-variables:
- - group: Release Variables
- - template: /eng/pipelines/onebranch/variables/common-variables.yml@self
-
- - name: TempFolderName # extract the nuget package here
- value: temp
- - name: extractedNugetRootPath
- value: $(Build.SourcesDirectory)\$(TempFolderName)\Microsoft.Data.SqlClient
- - name: extractedNugetPath
- value: $(extractedNugetRootPath).$(mdsPackageVersion)
- - name: expectedFolderNames
- value: lib,ref,runtimes
- - name: expectedDotnetVersions
- value: netstandard2.0,net462,net8.0,net9.0
- - name: Database
- value: Northwind
- - name: platform
- value: AnyCPU
- - name: TargetNetFxVersion
- value: net481
- - name: TargetNetCoreVersion
- value: net9.0
- - name: SQLTarget
- value: localhost
- - name: encrypt
- value: false
- - name: SQL_NP_CONN_STRING
- value: Data Source=np:$(SQLTarget);Initial Catalog=$(Database);Integrated Security=true;Encrypt=$(ENCRYPT);TrustServerCertificate=true;
- - name: SQL_TCP_CONN_STRING
- value: Data Source=tcp:$(SQLTarget);Initial Catalog=$(Database);Integrated Security=true;Encrypt=$(ENCRYPT);TrustServerCertificate=true;