From c347fdc3d74caa65c536d5933b3d2ab4448b0348 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 14 May 2026 15:29:22 -0300 Subject: [PATCH 1/6] Added new sqlclient-package CI pipeline. --- .../ci/package/sqlclient-package.yml | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 eng/pipelines/ci/package/sqlclient-package.yml diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml new file mode 100644 index 0000000000..1052ed3d33 --- /dev/null +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -0,0 +1,181 @@ +################################################################################# +# 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 pipeline builds all packages using the build.proj Pack target with ReferenceType=Package, +# then publishes the resulting .nupkg and .snupkg files as a single pipeline artifact. +# +# It runs: +# - On pushes to GitHub main and ADO internal/main (batched) +# - Nightly at 00:00 UTC on both branches +# +# On internal/main the strong-name signing key is downloaded and used to sign assemblies during the +# build. +# +# GOTCHA: This pipeline definition is triggered by GitHub _and_ ADO CI. We distinguish the two via +# branch filters: +# +# - Only the GitHub repo has a 'main' branch. +# - Only the ADO repo has an 'internal/main' branch. + +name: $(DayOfYear)$(Rev:rr) + +# Do not trigger this pipeline for PRs. +pr: none + +# Trigger on pushes to main and internal/main, batching concurrent commits. +trigger: + batch: true + branches: + include: + - main + - internal/main + +# Nightly schedule at 00:00 UTC. +schedules: + - cron: '0 0 * * *' + displayName: Nightly Build + branches: + include: + - main + - internal/main + always: true + +# Pipeline parameters visible in the Azure DevOps UI. +parameters: + + # The agent image to use for the build. This must exist in both the ADO-1ES-Pool and + # ADO-CI-1ES-Pool agent pools. + - name: agentImage + displayName: Agent Image + type: string + default: ADO-UB24 + values: + - ADO-UB24 + - ADO-Win25 + + # The build configuration to use, either Debug or Release. + - name: buildConfiguration + displayName: Build Configuration + type: string + default: Release + values: + - Debug + - Release + + # True to enable debug steps and output. + - name: debug + displayName: Enable debug output + type: boolean + default: false + + # The verbosity level of dotnet CLI commands. + - name: dotnetVerbosity + displayName: dotnet CLI Verbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + +variables: + # Disable codesign validation injection for CI builds. + # + # TODO: Should we enable this for internal/main since those builds produce signed assemblies? + - name: runCodesignValidationInjection + value: false + + # Skip component governance detection for CI builds. + # + # TODO: This should never be skipped, should it? + #- name: skipComponentGovernanceDetection + # value: true + + # Whether this is an internal (ADO) build that should strong-name sign. + - name: isInternalBuild + value: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/internal/') }} + + # Package version suffix for CI builds. + - name: buildSuffix + value: ci + +jobs: + - job: pack_all_packages + displayName: Pack All Packages + + pool: + ${{ if eq(variables.isInternalBuild, 'True') }}: + name: ADO-1ES-Pool + ${{ else }}: + name: ADO-CI-1ES-Pool + demands: + - ImageOverride -equals ${{ parameters.agentImage }} + + steps: + + # Emit environment variables if debug is enabled. + - ${{ if eq(parameters.debug, true) }}: + - pwsh: 'Get-ChildItem Env: | Sort-Object Name' + displayName: '[Debug] Print Environment Variables' + + # Install the .NET SDK from global.json. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + debug: ${{ parameters.debug }} + + # Clean any pre-existing .nupkg / .snupkg files from the packages/ directory + # to ensure we only publish packages produced by this run. + - pwsh: | + Write-Host 'Cleaning packages/ directory...' + Remove-Item -Force "$(Build.SourcesDirectory)/packages/*.nupkg" -ErrorAction SilentlyContinue + Remove-Item -Force "$(Build.SourcesDirectory)/packages/*.snupkg" -ErrorAction SilentlyContinue + Write-Host 'Done.' + displayName: Clean packages/ directory + + # On internal/main, download the strong-name signing key and setup assembly signing. + - ${{ if eq(variables.isInternalBuild, 'True') }}: + - task: DownloadSecureFile@1 + displayName: Download Signing Key + inputs: + secureFile: netfxKeypair.snk + name: keyFile + + - pwsh: | + Write-Host "##vso[task.setvariable variable=signingKeyArg]-p:SigningKeyPath=`"$(keyFile.secureFilePath)`"" + displayName: Set Signing Key Argument + + # Run the Pack target via build.proj. + # On internal/main the signing key path is included via $(signingKeyArg). + - task: DotNetCoreCLI@2 + displayName: build.proj - Pack (ReferenceType=Package) + inputs: + command: build + projects: '$(Build.SourcesDirectory)/build.proj' + arguments: >- + -t:Pack + -p:Configuration=${{ parameters.buildConfiguration }} + -p:ReferenceType=Package + -p:BuildNumber="$(Build.BuildNumber)" + -p:BuildSuffix=$(buildSuffix) + $(signingKeyArg) + -verbosity:${{ parameters.dotnetVerbosity }} + + # List produced packages for diagnostics. + - pwsh: | + Write-Host 'Packages produced:' + Get-ChildItem "$(Build.SourcesDirectory)/packages/*.nupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length + Get-ChildItem "$(Build.SourcesDirectory)/packages/*.snupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length + displayName: List produced packages + + # Publish all .nupkg and .snupkg files from packages/ as a pipeline artifact. + - task: PublishPipelineArtifact@1 + displayName: Publish NuGet Packages + inputs: + targetPath: '$(Build.SourcesDirectory)/packages' + artifactName: Packages + publishLocation: pipeline From 24d7779dd8aa06e6c3118af59188b6e3f35c82d1 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 14 May 2026 15:45:10 -0300 Subject: [PATCH 2/6] Updated pool choice to use the Azure DevOps project name. --- eng/pipelines/ci/package/sqlclient-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index 1052ed3d33..f85391d62f 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -96,9 +96,9 @@ variables: #- name: skipComponentGovernanceDetection # value: true - # Whether this is an internal (ADO) build that should strong-name sign. + # Whether this is an internal (ADO.Net project) or public (Public project) build. - name: isInternalBuild - value: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/internal/') }} + value: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} # Package version suffix for CI builds. - name: buildSuffix From 52f60a1713e588f5eb1c29848ccaebd4defa34b1 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 14 May 2026 16:12:24 -0300 Subject: [PATCH 3/6] Add CI package pipeline for building and publishing NuGet packages --- eng/pipelines/ci/package/sqlclient-package.yml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index f85391d62f..563d8ca8bb 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -87,14 +87,8 @@ variables: # Disable codesign validation injection for CI builds. # # TODO: Should we enable this for internal/main since those builds produce signed assemblies? - - name: runCodesignValidationInjection - value: false - - # Skip component governance detection for CI builds. - # - # TODO: This should never be skipped, should it? - #- name: skipComponentGovernanceDetection - # value: true + #- name: runCodesignValidationInjection + # value: false # Whether this is an internal (ADO.Net project) or public (Public project) build. - name: isInternalBuild @@ -120,7 +114,8 @@ jobs: # Emit environment variables if debug is enabled. - ${{ if eq(parameters.debug, true) }}: - - pwsh: 'Get-ChildItem Env: | Sort-Object Name' + - pwsh: | + Get-ChildItem Env: | Sort-Object Name | Format-Table -AutoSize -Wrap displayName: '[Debug] Print Environment Variables' # Install the .NET SDK from global.json. @@ -168,8 +163,8 @@ jobs: # List produced packages for diagnostics. - pwsh: | Write-Host 'Packages produced:' - Get-ChildItem "$(Build.SourcesDirectory)/packages/*.nupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length - Get-ChildItem "$(Build.SourcesDirectory)/packages/*.snupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length + Get-ChildItem "$(Build.SourcesDirectory)/packages/*.nupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length -AutoSize -Wrap + Get-ChildItem "$(Build.SourcesDirectory)/packages/*.snupkg" -ErrorAction SilentlyContinue | Format-Table Name, Length -AutoSize -Wrap displayName: List produced packages # Publish all .nupkg and .snupkg files from packages/ as a pipeline artifact. From 8751e7843d0c75b25b63bdb779f3262f571db380 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 14 May 2026 16:25:07 -0300 Subject: [PATCH 4/6] Address Copilot review: declare signingKeyArg conditionally, remove dead code --- .../ci/package/sqlclient-package.yml | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index 563d8ca8bb..afc3388b1c 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -84,19 +84,17 @@ parameters: - diagnostic variables: - # Disable codesign validation injection for CI builds. - # - # TODO: Should we enable this for internal/main since those builds produce signed assemblies? - #- name: runCodesignValidationInjection - # value: false - # Whether this is an internal (ADO.Net project) or public (Public project) build. - name: isInternalBuild value: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} - # Package version suffix for CI builds. - - name: buildSuffix - value: ci + # Signing key argument passed to build.proj. On internal builds this references the secure file + # downloaded by DownloadSecureFile@1; on public builds it expands to empty. + - name: signingKeyArg + ${{ if eq(variables.isInternalBuild, 'True') }}: + value: '-p:SigningKeyPath="$(keyFile.secureFilePath)"' + ${{ else }}: + value: '' jobs: - job: pack_all_packages @@ -132,7 +130,7 @@ jobs: Write-Host 'Done.' displayName: Clean packages/ directory - # On internal/main, download the strong-name signing key and setup assembly signing. + # On internal builds, download the strong-name signing key. - ${{ if eq(variables.isInternalBuild, 'True') }}: - task: DownloadSecureFile@1 displayName: Download Signing Key @@ -140,12 +138,7 @@ jobs: secureFile: netfxKeypair.snk name: keyFile - - pwsh: | - Write-Host "##vso[task.setvariable variable=signingKeyArg]-p:SigningKeyPath=`"$(keyFile.secureFilePath)`"" - displayName: Set Signing Key Argument - # Run the Pack target via build.proj. - # On internal/main the signing key path is included via $(signingKeyArg). - task: DotNetCoreCLI@2 displayName: build.proj - Pack (ReferenceType=Package) inputs: @@ -156,7 +149,7 @@ jobs: -p:Configuration=${{ parameters.buildConfiguration }} -p:ReferenceType=Package -p:BuildNumber="$(Build.BuildNumber)" - -p:BuildSuffix=$(buildSuffix) + -p:BuildSuffix=ci $(signingKeyArg) -verbosity:${{ parameters.dotnetVerbosity }} From 583f875e12cf0880a64aec7af48dcea95be4d591 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 14 May 2026 16:26:19 -0300 Subject: [PATCH 5/6] Exclude the new CI pipeline files from PR checks. --- eng/pipelines/sqlclient-pr-package-ref-pipeline.yml | 1 + eng/pipelines/sqlclient-pr-project-ref-pipeline.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml b/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml index be7e2e9e3b..70a37e0fa7 100644 --- a/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml +++ b/eng/pipelines/sqlclient-pr-package-ref-pipeline.yml @@ -51,6 +51,7 @@ pr: - global.json - NuGet.config exclude: + - eng/pipelines/ci/* - eng/pipelines/kerberos/* - eng/pipelines/onebranch/* - eng/pipelines/stress/* diff --git a/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml b/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml index 30950ec21c..f777626c90 100644 --- a/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml +++ b/eng/pipelines/sqlclient-pr-project-ref-pipeline.yml @@ -51,6 +51,7 @@ pr: - global.json - NuGet.config exclude: + - eng/pipelines/ci/* - eng/pipelines/kerberos/* - eng/pipelines/onebranch/* - eng/pipelines/stress/* From c6bf797f4f209db382c236d121ab3c0bcca76d0f Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Wed, 20 May 2026 15:12:53 -0300 Subject: [PATCH 6/6] Address Copilot review: fix verbosity switch and boolean comparisons - Change -verbosity: to --verbosity for dotnet CLI consistency - Change isInternalBuild comparisons from string 'True' to boolean true --- eng/pipelines/ci/package/sqlclient-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index afc3388b1c..c907fd0219 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -91,7 +91,7 @@ variables: # Signing key argument passed to build.proj. On internal builds this references the secure file # downloaded by DownloadSecureFile@1; on public builds it expands to empty. - name: signingKeyArg - ${{ if eq(variables.isInternalBuild, 'True') }}: + ${{ if eq(variables.isInternalBuild, true) }}: value: '-p:SigningKeyPath="$(keyFile.secureFilePath)"' ${{ else }}: value: '' @@ -101,7 +101,7 @@ jobs: displayName: Pack All Packages pool: - ${{ if eq(variables.isInternalBuild, 'True') }}: + ${{ if eq(variables.isInternalBuild, true) }}: name: ADO-1ES-Pool ${{ else }}: name: ADO-CI-1ES-Pool @@ -131,7 +131,7 @@ jobs: displayName: Clean packages/ directory # On internal builds, download the strong-name signing key. - - ${{ if eq(variables.isInternalBuild, 'True') }}: + - ${{ if eq(variables.isInternalBuild, true) }}: - task: DownloadSecureFile@1 displayName: Download Signing Key inputs: @@ -151,7 +151,7 @@ jobs: -p:BuildNumber="$(Build.BuildNumber)" -p:BuildSuffix=ci $(signingKeyArg) - -verbosity:${{ parameters.dotnetVerbosity }} + --verbosity ${{ parameters.dotnetVerbosity }} # List produced packages for diagnostics. - pwsh: |