From e89f1e74ed32c73bb7dd408f7e1e69d925fa5686 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 12 Nov 2025 16:24:26 -0800 Subject: [PATCH 01/12] Add publish support in OneBranch Official pipeline --- .../common/templates/jobs/approval-job.yml | 40 ++++++ .../templates/jobs/publish-packages-job.yml | 60 +++++++++ .../common/templates/stages/release-stage.yml | 53 ++++++++ .../templates/steps/list-packages-step.yml | 14 +++ .../steps/publish-internal-feed-step.yml | 32 +++++ .../steps/publish-public-nuget-step.yml | 49 ++++++++ .../templates/steps/publish-symbols-step.yml | 115 +++++++----------- .../dotnet-sqlclient-signing-pipeline.yml | 54 ++++++++ 8 files changed, 349 insertions(+), 68 deletions(-) create mode 100644 eng/pipelines/common/templates/jobs/approval-job.yml create mode 100644 eng/pipelines/common/templates/jobs/publish-packages-job.yml create mode 100644 eng/pipelines/common/templates/stages/release-stage.yml create mode 100644 eng/pipelines/common/templates/steps/list-packages-step.yml create mode 100644 eng/pipelines/common/templates/steps/publish-internal-feed-step.yml create mode 100644 eng/pipelines/common/templates/steps/publish-public-nuget-step.yml diff --git a/eng/pipelines/common/templates/jobs/approval-job.yml b/eng/pipelines/common/templates/jobs/approval-job.yml new file mode 100644 index 0000000000..45dd00a05c --- /dev/null +++ b/eng/pipelines/common/templates/jobs/approval-job.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. # +################################################################################# +parameters: + - name: approvalAliases + type: string + - name: publishDestination + type: string + - name: dryRun + type: boolean + - name: isPreview + type: boolean + - name: publishSymbols + type: boolean + - name: nugetPackageVersion + type: string + - name: product + type: string + +jobs: +- job: AwaitApproval + displayName: 'Await Release Approval' + pool: server + steps: + - task: ManualValidation@0 + displayName: 'Manual Approval' + timeoutInMinutes: 4320 + inputs: + notifyUsers: ${{ parameters.approvalAliases }} + instructions: | + Release Checklist: + * Destination: ${{ parameters.publishDestination }} + * Preview build: ${{ parameters.isPreview }} + * Dry run: ${{ parameters.dryRun }} + * Symbols: ${{ parameters.publishSymbols }} + * NuGet package version: ${{ parameters.nugetPackageVersion }} + * Product: ${{ parameters.product }} + Approve to continue or Reject to abort. diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml new file mode 100644 index 0000000000..779591f896 --- /dev/null +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -0,0 +1,60 @@ +################################################################################# +# 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: publishDestination + type: string + - name: dryRun + type: boolean + - name: internalFeedSource + type: string + - name: publicNuGetSource + type: string + - name: publishSymbols + type: boolean + - name: packageFolderName + type: string + - name: nugetPackageVersion + type: string + - name: product + type: string + +jobs: +- job: PublishPackages + displayName: 'Publish Packages' + dependsOn: AwaitApproval + condition: succeeded() + pool: + vmImage: 'ubuntu-latest' + steps: + - task: DownloadPipelineArtifact@2 + displayName: 'Download Signed Packages' + inputs: + buildType: current + artifactName: ${{ parameters.packageFolderName }} + targetPath: $(Pipeline.Workspace)/release/packages + - script: | + echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" + displayName: 'Echo NuGet Package Version' + - template: ../steps/list-packages-step.yml + parameters: + path: $(Pipeline.Workspace)/release/packages + - ${{ if ne(parameters.publishDestination, 'Public') }}: + - template: ../steps/publish-internal-feed-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + internalFeedSource: ${{ parameters.internalFeedSource }} + - ${{ if eq(parameters.publishDestination, 'Public') }}: + - template: ../steps/publish-public-nuget-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + - ${{ if parameters.publishSymbols }}: + - template: ../steps/publish-symbols-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + publishSymbols: ${{ parameters.publishSymbols }} + symbolsArtifactName: ${{ parameters.product }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.nugetPackageVersion }}_$(System.TimelineId) + product: ${{ parameters.product }} diff --git a/eng/pipelines/common/templates/stages/release-stage.yml b/eng/pipelines/common/templates/stages/release-stage.yml new file mode 100644 index 0000000000..a61115fa3b --- /dev/null +++ b/eng/pipelines/common/templates/stages/release-stage.yml @@ -0,0 +1,53 @@ +################################################################################# +# 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: runRelease + type: boolean + - name: publishDestination + type: string + - name: dryRun + type: boolean + - name: approvalAliases + type: string + - name: internalFeedSource + type: string + - name: publicNuGetSource + type: string + - name: publishSymbols + type: boolean + - name: isPreview + type: boolean + - name: product + type: string + - name: nugetPackageVersion + type: string + - name: packageFolderName + type: string + +stages: +- stage: releaseMDS + displayName: 'Release (Manual)' + condition: and(succeeded(), eq(variables['Build.Reason'],'Manual'), eq(${{ parameters.runRelease }}, true)) + jobs: + - template: ../jobs/approval-job.yml + parameters: + approvalAliases: ${{ parameters.approvalAliases }} + publishDestination: ${{ parameters.publishDestination }} + dryRun: ${{ parameters.dryRun }} + isPreview: ${{ parameters.isPreview }} + publishSymbols: ${{ parameters.publishSymbols }} + nugetPackageVersion: ${{ parameters.nugetPackageVersion }} + product: ${{ parameters.product }} + - template: ../jobs/publish-packages-job.yml + parameters: + publishDestination: ${{ parameters.publishDestination }} + dryRun: ${{ parameters.dryRun }} + internalFeedSource: ${{ parameters.internalFeedSource }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + publishSymbols: ${{ parameters.publishSymbols }} + packageFolderName: ${{ parameters.packageFolderName }} + nugetPackageVersion: ${{ parameters.nugetPackageVersion }} + product: ${{ parameters.product }} diff --git a/eng/pipelines/common/templates/steps/list-packages-step.yml b/eng/pipelines/common/templates/steps/list-packages-step.yml new file mode 100644 index 0000000000..1d6249a8ac --- /dev/null +++ b/eng/pipelines/common/templates/steps/list-packages-step.yml @@ -0,0 +1,14 @@ +################################################################################# +# 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: path + type: string + +steps: +- script: | + echo "Packages in ${{ parameters.path }}:" + find "${{ parameters.path }}" -name "*.nupkg" -maxdepth 3 + displayName: 'List Packages' diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml new file mode 100644 index 0000000000..f478d8e7ae --- /dev/null +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -0,0 +1,32 @@ +################################################################################# +# 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: dryRun + type: boolean + - name: internalFeedSource + type: string + - name: packagesGlob + type: string + default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' + +steps: +- script: | + set -e + SRC='${{ parameters.internalFeedSource }}' + if [ -z "$SRC" ]; then + echo "Internal feed source parameter not set." + exit 1 + fi + if [ "${{ parameters.dryRun }}" = "true" ]; then + echo "[DRY RUN] Would push to $SRC" + find "${{ parameters.packagesGlob }}" -name "*.nupkg" + exit 0 + fi + for f in $(find "${{ parameters.packagesGlob }}" -name "*.nupkg"); do + echo "Push $f" + dotnet nuget push --source "$SRC" --api-key az "$f" + done + displayName: 'Publish to Internal Feed' diff --git a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml new file mode 100644 index 0000000000..719aa2d0e9 --- /dev/null +++ b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml @@ -0,0 +1,49 @@ +################################################################################# +# 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: dryRun + type: boolean + - name: publicNuGetSource + type: string + - name: nugetServiceConnection + type: string + default: 'ADO Nuget Org Connection' + - name: packagesGlob + type: string + default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' + +steps: +- task: NuGetToolInstaller@1 + displayName: 'Install Latest Nuget' + inputs: + checkLatest: true +- script: | + echo "[DRY RUN] Listing packages targeted for push to: ${{ parameters.publicNuGetSource }}" + echo "Using glob pattern: ${{ parameters.packagesGlob }}" + # Derive directory and filename pattern from the glob for a precise find (handles nested patterns minimally) + glob='${{ parameters.packagesGlob }}' + dir="${glob%/*}" + name="${glob##*/}" + echo "Resolved directory: $dir" + echo "Filename pattern: $name" + if [ -d "$dir" ]; then + echo "Matched files:" || true + # Limit depth to avoid traversing unrelated trees; adjust if patterns intentionally include deeper globs + find "$dir" -maxdepth 2 -type f -name "$name" -print || true + else + echo "Directory does not exist yet: $dir" + fi + displayName: 'Dry Run - List Packages' + condition: and(succeeded(), eq(${{ parameters.dryRun }}, true)) + +- task: NuGetCommand@2 + displayName: 'Push to Nuget.org' + condition: and(succeeded(), eq(${{ parameters.dryRun }}, false)) + inputs: + command: push + packagesToPush: '${{ parameters.packagesGlob }}' + nuGetFeedType: external + publishFeedCredentials: '${{ parameters.nugetServiceConnection }}' diff --git a/eng/pipelines/common/templates/steps/publish-symbols-step.yml b/eng/pipelines/common/templates/steps/publish-symbols-step.yml index 5f8d2e6a7d..aa40e0480a 100644 --- a/eng/pipelines/common/templates/steps/publish-symbols-step.yml +++ b/eng/pipelines/common/templates/steps/publish-symbols-step.yml @@ -9,51 +9,48 @@ parameters: - name: SymAccount type: string default: 'SqlClientDrivers' - - name: publishSymbols - type: string - + type: boolean + default: false - name: symbolsVersion type: string - default: '$(NuGetPackageVersion)' - + default: '$(NugetPackageVersion)' - name: symbolServer type: string default: '$(SymbolServer)' - - name: symbolTokenUri type: string default: '$(SymbolTokenUri)' - - name: symbolsArtifactName type: string - - name: publishToServers type: object - default: + default: internal: true public: true - - name: referenceType default: project values: - - project - - package - + - project + - package - name: product default: MDS values: - - MDS - - MSS + - MDS + - MSS + - AKV + - name: azureSubscription + type: string + default: 'Symbols publishing Workload Identity federation service-ADO.Net' steps: - powershell: 'Write-Host "##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{parameters.SymAccount}}"' displayName: 'Update Symbol.AccountName with ${{parameters.SymAccount}}' - condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + condition: and(succeeded(), eq(parameters.publishSymbols, true)) -- ${{ if eq(parameters.product, 'MDS') }}: +- ${{ if and(eq(parameters.publishSymbols, true), eq(parameters.product, 'MDS')) }}: - task: PublishSymbols@2 - displayName: 'Upload symbols to ${{parameters.SymAccount }} org' + displayName: 'Upload MDS symbols to ${{parameters.SymAccount }} org' inputs: SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\${{parameters.referenceType }}\bin' SearchPattern: | @@ -68,63 +65,45 @@ steps: SymbolsArtifactName: ${{parameters.symbolsArtifactName }} Pat: $(System.AccessToken) condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + - task: AzureCLI@2 + displayName: 'Publish MDS symbols' + condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + inputs: + azureSubscription: ${{ parameters.azureSubscription }} + scriptType: ps + scriptLocation: inlineScript + inlineScript: | + $publishToInternalServer = "${{parameters.publishToServers.internal }}".ToLower() + $publishToPublicServer = "${{parameters.publishToServers.public }}".ToLower() -- task: AzureCLI@2 - displayName: 'Publish symbols' - condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) - 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: ${{parameters.symbolsArtifactName }}" - echo "Publish to internal server: $publishToInternalServer" - echo "Publish to public server: $publishToPublicServer" + echo "Publishing request name: ${{parameters.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" + $symbolServer = "${{parameters.symbolServer }}" + $tokenUri = "${{parameters.symbolTokenUri }}" + $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 + $symbolPublishingToken = az account get-access-token --resource $tokenUri --query accessToken -o tsv - echo "> 1.Symbol publishing token acquired." + echo "> 1.Symbol publishing token acquired." - echo "Registering the request name ..." - $requestName = "${{parameters.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 "Registering the request name ..." + $requestName = "${{parameters.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 "> 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 "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." + 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 ..." + 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" - 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" + echo "PublishingStatus"; echo "-----------------"; echo "0 NotRequested"; echo "1 Submitted"; echo "2 Processing"; echo "3 Completed" + echo "PublishingResult"; echo "-----------------"; echo "0 Pending"; echo "1 Succeeded"; echo "2 Failed"; echo "3 Cancelled" diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index e104b99193..064d3bfa91 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -68,6 +68,45 @@ parameters: # parameters are shown up in ADO UI in a build queue time type: string default: 90 +# Manual Release Parameters +# Release stage runs ONLY when build is manually queued AND runRelease = true. +- name: runRelease + displayName: 'Run manual release stage' + type: boolean + default: false + +- name: publishDestination + displayName: 'Publish destination' + type: string + default: Internal + values: + - Internal + - Public + +- name: dryRun + displayName: 'Dry run (no publish)' + type: boolean + default: false + +- name: internalFeedSource + displayName: 'Internal feed source URL' + type: string + default: '' + +- name: publicNuGetSource + displayName: 'Public NuGet source URL' + type: string + default: 'https://api.nuget.org/v3/index.json' + +- name: product + displayName: 'Product code (mds|akv)' + type: string + default: 'mds' + values: + - mds + - mss + - akv + variables: - template: /eng/pipelines/libraries/variables.yml@self - name: packageFolderName @@ -174,3 +213,18 @@ extends: # artifact: $(packageFolderName) # patterns: '**/*.nupkg' # displayName: 'Download NuGet Package' + + # Manual Release Stage (templated) + - template: eng/pipelines/common/templates/stages/release-stage.yml@self + parameters: + runRelease: ${{ parameters.runRelease }} + publishDestination: ${{ parameters.publishDestination }} + dryRun: ${{ parameters.dryRun }} + approvalAliases: '[ADO.Net]\\SqlClient Admins' + internalFeedSource: ${{ parameters.internalFeedSource }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + publishSymbols: ${{ parameters.publishSymbols }} + isPreview: ${{ parameters.isPreview }} + packageFolderName: $(packageFolderName) + nugetPackageVersion: $(NugetPackageVersion) + product: ${{ parameters.product }} From dd2145681fdf0ca33b7a26c646291211025ad40d Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 12 Nov 2025 20:26:14 -0800 Subject: [PATCH 02/12] Improvements --- .../templates/jobs/publish-packages-job.yml | 5 +++-- .../steps/publish-internal-feed-step.yml | 18 +++++++++++++++--- .../steps/publish-public-nuget-step.yml | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml index 779591f896..78028654e3 100644 --- a/eng/pipelines/common/templates/jobs/publish-packages-job.yml +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -46,15 +46,16 @@ jobs: parameters: dryRun: ${{ parameters.dryRun }} internalFeedSource: ${{ parameters.internalFeedSource }} + packagesGlob: $(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg - ${{ if eq(parameters.publishDestination, 'Public') }}: - template: ../steps/publish-public-nuget-step.yml parameters: dryRun: ${{ parameters.dryRun }} publicNuGetSource: ${{ parameters.publicNuGetSource }} - - ${{ if parameters.publishSymbols }}: + packagesGlob: $(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg + - ${{ if and(parameters.publishSymbols, ne(parameters.dryRun, true)) }}: - template: ../steps/publish-symbols-step.yml parameters: - dryRun: ${{ parameters.dryRun }} publishSymbols: ${{ parameters.publishSymbols }} symbolsArtifactName: ${{ parameters.product }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.nugetPackageVersion }}_$(System.TimelineId) product: ${{ parameters.product }} diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index f478d8e7ae..1cf65e2716 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -21,9 +21,21 @@ steps: exit 1 fi if [ "${{ parameters.dryRun }}" = "true" ]; then - echo "[DRY RUN] Would push to $SRC" - find "${{ parameters.packagesGlob }}" -name "*.nupkg" - exit 0 + echo "[DRY RUN] Listing packages targeted for push to: ${{ parameters.publicNuGetSource }}" + echo "Using glob pattern: ${{ parameters.packagesGlob }}" + # Derive directory and filename pattern from the glob for a precise find (handles nested patterns minimally) + glob='${{ parameters.packagesGlob }}' + dir="${glob%/*}" + name="${glob##*/}" + echo "Resolved directory: $dir" + echo "Filename pattern: $name" + if [ -d "$dir" ]; then + echo "Matched files:" || true + # Print all matched files to identify what would be pushed + find "$dir" -type f -name "$name" -print || true + else + echo "Directory does not exist yet: $dir" + fi fi for f in $(find "${{ parameters.packagesGlob }}" -name "*.nupkg"); do echo "Push $f" diff --git a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml index 719aa2d0e9..60dab98fb3 100644 --- a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml +++ b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml @@ -31,8 +31,8 @@ steps: echo "Filename pattern: $name" if [ -d "$dir" ]; then echo "Matched files:" || true - # Limit depth to avoid traversing unrelated trees; adjust if patterns intentionally include deeper globs - find "$dir" -maxdepth 2 -type f -name "$name" -print || true + # Print all matched files to identify what would be pushed + find "$dir" -type f -name "$name" -print || true else echo "Directory does not exist yet: $dir" fi From 02cbe584311dcecb357e4890f3aea23d0e8f3b6a Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 12 Nov 2025 21:01:07 -0800 Subject: [PATCH 03/12] Cleanups --- .../common/templates/jobs/approval-job.yml | 9 +++++++- .../templates/jobs/publish-packages-job.yml | 10 +++++--- .../common/templates/stages/release-stage.yml | 13 +++++++++++ .../templates/steps/list-packages-step.yml | 14 ----------- .../templates/steps/publish-symbols-step.yml | 23 +++++++++++++------ .../dotnet-sqlclient-signing-pipeline.yml | 10 ++++---- 6 files changed, 49 insertions(+), 30 deletions(-) delete mode 100644 eng/pipelines/common/templates/steps/list-packages-step.yml diff --git a/eng/pipelines/common/templates/jobs/approval-job.yml b/eng/pipelines/common/templates/jobs/approval-job.yml index 45dd00a05c..051a3875ff 100644 --- a/eng/pipelines/common/templates/jobs/approval-job.yml +++ b/eng/pipelines/common/templates/jobs/approval-job.yml @@ -6,16 +6,23 @@ parameters: - name: approvalAliases type: string + default: '[ADO.Net]\\SqlClient Admins' + - name: publishDestination type: string + - name: dryRun type: boolean + - name: isPreview type: boolean + - name: publishSymbols type: boolean + - name: nugetPackageVersion type: string + - name: product type: string @@ -26,7 +33,7 @@ jobs: steps: - task: ManualValidation@0 displayName: 'Manual Approval' - timeoutInMinutes: 4320 + timeoutInMinutes: 4320 # 3 days inputs: notifyUsers: ${{ parameters.approvalAliases }} instructions: | diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml index 78028654e3..d36932a6d6 100644 --- a/eng/pipelines/common/templates/jobs/publish-packages-job.yml +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -6,18 +6,25 @@ parameters: - name: publishDestination type: string + - name: dryRun type: boolean + - name: internalFeedSource type: string + - name: publicNuGetSource type: string + - name: publishSymbols type: boolean + - name: packageFolderName type: string + - name: nugetPackageVersion type: string + - name: product type: string @@ -38,9 +45,6 @@ jobs: - script: | echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" displayName: 'Echo NuGet Package Version' - - template: ../steps/list-packages-step.yml - parameters: - path: $(Pipeline.Workspace)/release/packages - ${{ if ne(parameters.publishDestination, 'Public') }}: - template: ../steps/publish-internal-feed-step.yml parameters: diff --git a/eng/pipelines/common/templates/stages/release-stage.yml b/eng/pipelines/common/templates/stages/release-stage.yml index a61115fa3b..2fa4d891a6 100644 --- a/eng/pipelines/common/templates/stages/release-stage.yml +++ b/eng/pipelines/common/templates/stages/release-stage.yml @@ -6,24 +6,37 @@ parameters: - name: runRelease type: boolean + default: false + - name: publishDestination type: string + - name: dryRun type: boolean + default: false + - name: approvalAliases type: string + - name: internalFeedSource type: string + - name: publicNuGetSource type: string + - name: publishSymbols type: boolean + default: false + - name: isPreview type: boolean + - name: product type: string + - name: nugetPackageVersion type: string + - name: packageFolderName type: string diff --git a/eng/pipelines/common/templates/steps/list-packages-step.yml b/eng/pipelines/common/templates/steps/list-packages-step.yml deleted file mode 100644 index 1d6249a8ac..0000000000 --- a/eng/pipelines/common/templates/steps/list-packages-step.yml +++ /dev/null @@ -1,14 +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: path - type: string - -steps: -- script: | - echo "Packages in ${{ parameters.path }}:" - find "${{ parameters.path }}" -name "*.nupkg" -maxdepth 3 - displayName: 'List Packages' diff --git a/eng/pipelines/common/templates/steps/publish-symbols-step.yml b/eng/pipelines/common/templates/steps/publish-symbols-step.yml index aa40e0480a..d8eae8837a 100644 --- a/eng/pipelines/common/templates/steps/publish-symbols-step.yml +++ b/eng/pipelines/common/templates/steps/publish-symbols-step.yml @@ -9,36 +9,45 @@ parameters: - name: SymAccount type: string default: 'SqlClientDrivers' + - name: publishSymbols type: boolean default: false + - name: symbolsVersion type: string default: '$(NugetPackageVersion)' + - name: symbolServer type: string default: '$(SymbolServer)' + - name: symbolTokenUri type: string default: '$(SymbolTokenUri)' + - name: symbolsArtifactName type: string + - name: publishToServers type: object default: internal: true public: true + - name: referenceType default: project values: - - project - - package + - project + - package + - name: product default: MDS values: - - MDS - - MSS - - AKV + - MDS + - MSS + - AKV + - name: azureSubscription type: string default: 'Symbols publishing Workload Identity federation service-ADO.Net' @@ -64,10 +73,10 @@ steps: SymbolsVersion: ${{parameters.symbolsVersion }} SymbolsArtifactName: ${{parameters.symbolsArtifactName }} Pat: $(System.AccessToken) - condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + condition: and(succeeded(), eq(parameters.publishSymbols, true)) - task: AzureCLI@2 displayName: 'Publish MDS symbols' - condition: and(succeeded(), ${{ eq(parameters.publishSymbols, 'true') }}) + condition: and(succeeded(), eq(parameters.publishSymbols, true)) inputs: azureSubscription: ${{ parameters.azureSubscription }} scriptType: ps diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index 064d3bfa91..ba33cdf50d 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -99,13 +99,13 @@ parameters: # parameters are shown up in ADO UI in a build queue time default: 'https://api.nuget.org/v3/index.json' - name: product - displayName: 'Product code (mds|akv)' + displayName: 'Product code (MDS|MSS|AKV)' type: string - default: 'mds' + default: 'MDS' values: - - mds - - mss - - akv + - MDS + - MSS + - AKV variables: - template: /eng/pipelines/libraries/variables.yml@self From a693ea40e482da392308029d4e3c7a564e9ccd72 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 12 Nov 2025 21:02:51 -0800 Subject: [PATCH 04/12] Minor touch-ups --- .../common/templates/steps/publish-internal-feed-step.yml | 2 ++ .../common/templates/steps/publish-public-nuget-step.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index 1cf65e2716..8ebfe9f74a 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -6,8 +6,10 @@ parameters: - name: dryRun type: boolean + - name: internalFeedSource type: string + - name: packagesGlob type: string default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' diff --git a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml index 60dab98fb3..8c827ec93f 100644 --- a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml +++ b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml @@ -6,11 +6,14 @@ parameters: - name: dryRun type: boolean + - name: publicNuGetSource type: string + - name: nugetServiceConnection type: string default: 'ADO Nuget Org Connection' + - name: packagesGlob type: string default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' From ccc9259dbe3db87a58a11106012da44623408931 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 10 Dec 2025 22:33:57 -0800 Subject: [PATCH 05/12] Convert inline script to ps script file --- .../steps/publish-internal-feed-step.yml | 32 ++------ tools/scripts/downloadLatestNuget.ps1 | 3 +- tools/scripts/publishPackagesToFeed.ps1 | 81 +++++++++++++++++++ 3 files changed, 87 insertions(+), 29 deletions(-) create mode 100644 tools/scripts/publishPackagesToFeed.ps1 diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index 8ebfe9f74a..efff1c31a2 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -6,6 +6,7 @@ parameters: - name: dryRun type: boolean + default: true - name: internalFeedSource type: string @@ -16,31 +17,8 @@ parameters: steps: - script: | - set -e - SRC='${{ parameters.internalFeedSource }}' - if [ -z "$SRC" ]; then - echo "Internal feed source parameter not set." - exit 1 - fi - if [ "${{ parameters.dryRun }}" = "true" ]; then - echo "[DRY RUN] Listing packages targeted for push to: ${{ parameters.publicNuGetSource }}" - echo "Using glob pattern: ${{ parameters.packagesGlob }}" - # Derive directory and filename pattern from the glob for a precise find (handles nested patterns minimally) - glob='${{ parameters.packagesGlob }}' - dir="${glob%/*}" - name="${glob##*/}" - echo "Resolved directory: $dir" - echo "Filename pattern: $name" - if [ -d "$dir" ]; then - echo "Matched files:" || true - # Print all matched files to identify what would be pushed - find "$dir" -type f -name "$name" -print || true - else - echo "Directory does not exist yet: $dir" - fi - fi - for f in $(find "${{ parameters.packagesGlob }}" -name "*.nupkg"); do - echo "Push $f" - dotnet nuget push --source "$SRC" --api-key az "$f" - done + pwsh ./tools/scripts/publishPackagesToFeed.ps1 ` + -dryRun ${{ parameters.dryRun }} ` + -internalFeedSource '${{ parameters.internalFeedSource }}' ` + -packagesGlob '${{ parameters.packagesGlob }}' displayName: 'Publish to Internal Feed' diff --git a/tools/scripts/downloadLatestNuget.ps1 b/tools/scripts/downloadLatestNuget.ps1 index faddf3bb09..d978897873 100644 --- a/tools/scripts/downloadLatestNuget.ps1 +++ b/tools/scripts/downloadLatestNuget.ps1 @@ -2,7 +2,6 @@ # The .NET Foundation licenses this file to you under the MIT license. # See the LICENSE file in the project root for more information. # Script: downloadLatestNuget.ps1 -# Author: Keerat Singh # Date: 07-Dec-2018 # Comments: This script downloads the latest NuGet Binary. # @@ -24,4 +23,4 @@ Function DownloadLatestNuget() Write-Output "Destination: $nugetDestPath" Start-BitsTransfer -Source $nugetSrcPath -Destination $nugetDestPath\nuget.exe } -DownloadLatestNuget \ No newline at end of file +DownloadLatestNuget diff --git a/tools/scripts/publishPackagesToFeed.ps1 b/tools/scripts/publishPackagesToFeed.ps1 new file mode 100644 index 0000000000..1b70dfd9db --- /dev/null +++ b/tools/scripts/publishPackagesToFeed.ps1 @@ -0,0 +1,81 @@ +# 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. + +# Script: publishPackagesToFeed.ps1 +# Date: 10-12-2025 +# Comments: This script publishes packages to an internal Azure DevOps Feed. + +param( + [bool]$dryRun = $true, + [string]$internalFeedSource, + [string]$packagesGlob = "artifacts/packages/**/*.nupkg" +) + +Function PublishToInternalFeed() { + $SRC = $internalFeedSource + + if ([string]::IsNullOrEmpty($SRC)) { + Write-Host "Internal feed source parameter not set." -ForegroundColor Red + exit 1 + } + + Write-Host "[DRY RUN] Listing packages targeted for push to: $internalFeedSource" -ForegroundColor Cyan + Write-Host "Using glob pattern: $packagesGlob" -ForegroundColor Cyan + + # Parse the glob pattern to extract directory and filename pattern + $glob = $packagesGlob + $lastSlashIndex = $glob.LastIndexOf('/') + + if ($lastSlashIndex -ge 0) { + $dir = $glob.Substring(0, $lastSlashIndex) + $namePattern = $glob.Substring($lastSlashIndex + 1) + } else { + $dir = "." + $namePattern = $glob + } + + # Handle ** wildcard for recursive search + $recurse = $dir -like '*/**' + if ($recurse) { + $dir = $dir -replace '/?\*\*/?', '' + } + + Write-Host "Resolved directory: $dir" -ForegroundColor Yellow + Write-Host "Filename pattern: $namePattern" -ForegroundColor Yellow + + if (Test-Path $dir -PathType Container) { + Write-Host "Matched files:" -ForegroundColor Green + + # Find matching .nupkg files + $packages = Get-ChildItem -Path $dir -Filter "*.nupkg" -Recurse:$recurse -File -ErrorAction SilentlyContinue + + if ($packages) { + foreach ($package in $packages) { + Write-Host " - $($package.FullName)" -ForegroundColor Gray + } + + if (-not $dryRun) { + Write-Host "`nPushing packages to feed..." -ForegroundColor Cyan + foreach ($package in $packages) { + Write-Host "Pushing package: $($package.FullName)" -ForegroundColor Yellow + dotnet nuget push $package.FullName --source $SRC --api-key az + + if ($LASTEXITCODE -ne 0) { + Write-Host "Failed to push package: $($package.FullName)" -ForegroundColor Red + } else { + Write-Host "Successfully pushed: $($package.Name)" -ForegroundColor Green + } + } + } else { + Write-Host "`n[DRY RUN] No packages were pushed. Set -dryRun `$false to push." -ForegroundColor Yellow + } + } else { + Write-Host "No .nupkg files found matching the pattern." -ForegroundColor Yellow + } + } else { + Write-Host "Directory does not exist: $dir" -ForegroundColor Red + } +} + +PublishToInternalFeed From adae0fadd861aa17e017535ccb6507a302a7463c Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 10 Dec 2025 23:24:19 -0800 Subject: [PATCH 06/12] More changes --- .../common/templates/jobs/approval-job.yml | 47 ------------------ .../templates/jobs/publish-packages-job.yml | 48 +++++++++++++++++-- .../common/templates/stages/release-stage.yml | 25 ++++++---- .../steps/publish-internal-feed-step.yml | 1 - .../steps/publish-public-nuget-step.yml | 4 +- .../dotnet-sqlclient-signing-pipeline.yml | 12 ++++- ...Feed.ps1 => publishPackagesToAzDOFeed.ps1} | 2 +- 7 files changed, 74 insertions(+), 65 deletions(-) delete mode 100644 eng/pipelines/common/templates/jobs/approval-job.yml rename tools/scripts/{publishPackagesToFeed.ps1 => publishPackagesToAzDOFeed.ps1} (98%) diff --git a/eng/pipelines/common/templates/jobs/approval-job.yml b/eng/pipelines/common/templates/jobs/approval-job.yml deleted file mode 100644 index 051a3875ff..0000000000 --- a/eng/pipelines/common/templates/jobs/approval-job.yml +++ /dev/null @@ -1,47 +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: approvalAliases - type: string - default: '[ADO.Net]\\SqlClient Admins' - - - name: publishDestination - type: string - - - name: dryRun - type: boolean - - - name: isPreview - type: boolean - - - name: publishSymbols - type: boolean - - - name: nugetPackageVersion - type: string - - - name: product - type: string - -jobs: -- job: AwaitApproval - displayName: 'Await Release Approval' - pool: server - steps: - - task: ManualValidation@0 - displayName: 'Manual Approval' - timeoutInMinutes: 4320 # 3 days - inputs: - notifyUsers: ${{ parameters.approvalAliases }} - instructions: | - Release Checklist: - * Destination: ${{ parameters.publishDestination }} - * Preview build: ${{ parameters.isPreview }} - * Dry run: ${{ parameters.dryRun }} - * Symbols: ${{ parameters.publishSymbols }} - * NuGet package version: ${{ parameters.nugetPackageVersion }} - * Product: ${{ parameters.product }} - Approve to continue or Reject to abort. diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml index d36932a6d6..985deecbc8 100644 --- a/eng/pipelines/common/templates/jobs/publish-packages-job.yml +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -4,33 +4,71 @@ # See the LICENSE file in the project root for more information. # ################################################################################# parameters: + # Approval aliases for manual validation before publishing packages + - name: approvalAliases + type: string + default: '[ADO.Net]\\SqlClient Admins' + + # Where to publish the packages: 'Internal' or 'Public' feed - name: publishDestination type: string + # Boolean value to indicate whether to perform a dry run or actual publish - name: dryRun type: boolean + # Boolean value to indicate if the build is a preview release build + - name: isPreview + type: boolean + + # Internal feed source URL for publishing packages to Azure DevOps Feed - name: internalFeedSource type: string + # Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource type: string + # Boolean value to indicate whether to publish symbols - name: publishSymbols type: boolean + # Name of the folder containing the packages to be published - name: packageFolderName type: string + # NuGet package version to be published - name: nugetPackageVersion type: string + # Product name associated with the packages - name: product type: string jobs: +- job: AwaitApproval + displayName: 'Await Release Approval' + pool: server + steps: + - task: ManualValidation@0 + displayName: 'Manual Approval' + timeoutInMinutes: 4320 # 3 days + inputs: + notifyUsers: ${{ parameters.approvalAliases }} + instructions: | + Release Checklist: + * Destination: ${{ parameters.publishDestination }} + * Preview build: ${{ parameters.isPreview }} + * Dry run: ${{ parameters.dryRun }} + * Symbols: ${{ parameters.publishSymbols }} + * NuGet package version: ${{ parameters.nugetPackageVersion }} + * Product: ${{ parameters.product }} + Approve to continue or Reject to abort. + - job: PublishPackages displayName: 'Publish Packages' + variables: + - targetDownloadPath: '$(Pipeline.Workspace)/release/packages' dependsOn: AwaitApproval condition: succeeded() pool: @@ -41,22 +79,26 @@ jobs: inputs: buildType: current artifactName: ${{ parameters.packageFolderName }} - targetPath: $(Pipeline.Workspace)/release/packages + targetPath: ${{ variables.targetDownloadPath }} - script: | echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" + echo "Downloaded signed packages to: ${{ variables.targetDownloadPath }}" displayName: 'Echo NuGet Package Version' + # Push to Internal Feed if publishDestination is not 'Public' - ${{ if ne(parameters.publishDestination, 'Public') }}: - template: ../steps/publish-internal-feed-step.yml parameters: dryRun: ${{ parameters.dryRun }} internalFeedSource: ${{ parameters.internalFeedSource }} - packagesGlob: $(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg + packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg + # Push to Public NuGet Feed if publishDestination is 'Public' - ${{ if eq(parameters.publishDestination, 'Public') }}: - template: ../steps/publish-public-nuget-step.yml parameters: dryRun: ${{ parameters.dryRun }} publicNuGetSource: ${{ parameters.publicNuGetSource }} - packagesGlob: $(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg + packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg + # Publish Symbols if publishSymbols is true and is not a dry run - ${{ if and(parameters.publishSymbols, ne(parameters.dryRun, true)) }}: - template: ../steps/publish-symbols-step.yml parameters: diff --git a/eng/pipelines/common/templates/stages/release-stage.yml b/eng/pipelines/common/templates/stages/release-stage.yml index 2fa4d891a6..2171c4b0de 100644 --- a/eng/pipelines/common/templates/stages/release-stage.yml +++ b/eng/pipelines/common/templates/stages/release-stage.yml @@ -4,39 +4,50 @@ # See the LICENSE file in the project root for more information. # ################################################################################# parameters: + # Boolean value to indicate whether to run the release stage - name: runRelease type: boolean default: false + # Where to publish the packages: 'Internal' or 'Public' feed - name: publishDestination type: string + # Boolean value to indicate whether to perform a dry run or actual publish - name: dryRun type: boolean - default: false + default: true + # Approval aliases for manual validation before publishing packages - name: approvalAliases type: string + # Internal feed source URL for publishing packages to Azure DevOps Feed - name: internalFeedSource type: string + # Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource type: string + # Boolean value to indicate whether to publish symbols - name: publishSymbols type: boolean default: false + # Boolean value to indicate if the build is a preview release build - name: isPreview type: boolean + # Product name associated with the packages - name: product type: string - + + # NuGet package version to be published - name: nugetPackageVersion type: string + # Name of the folder containing the packages to be published - name: packageFolderName type: string @@ -45,22 +56,16 @@ stages: displayName: 'Release (Manual)' condition: and(succeeded(), eq(variables['Build.Reason'],'Manual'), eq(${{ parameters.runRelease }}, true)) jobs: - - template: ../jobs/approval-job.yml + - template: ../jobs/publish-packages-job.yml parameters: approvalAliases: ${{ parameters.approvalAliases }} publishDestination: ${{ parameters.publishDestination }} dryRun: ${{ parameters.dryRun }} isPreview: ${{ parameters.isPreview }} - publishSymbols: ${{ parameters.publishSymbols }} - nugetPackageVersion: ${{ parameters.nugetPackageVersion }} - product: ${{ parameters.product }} - - template: ../jobs/publish-packages-job.yml - parameters: - publishDestination: ${{ parameters.publishDestination }} - dryRun: ${{ parameters.dryRun }} internalFeedSource: ${{ parameters.internalFeedSource }} publicNuGetSource: ${{ parameters.publicNuGetSource }} publishSymbols: ${{ parameters.publishSymbols }} packageFolderName: ${{ parameters.packageFolderName }} nugetPackageVersion: ${{ parameters.nugetPackageVersion }} product: ${{ parameters.product }} + diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index efff1c31a2..1ce616bc30 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -13,7 +13,6 @@ parameters: - name: packagesGlob type: string - default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' steps: - script: | diff --git a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml index 8c827ec93f..27c0015039 100644 --- a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml +++ b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml @@ -6,6 +6,7 @@ parameters: - name: dryRun type: boolean + default: true - name: publicNuGetSource type: string @@ -16,8 +17,7 @@ parameters: - name: packagesGlob type: string - default: '$(System.DefaultWorkingDirectory)/_dotnet-sqlclient-Official/drop_buildMDS_build_signed_package/*.nupkg' - + steps: - task: NuGetToolInstaller@1 displayName: 'Install Latest Nuget' diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index ba33cdf50d..0df5bf38ec 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -35,21 +35,25 @@ schedules: - internal/main parameters: # parameters are shown up in ADO UI in a build queue time +# Enable debug output for this build - name: 'debug' displayName: 'Enable debug output' type: boolean default: false +# Boolean value to indicate whether to publish symbols - name: publishSymbols displayName: 'Publish symbols' type: boolean default: false +# Lowest supported .NET Framework version for this build (for MDS validation) - name: CurrentNetFxVersion displayName: 'Lowest supported .NET Framework version (MDS validation)' type: string default: 'net462' +# OneBranch template type: Official or NonOfficial - name: oneBranchType displayName: 'Select OneBranch template' default: Official @@ -57,6 +61,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time - NonOfficial - Official +# Is this a preview build? - name: isPreview displayName: 'Is this a preview build?' type: boolean @@ -75,6 +80,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time type: boolean default: false +# Publish destination: Internal or Public - name: publishDestination displayName: 'Publish destination' type: string @@ -83,21 +89,25 @@ parameters: # parameters are shown up in ADO UI in a build queue time - Internal - Public +# Boolean value to indicate whether to perform a dry run or actual publish of NuGet Packages - name: dryRun displayName: 'Dry run (no publish)' type: boolean - default: false + default: true +# Internal feed source URL for publishing packages to Azure DevOps Feed - name: internalFeedSource displayName: 'Internal feed source URL' type: string default: '' +# Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource displayName: 'Public NuGet source URL' type: string default: 'https://api.nuget.org/v3/index.json' +# Product name associated with the packages - name: product displayName: 'Product code (MDS|MSS|AKV)' type: string diff --git a/tools/scripts/publishPackagesToFeed.ps1 b/tools/scripts/publishPackagesToAzDOFeed.ps1 similarity index 98% rename from tools/scripts/publishPackagesToFeed.ps1 rename to tools/scripts/publishPackagesToAzDOFeed.ps1 index 1b70dfd9db..77d0bb6e68 100644 --- a/tools/scripts/publishPackagesToFeed.ps1 +++ b/tools/scripts/publishPackagesToAzDOFeed.ps1 @@ -2,7 +2,7 @@ # The .NET Foundation licenses this file to you under the MIT license. # See the LICENSE file in the project root for more information. -# Script: publishPackagesToFeed.ps1 +# Script: publishPackagesToAzDOFeed.ps1 # Date: 10-12-2025 # Comments: This script publishes packages to an internal Azure DevOps Feed. From 4bb21803c155c18c271ba4957f27eddc1b556687 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 10 Dec 2025 23:31:48 -0800 Subject: [PATCH 07/12] Minor changes --- .../templates/jobs/publish-packages-job.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml index 985deecbc8..2f2959ae5c 100644 --- a/eng/pipelines/common/templates/jobs/publish-packages-job.yml +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -84,13 +84,6 @@ jobs: echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" echo "Downloaded signed packages to: ${{ variables.targetDownloadPath }}" displayName: 'Echo NuGet Package Version' - # Push to Internal Feed if publishDestination is not 'Public' - - ${{ if ne(parameters.publishDestination, 'Public') }}: - - template: ../steps/publish-internal-feed-step.yml - parameters: - dryRun: ${{ parameters.dryRun }} - internalFeedSource: ${{ parameters.internalFeedSource }} - packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg # Push to Public NuGet Feed if publishDestination is 'Public' - ${{ if eq(parameters.publishDestination, 'Public') }}: - template: ../steps/publish-public-nuget-step.yml @@ -98,8 +91,15 @@ jobs: dryRun: ${{ parameters.dryRun }} publicNuGetSource: ${{ parameters.publicNuGetSource }} packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg + # Else Push to Internal Feed + - ${{ else }}: + - template: ../steps/publish-internal-feed-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + internalFeedSource: ${{ parameters.internalFeedSource }} + packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg # Publish Symbols if publishSymbols is true and is not a dry run - - ${{ if and(parameters.publishSymbols, ne(parameters.dryRun, true)) }}: + - ${{ if and(parameters.publishSymbols, eq(parameters.dryRun, false)) }}: - template: ../steps/publish-symbols-step.yml parameters: publishSymbols: ${{ parameters.publishSymbols }} From 226f6e7f38790d2cfec0b1167b366e33fecc7a3e Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 10 Dec 2025 23:38:46 -0800 Subject: [PATCH 08/12] Update official signing pipeline --- .../dotnet-sqlclient-signing-pipeline.yml | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index 0df5bf38ec..00805f0085 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -120,7 +120,7 @@ parameters: # parameters are shown up in ADO UI in a build queue time variables: - template: /eng/pipelines/libraries/variables.yml@self - name: packageFolderName - value: drop_buildMDS_build_signed_package + value: drop_build${{ parameters['product'] }}_build_signed_package - name: PublishSymbols value: ${{ parameters['publishSymbols'] }} - name: CurrentNetFxVersion @@ -188,42 +188,42 @@ extends: tsaOptionsPath: $(REPOROOT)\.config\tsaoptions.json disableLegacyManifest: true stages: - - stage: buildMDS - displayName: 'Build MDS' - jobs: - - template: eng/pipelines/common/templates/jobs/build-signed-package-job.yml@self - parameters: - symbolsFolder: $(symbolsFolder) - softwareFolder: $(softwareFolder) - publishSymbols: ${{ parameters['publishSymbols'] }} - isPreview: ${{ parameters['isPreview'] }} - - - stage: mds_package_validation - displayName: 'MDS Package Validation' - dependsOn: buildMDS - jobs: - - template: eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self - parameters: - packageFolderName: $(packageFolderName) - isPreview: ${{ parameters['isPreview'] }} - downloadPackageStep: - download: current - artifact: $(packageFolderName) - patterns: '**/*.*nupkg' - displayName: 'Download NuGet Package' - -# Disabling as of 10/15/2025 due to OneBranch apparently disallowing MSBuild tasks in validation stages. -# - template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self -# parameters: -# packageFolderName: $(packageFolderName) -# isPreview: ${{ parameters['isPreview'] }} -# timeout: ${{ parameters.testsTimeout }} -# downloadPackageStep: -# download: current -# artifact: $(packageFolderName) -# patterns: '**/*.nupkg' -# displayName: 'Download NuGet Package' - + # TODO: Build other products as well based on parameters['product'] + # This pipeline currently only builds MDS product. + - ${{ if eq(parameters['product'], 'MDS') }}: + - stage: buildMDS + displayName: 'Build MDS' + jobs: + - template: eng/pipelines/common/templates/jobs/build-signed-package-job.yml@self + parameters: + symbolsFolder: $(symbolsFolder) + softwareFolder: $(softwareFolder) + publishSymbols: ${{ parameters['publishSymbols'] }} + isPreview: ${{ parameters['isPreview'] }} + - stage: mds_package_validation + displayName: 'MDS Package Validation' + dependsOn: buildMDS + jobs: + - template: eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self + parameters: + packageFolderName: $(packageFolderName) + isPreview: ${{ parameters['isPreview'] }} + downloadPackageStep: + download: current + artifact: $(packageFolderName) + patterns: '**/*.*nupkg' + displayName: 'Download NuGet Package' + # Disabling as of 10/15/2025 due to OneBranch apparently disallowing MSBuild tasks in validation stages. + # - template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self + # parameters: + # packageFolderName: $(packageFolderName) + # isPreview: ${{ parameters['isPreview'] }} + # timeout: ${{ parameters.testsTimeout }} + # downloadPackageStep: + # download: current + # artifact: $(packageFolderName) + # patterns: '**/*.nupkg' + # displayName: 'Download NuGet Package' # Manual Release Stage (templated) - template: eng/pipelines/common/templates/stages/release-stage.yml@self parameters: From 9875749b82b3c66d0ec3e9a352f687f42a477701 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Wed, 10 Dec 2025 23:55:02 -0800 Subject: [PATCH 09/12] Code formattings --- .../templates/jobs/publish-packages-job.yml | 135 ++++---- .../common/templates/stages/release-stage.yml | 41 ++- .../steps/publish-internal-feed-step.yml | 20 +- .../steps/publish-public-nuget-step.yml | 75 +++-- .../templates/steps/publish-symbols-step.yml | 161 +++++---- .../dotnet-sqlclient-signing-pipeline.yml | 313 +++++++++--------- tools/scripts/publishPackagesToAzDOFeed.ps1 | 14 +- 7 files changed, 400 insertions(+), 359 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/publish-packages-job.yml b/eng/pipelines/common/templates/jobs/publish-packages-job.yml index 2f2959ae5c..49885bf1c1 100644 --- a/eng/pipelines/common/templates/jobs/publish-packages-job.yml +++ b/eng/pipelines/common/templates/jobs/publish-packages-job.yml @@ -9,99 +9,100 @@ parameters: type: string default: '[ADO.Net]\\SqlClient Admins' - # Where to publish the packages: 'Internal' or 'Public' feed + # Where to publish the packages: 'Internal' or 'Public' feed - name: publishDestination type: string - # Boolean value to indicate whether to perform a dry run or actual publish + # Boolean value to indicate whether to perform a dry run or actual publish - name: dryRun type: boolean - # Boolean value to indicate if the build is a preview release build + # Boolean value to indicate if the build is a preview release build - name: isPreview type: boolean - # Internal feed source URL for publishing packages to Azure DevOps Feed + # Internal feed source URL for publishing packages to Azure DevOps Feed - name: internalFeedSource type: string - # Public NuGet source URL for publishing packages to public feed + # Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource type: string - # Boolean value to indicate whether to publish symbols + # Boolean value to indicate whether to publish symbols - name: publishSymbols type: boolean - # Name of the folder containing the packages to be published + # Name of the folder containing the packages to be published - name: packageFolderName type: string - # NuGet package version to be published + # NuGet package version to be published - name: nugetPackageVersion type: string - # Product name associated with the packages + # Product name associated with the packages - name: product type: string jobs: -- job: AwaitApproval - displayName: 'Await Release Approval' - pool: server - steps: - - task: ManualValidation@0 - displayName: 'Manual Approval' - timeoutInMinutes: 4320 # 3 days - inputs: - notifyUsers: ${{ parameters.approvalAliases }} - instructions: | - Release Checklist: - * Destination: ${{ parameters.publishDestination }} - * Preview build: ${{ parameters.isPreview }} - * Dry run: ${{ parameters.dryRun }} - * Symbols: ${{ parameters.publishSymbols }} - * NuGet package version: ${{ parameters.nugetPackageVersion }} - * Product: ${{ parameters.product }} - Approve to continue or Reject to abort. + - job: AwaitApproval + displayName: "Await Release Approval" + pool: server + steps: + - task: ManualValidation@0 + displayName: "Manual Approval" + timeoutInMinutes: 4320 # 3 days + inputs: + notifyUsers: ${{ parameters.approvalAliases }} + instructions: | + Release Checklist: + * Destination: ${{ parameters.publishDestination }} + * Preview build: ${{ parameters.isPreview }} + * Dry run: ${{ parameters.dryRun }} + * Symbols: ${{ parameters.publishSymbols }} + * NuGet package version: ${{ parameters.nugetPackageVersion }} + * Product: ${{ parameters.product }} + Approve to continue or Reject to abort. -- job: PublishPackages - displayName: 'Publish Packages' - variables: - - targetDownloadPath: '$(Pipeline.Workspace)/release/packages' - dependsOn: AwaitApproval - condition: succeeded() - pool: - vmImage: 'ubuntu-latest' - steps: - - task: DownloadPipelineArtifact@2 - displayName: 'Download Signed Packages' - inputs: - buildType: current - artifactName: ${{ parameters.packageFolderName }} - targetPath: ${{ variables.targetDownloadPath }} - - script: | - echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" - echo "Downloaded signed packages to: ${{ variables.targetDownloadPath }}" - displayName: 'Echo NuGet Package Version' - # Push to Public NuGet Feed if publishDestination is 'Public' - - ${{ if eq(parameters.publishDestination, 'Public') }}: - - template: ../steps/publish-public-nuget-step.yml - parameters: - dryRun: ${{ parameters.dryRun }} - publicNuGetSource: ${{ parameters.publicNuGetSource }} - packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg - # Else Push to Internal Feed - - ${{ else }}: - - template: ../steps/publish-internal-feed-step.yml - parameters: - dryRun: ${{ parameters.dryRun }} - internalFeedSource: ${{ parameters.internalFeedSource }} - packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg - # Publish Symbols if publishSymbols is true and is not a dry run - - ${{ if and(parameters.publishSymbols, eq(parameters.dryRun, false)) }}: - - template: ../steps/publish-symbols-step.yml - parameters: - publishSymbols: ${{ parameters.publishSymbols }} - symbolsArtifactName: ${{ parameters.product }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.nugetPackageVersion }}_$(System.TimelineId) - product: ${{ parameters.product }} + - job: PublishPackages + displayName: "Publish Packages" + variables: + - name: targetDownloadPath + value: "$(Pipeline.Workspace)/release/packages" + dependsOn: AwaitApproval + condition: succeeded() + pool: + vmImage: "ubuntu-latest" + steps: + - task: DownloadPipelineArtifact@2 + displayName: "Download Signed Packages" + inputs: + buildType: current + artifactName: ${{ parameters.packageFolderName }} + targetPath: ${{ variables.targetDownloadPath }} + - script: | + echo "NuGet Package Version: ${{ parameters.nugetPackageVersion }}" + echo "Downloaded signed packages to: ${{ variables.targetDownloadPath }}" + displayName: "Echo NuGet Package Version" + # Push to Public NuGet Feed if publishDestination is 'Public' + - ${{ if eq(parameters.publishDestination, 'Public') }}: + - template: ../steps/publish-public-nuget-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg + # Else Push to Internal Feed + - ${{ else }}: + - template: ../steps/publish-internal-feed-step.yml + parameters: + dryRun: ${{ parameters.dryRun }} + internalFeedSource: ${{ parameters.internalFeedSource }} + packagesGlob: ${{ variables.targetDownloadPath }}/*.nupkg + # Publish Symbols if publishSymbols is true and is not a dry run + - ${{ if and(parameters.publishSymbols, not(parameters.dryRun)) }}: + - template: ../steps/publish-symbols-step.yml + parameters: + publishSymbols: ${{ parameters.publishSymbols }} + symbolsArtifactName: ${{ parameters.product }}_symbols_$(System.TeamProject)_$(Build.Repository.Name)_$(Build.SourceBranchName)_${{ parameters.nugetPackageVersion }}_$(System.TimelineId) + product: ${{ parameters.product }} diff --git a/eng/pipelines/common/templates/stages/release-stage.yml b/eng/pipelines/common/templates/stages/release-stage.yml index 2171c4b0de..bd8835ac64 100644 --- a/eng/pipelines/common/templates/stages/release-stage.yml +++ b/eng/pipelines/common/templates/stages/release-stage.yml @@ -26,7 +26,7 @@ parameters: - name: internalFeedSource type: string - # Public NuGet source URL for publishing packages to public feed + # Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource type: string @@ -34,7 +34,7 @@ parameters: - name: publishSymbols type: boolean default: false - + # Boolean value to indicate if the build is a preview release build - name: isPreview type: boolean @@ -42,30 +42,29 @@ parameters: # Product name associated with the packages - name: product type: string - + # NuGet package version to be published - name: nugetPackageVersion type: string - + # Name of the folder containing the packages to be published - name: packageFolderName type: string stages: -- stage: releaseMDS - displayName: 'Release (Manual)' - condition: and(succeeded(), eq(variables['Build.Reason'],'Manual'), eq(${{ parameters.runRelease }}, true)) - jobs: - - template: ../jobs/publish-packages-job.yml - parameters: - approvalAliases: ${{ parameters.approvalAliases }} - publishDestination: ${{ parameters.publishDestination }} - dryRun: ${{ parameters.dryRun }} - isPreview: ${{ parameters.isPreview }} - internalFeedSource: ${{ parameters.internalFeedSource }} - publicNuGetSource: ${{ parameters.publicNuGetSource }} - publishSymbols: ${{ parameters.publishSymbols }} - packageFolderName: ${{ parameters.packageFolderName }} - nugetPackageVersion: ${{ parameters.nugetPackageVersion }} - product: ${{ parameters.product }} - + - stage: Release ${{ parameters.product }} + displayName: "Release (Manual)" + condition: and(succeeded(), eq(variables['Build.Reason'],'Manual'), eq(${{ parameters.runRelease }}, true)) + jobs: + - template: ../jobs/publish-packages-job.yml + parameters: + approvalAliases: ${{ parameters.approvalAliases }} + publishDestination: ${{ parameters.publishDestination }} + dryRun: ${{ parameters.dryRun }} + isPreview: ${{ parameters.isPreview }} + internalFeedSource: ${{ parameters.internalFeedSource }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + publishSymbols: ${{ parameters.publishSymbols }} + packageFolderName: ${{ parameters.packageFolderName }} + nugetPackageVersion: ${{ parameters.nugetPackageVersion }} + product: ${{ parameters.product }} diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index 1ce616bc30..f004c79c49 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -3,21 +3,27 @@ # The .NET Foundation licenses this file to you under the MIT license. # # See the LICENSE file in the project root for more information. # ################################################################################# + +# Template to publish NuGet packages to an internal Azure DevOps feed + parameters: + # Boolean value to indicate whether to perform a dry run or actual publish - name: dryRun type: boolean default: true + # Internal feed source URL for publishing packages to Azure DevOps Feed - name: internalFeedSource type: string - + + # Glob pattern to identify packages to be published - name: packagesGlob type: string steps: -- script: | - pwsh ./tools/scripts/publishPackagesToFeed.ps1 ` - -dryRun ${{ parameters.dryRun }} ` - -internalFeedSource '${{ parameters.internalFeedSource }}' ` - -packagesGlob '${{ parameters.packagesGlob }}' - displayName: 'Publish to Internal Feed' + - script: | + pwsh ./tools/scripts/publishPackagesToAzDOFeed.ps1 ` + -dryRun ${{ parameters.dryRun }} ` + -internalFeedSource '${{ parameters.internalFeedSource }}' ` + -packagesGlob '${{ parameters.packagesGlob }}' + displayName: "Publish to Internal Feed" diff --git a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml index 27c0015039..fc6947bb22 100644 --- a/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml +++ b/eng/pipelines/common/templates/steps/publish-public-nuget-step.yml @@ -3,50 +3,57 @@ # The .NET Foundation licenses this file to you under the MIT license. # # See the LICENSE file in the project root for more information. # ################################################################################# + +# Template to publish NuGet packages to a public NuGet feed + parameters: + # Boolean value to indicate whether to perform a dry run or actual publish - name: dryRun type: boolean default: true + # Public NuGet source URL for publishing packages to public feed - name: publicNuGetSource type: string - + + # Service connection name for authenticating to NuGet.org - name: nugetServiceConnection type: string - default: 'ADO Nuget Org Connection' - + default: "ADO Nuget Org Connection" + + # Glob pattern to identify packages to be published - name: packagesGlob type: string - + steps: -- task: NuGetToolInstaller@1 - displayName: 'Install Latest Nuget' - inputs: - checkLatest: true -- script: | - echo "[DRY RUN] Listing packages targeted for push to: ${{ parameters.publicNuGetSource }}" - echo "Using glob pattern: ${{ parameters.packagesGlob }}" - # Derive directory and filename pattern from the glob for a precise find (handles nested patterns minimally) - glob='${{ parameters.packagesGlob }}' - dir="${glob%/*}" - name="${glob##*/}" - echo "Resolved directory: $dir" - echo "Filename pattern: $name" - if [ -d "$dir" ]; then - echo "Matched files:" || true - # Print all matched files to identify what would be pushed - find "$dir" -type f -name "$name" -print || true - else - echo "Directory does not exist yet: $dir" - fi - displayName: 'Dry Run - List Packages' - condition: and(succeeded(), eq(${{ parameters.dryRun }}, true)) + - task: NuGetToolInstaller@1 + displayName: "Install Latest Nuget" + inputs: + checkLatest: true + - script: | + echo "[DRY RUN] Listing packages targeted for push to: ${{ parameters.publicNuGetSource }}" + echo "Using glob pattern: ${{ parameters.packagesGlob }}" + # Derive directory and filename pattern from the glob for a precise find (handles nested patterns minimally) + glob='${{ parameters.packagesGlob }}' + dir="${glob%/*}" + name="${glob##*/}" + echo "Resolved directory: $dir" + echo "Filename pattern: $name" + if [ -d "$dir" ]; then + echo "Matched files:" || true + # Print all matched files to identify what would be pushed + find "$dir" -type f -name "$name" -print || true + else + echo "Directory does not exist yet: $dir" + fi + displayName: "Dry Run - List Packages" + condition: and(succeeded(), eq(${{ parameters.dryRun }}, true)) -- task: NuGetCommand@2 - displayName: 'Push to Nuget.org' - condition: and(succeeded(), eq(${{ parameters.dryRun }}, false)) - inputs: - command: push - packagesToPush: '${{ parameters.packagesGlob }}' - nuGetFeedType: external - publishFeedCredentials: '${{ parameters.nugetServiceConnection }}' + - task: NuGetCommand@2 + displayName: "Push to Nuget.org" + condition: and(succeeded(), eq(${{ parameters.dryRun }}, false)) + inputs: + command: push + packagesToPush: "${{ parameters.packagesGlob }}" + nuGetFeedType: external + publishFeedCredentials: "${{ parameters.nugetServiceConnection }}" diff --git a/eng/pipelines/common/templates/steps/publish-symbols-step.yml b/eng/pipelines/common/templates/steps/publish-symbols-step.yml index d8eae8837a..7891995203 100644 --- a/eng/pipelines/common/templates/steps/publish-symbols-step.yml +++ b/eng/pipelines/common/templates/steps/publish-symbols-step.yml @@ -6,113 +6,128 @@ # doc: https://www.osgwiki.com/wiki/Symbols_Publishing_Pipeline_to_SymWeb_and_MSDL # #################################################################################### parameters: + # Symbol account name in Azure DevOps organization where symbols will be published - name: SymAccount type: string - default: 'SqlClientDrivers' + default: "SqlClientDrivers" + # Boolean value to indicate whether to publish symbols - name: publishSymbols type: boolean default: false + # Version of the symbols being published - name: symbolsVersion type: string - default: '$(NugetPackageVersion)' + default: "$(NugetPackageVersion)" + # Symbol server name (without .trafficmanager.net) - name: symbolServer type: string - default: '$(SymbolServer)' + default: "$(SymbolServer)" + # Token URI for authenticating to the symbol server - name: symbolTokenUri type: string - default: '$(SymbolTokenUri)' + default: "$(SymbolTokenUri)" + # Artifact name for the symbols being published - name: symbolsArtifactName type: string + # Servers to which symbols should be published - name: publishToServers type: object default: internal: true public: true + # Type of reference for which symbols are being published - name: referenceType default: project values: - - project - - package - + - project + - package + + # Product name associated with the symbols + # Symbols publishing Step is currently only configured for the MDS driver, as they are required to be published to 3 locations: + # 1. Azure DevOps Org, + #. 2. MS Internal Symbols server + # 3. MS Public symbol server + # For other products: Symbols are uploaded to NuGet.org symbol server via snuget package push during package publishing. - name: product default: MDS values: - - MDS - - MSS - - AKV - + - MDS + - MSS + - AKV + + # Azure subscription for publishing symbols to internal and public symbol servers - name: azureSubscription type: string - default: 'Symbols publishing Workload Identity federation service-ADO.Net' + default: "Symbols publishing Workload Identity federation service-ADO.Net" steps: -- powershell: 'Write-Host "##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{parameters.SymAccount}}"' - displayName: 'Update Symbol.AccountName with ${{parameters.SymAccount}}' - condition: and(succeeded(), eq(parameters.publishSymbols, true)) - -- ${{ if and(eq(parameters.publishSymbols, true), eq(parameters.product, 'MDS')) }}: - - task: PublishSymbols@2 - displayName: 'Upload MDS symbols to ${{parameters.SymAccount }} org' - inputs: - SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\${{parameters.referenceType }}\bin' - SearchPattern: | - Windows_NT/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb - Unix/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb - IndexSources: false - SymbolServerType: TeamServices - SymbolsMaximumWaitTime: 60 - SymbolExpirationInDays: 1825 # 5 years - SymbolsProduct: Microsoft.Data.SqlClient - SymbolsVersion: ${{parameters.symbolsVersion }} - SymbolsArtifactName: ${{parameters.symbolsArtifactName }} - Pat: $(System.AccessToken) - condition: and(succeeded(), eq(parameters.publishSymbols, true)) - - task: AzureCLI@2 - displayName: 'Publish MDS symbols' + - powershell: 'Write-Host "##vso[task.setvariable variable=ArtifactServices.Symbol.AccountName;]${{parameters.SymAccount}}"' + displayName: "Update Symbol.AccountName with ${{parameters.SymAccount}}" condition: and(succeeded(), eq(parameters.publishSymbols, true)) - inputs: - azureSubscription: ${{ parameters.azureSubscription }} - scriptType: ps - scriptLocation: inlineScript - inlineScript: | - $publishToInternalServer = "${{parameters.publishToServers.internal }}".ToLower() - $publishToPublicServer = "${{parameters.publishToServers.public }}".ToLower() - - echo "Publishing request name: ${{parameters.symbolsArtifactName }}" - echo "Publish to internal server: $publishToInternalServer" - echo "Publish to public server: $publishToPublicServer" - - $symbolServer = "${{parameters.symbolServer }}" - $tokenUri = "${{parameters.symbolTokenUri }}" - $projectName = "Microsoft.Data.SqlClient.SNI" - - $symbolPublishingToken = az account get-access-token --resource $tokenUri --query accessToken -o tsv - - echo "> 1.Symbol publishing token acquired." - - echo "Registering the request name ..." - $requestName = "${{parameters.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." - - 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 "PublishingStatus"; echo "-----------------"; echo "0 NotRequested"; echo "1 Submitted"; echo "2 Processing"; echo "3 Completed" - echo "PublishingResult"; echo "-----------------"; echo "0 Pending"; echo "1 Succeeded"; echo "2 Failed"; echo "3 Cancelled" + - ${{ if and(eq(parameters.publishSymbols, true), eq(parameters.product, 'MDS')) }}: + - task: PublishSymbols@2 + displayName: "Upload MDS symbols to ${{parameters.SymAccount }} org" + inputs: + SymbolsFolder: '$(Build.SourcesDirectory)\artifacts\${{parameters.referenceType }}\bin' + SearchPattern: | + Windows_NT/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb + Unix/$(Configuration).AnyCPU/**/Microsoft.Data.SqlClient.pdb + IndexSources: false + SymbolServerType: TeamServices + SymbolsMaximumWaitTime: 60 + SymbolExpirationInDays: 1825 # 5 years + SymbolsProduct: Microsoft.Data.SqlClient + SymbolsVersion: ${{parameters.symbolsVersion }} + SymbolsArtifactName: ${{parameters.symbolsArtifactName }} + Pat: $(System.AccessToken) + condition: and(succeeded(), eq(parameters.publishSymbols, true)) + - task: AzureCLI@2 + displayName: "Publish MDS symbols" + condition: and(succeeded(), eq(parameters.publishSymbols, true)) + inputs: + azureSubscription: ${{ parameters.azureSubscription }} + scriptType: ps + scriptLocation: inlineScript + inlineScript: | + $publishToInternalServer = "${{parameters.publishToServers.internal }}".ToLower() + $publishToPublicServer = "${{parameters.publishToServers.public }}".ToLower() + + echo "Publishing request name: ${{parameters.symbolsArtifactName }}" + echo "Publish to internal server: $publishToInternalServer" + echo "Publish to public server: $publishToPublicServer" + + $symbolServer = "${{parameters.symbolServer }}" + $tokenUri = "${{parameters.symbolTokenUri }}" + $projectName = "Microsoft.Data.SqlClient.SNI" + + $symbolPublishingToken = az account get-access-token --resource $tokenUri --query accessToken -o tsv + + echo "> 1.Symbol publishing token acquired." + + echo "Registering the request name ..." + $requestName = "${{parameters.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." + + 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 "PublishingStatus"; echo "-----------------"; echo "0 NotRequested"; echo "1 Submitted"; echo "2 Processing"; echo "3 Completed" + echo "PublishingResult"; echo "-----------------"; echo "0 Pending"; echo "1 Succeeded"; echo "2 Failed"; echo "3 Cancelled" diff --git a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml index 00805f0085..d6d4835a28 100644 --- a/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-signing-pipeline.yml @@ -8,114 +8,115 @@ name: $(Year:YY)$(DayOfYear)$(Rev:.r) trigger: branches: include: - - internal/main + - internal/main paths: include: - - src - - eng - - tools - - .config - - build.proj - - Nuget.config - - '*.cmd' - - '*.sh' + - src + - eng + - tools + - .config + - build.proj + - Nuget.config + - "*.cmd" + - "*.sh" schedules: -- cron: '30 4 * * Mon' - displayName: Weekly Sunday 9:30 PM (UTC - 7) Build - branches: - include: - - internal/main - always: true - -- cron: '30 3 * * Mon-Fri' - displayName: Mon-Fri 8:30 PM (UTC - 7) Build - branches: - include: - - internal/main - -parameters: # parameters are shown up in ADO UI in a build queue time -# Enable debug output for this build -- name: 'debug' - displayName: 'Enable debug output' - type: boolean - default: false - -# Boolean value to indicate whether to publish symbols -- name: publishSymbols - displayName: 'Publish symbols' - type: boolean - default: false - -# Lowest supported .NET Framework version for this build (for MDS validation) -- name: CurrentNetFxVersion - displayName: 'Lowest supported .NET Framework version (MDS validation)' - type: string - default: 'net462' - -# OneBranch template type: Official or NonOfficial -- name: oneBranchType - displayName: 'Select OneBranch template' - default: Official - values: - - NonOfficial - - Official - -# Is this a preview build? -- name: isPreview - displayName: 'Is this a preview build?' - type: boolean - default: false - -# The timeout, in minutes, for each test job. -- name: testsTimeout - displayName: 'Tests timeout (in minutes)' - type: string - default: 90 - -# Manual Release Parameters -# Release stage runs ONLY when build is manually queued AND runRelease = true. -- name: runRelease - displayName: 'Run manual release stage' - type: boolean - default: false - -# Publish destination: Internal or Public -- name: publishDestination - displayName: 'Publish destination' - type: string - default: Internal - values: - - Internal - - Public - -# Boolean value to indicate whether to perform a dry run or actual publish of NuGet Packages -- name: dryRun - displayName: 'Dry run (no publish)' - type: boolean - default: true - -# Internal feed source URL for publishing packages to Azure DevOps Feed -- name: internalFeedSource - displayName: 'Internal feed source URL' - type: string - default: '' - -# Public NuGet source URL for publishing packages to public feed -- name: publicNuGetSource - displayName: 'Public NuGet source URL' - type: string - default: 'https://api.nuget.org/v3/index.json' - -# Product name associated with the packages -- name: product - displayName: 'Product code (MDS|MSS|AKV)' - type: string - default: 'MDS' - values: - - MDS - - MSS - - AKV + - cron: "30 4 * * Mon" + displayName: Weekly Sunday 9:30 PM (UTC - 7) Build + branches: + include: + - internal/main + always: true + + - cron: "30 3 * * Mon-Fri" + displayName: Mon-Fri 8:30 PM (UTC - 7) Build + branches: + include: + - internal/main + +# These parameters are shown up in ADO UI in a build queue time +parameters: + # Enable debug output for this build + - name: "debug" + displayName: "Enable debug output" + type: boolean + default: false + + # Boolean value to indicate whether to publish symbols + - name: publishSymbols + displayName: "Publish symbols" + type: boolean + default: false + + # Lowest supported .NET Framework version for this build (for MDS validation) + - name: CurrentNetFxVersion + displayName: "Lowest supported .NET Framework version (MDS validation)" + type: string + default: "net462" + + # OneBranch template type: Official or NonOfficial + - name: oneBranchType + displayName: "Select OneBranch template" + default: Official + values: + - NonOfficial + - Official + + # Is this a preview build? + - name: isPreview + displayName: "Is this a preview build?" + type: boolean + default: false + + # The timeout, in minutes, for each test job. + - name: testsTimeout + displayName: "Tests timeout (in minutes)" + type: string + default: 90 + + # Manual Release Parameters + # Release stage runs ONLY when build is manually queued AND runRelease = true. + - name: runRelease + displayName: "Run manual release stage" + type: boolean + default: false + + # Publish destination: Internal or Public + - name: publishDestination + displayName: "Publish destination" + type: string + default: Internal + values: + - Internal + - Public + + # Boolean value to indicate whether to perform a dry run or actual publish of NuGet Packages + - name: dryRun + displayName: "Dry run (no publish)" + type: boolean + default: true + + # Internal feed source URL for publishing packages to Azure DevOps Feed + - name: internalFeedSource + displayName: "Internal feed source URL" + type: string + default: "" + + # Public NuGet source URL for publishing packages to public feed + - name: publicNuGetSource + displayName: "Public NuGet source URL" + type: string + default: "https://api.nuget.org/v3/index.json" + + # Product name associated with the packages + - name: product + displayName: "Product code (MDS|MSS|AKV)" + type: string + default: "MDS" + values: + - MDS + - MSS + - AKV variables: - template: /eng/pipelines/libraries/variables.yml@self @@ -127,7 +128,7 @@ variables: value: ${{ parameters['CurrentNetFxVersion'] }} resources: - repositories: + repositories: - repository: templates type: git name: OneBranch.Pipelines/GovernedTemplates @@ -169,7 +170,7 @@ extends: break: true # always break the build on policheck issues. You can disable it by setting to 'false' exclusionsFile: $(REPOROOT)\.config\PolicheckExclusions.xml asyncSdl: - enabled: false + enabled: false credscan: enabled: ${{ not(parameters['isPreview']) }} suppressionsFile: $(REPOROOT)/.config/CredScanSuppressions.json @@ -188,53 +189,53 @@ extends: tsaOptionsPath: $(REPOROOT)\.config\tsaoptions.json disableLegacyManifest: true stages: - # TODO: Build other products as well based on parameters['product'] - # This pipeline currently only builds MDS product. - - ${{ if eq(parameters['product'], 'MDS') }}: - - stage: buildMDS - displayName: 'Build MDS' - jobs: - - template: eng/pipelines/common/templates/jobs/build-signed-package-job.yml@self - parameters: - symbolsFolder: $(symbolsFolder) - softwareFolder: $(softwareFolder) - publishSymbols: ${{ parameters['publishSymbols'] }} - isPreview: ${{ parameters['isPreview'] }} - - stage: mds_package_validation - displayName: 'MDS Package Validation' - dependsOn: buildMDS - jobs: - - template: eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self - parameters: - packageFolderName: $(packageFolderName) - isPreview: ${{ parameters['isPreview'] }} - downloadPackageStep: - download: current - artifact: $(packageFolderName) - patterns: '**/*.*nupkg' - displayName: 'Download NuGet Package' - # Disabling as of 10/15/2025 due to OneBranch apparently disallowing MSBuild tasks in validation stages. - # - template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self - # parameters: - # packageFolderName: $(packageFolderName) - # isPreview: ${{ parameters['isPreview'] }} - # timeout: ${{ parameters.testsTimeout }} - # downloadPackageStep: - # download: current - # artifact: $(packageFolderName) - # patterns: '**/*.nupkg' - # displayName: 'Download NuGet Package' - # Manual Release Stage (templated) - - template: eng/pipelines/common/templates/stages/release-stage.yml@self - parameters: - runRelease: ${{ parameters.runRelease }} - publishDestination: ${{ parameters.publishDestination }} - dryRun: ${{ parameters.dryRun }} - approvalAliases: '[ADO.Net]\\SqlClient Admins' - internalFeedSource: ${{ parameters.internalFeedSource }} - publicNuGetSource: ${{ parameters.publicNuGetSource }} - publishSymbols: ${{ parameters.publishSymbols }} - isPreview: ${{ parameters.isPreview }} - packageFolderName: $(packageFolderName) - nugetPackageVersion: $(NugetPackageVersion) - product: ${{ parameters.product }} + # TODO: Build other products as well based on parameters['product'] + # This pipeline currently only builds MDS product. + - ${{ if eq(parameters['product'], 'MDS') }}: + - stage: buildMDS + displayName: "Build MDS" + jobs: + - template: eng/pipelines/common/templates/jobs/build-signed-package-job.yml@self + parameters: + symbolsFolder: $(symbolsFolder) + softwareFolder: $(softwareFolder) + publishSymbols: ${{ parameters['publishSymbols'] }} + isPreview: ${{ parameters['isPreview'] }} + - stage: mds_package_validation + displayName: "MDS Package Validation" + dependsOn: buildMDS + jobs: + - template: eng/pipelines/common/templates/jobs/validate-signed-package-job.yml@self + parameters: + packageFolderName: $(packageFolderName) + isPreview: ${{ parameters['isPreview'] }} + downloadPackageStep: + download: current + artifact: $(packageFolderName) + patterns: "**/*.*nupkg" + displayName: "Download NuGet Package" + # Disabling as of 10/15/2025 due to OneBranch apparently disallowing MSBuild tasks in validation stages. + # - template: eng/pipelines/common/templates/jobs/run-tests-package-reference-job.yml@self + # parameters: + # packageFolderName: $(packageFolderName) + # isPreview: ${{ parameters['isPreview'] }} + # timeout: ${{ parameters.testsTimeout }} + # downloadPackageStep: + # download: current + # artifact: $(packageFolderName) + # patterns: '**/*.nupkg' + # displayName: 'Download NuGet Package' + # Manual Release Stage (templated) + - template: eng/pipelines/common/templates/stages/release-stage.yml@self + parameters: + runRelease: ${{ parameters.runRelease }} + publishDestination: ${{ parameters.publishDestination }} + dryRun: ${{ parameters.dryRun }} + approvalAliases: '[ADO.Net]\\SqlClient Admins' + internalFeedSource: ${{ parameters.internalFeedSource }} + publicNuGetSource: ${{ parameters.publicNuGetSource }} + publishSymbols: ${{ parameters.publishSymbols }} + isPreview: ${{ parameters.isPreview }} + packageFolderName: $(packageFolderName) + nugetPackageVersion: $(NugetPackageVersion) + product: ${{ parameters.product }} diff --git a/tools/scripts/publishPackagesToAzDOFeed.ps1 b/tools/scripts/publishPackagesToAzDOFeed.ps1 index 77d0bb6e68..cc5f8f2669 100644 --- a/tools/scripts/publishPackagesToAzDOFeed.ps1 +++ b/tools/scripts/publishPackagesToAzDOFeed.ps1 @@ -20,7 +20,11 @@ Function PublishToInternalFeed() { exit 1 } - Write-Host "[DRY RUN] Listing packages targeted for push to: $internalFeedSource" -ForegroundColor Cyan + if ($dryRun) { + Write-Host "[DRY RUN] Listing packages targeted for push to: $internalFeedSource" -ForegroundColor Cyan + } else { + Write-Host "Listing packages targeted for push to: $internalFeedSource" -ForegroundColor Cyan + } Write-Host "Using glob pattern: $packagesGlob" -ForegroundColor Cyan # Parse the glob pattern to extract directory and filename pattern @@ -57,16 +61,24 @@ Function PublishToInternalFeed() { if (-not $dryRun) { Write-Host "`nPushing packages to feed..." -ForegroundColor Cyan + foreach ($package in $packages) { + Write-Host "`nPushing packages to feed..." -ForegroundColor Cyan + $anyPushFailed = $false foreach ($package in $packages) { Write-Host "Pushing package: $($package.FullName)" -ForegroundColor Yellow dotnet nuget push $package.FullName --source $SRC --api-key az if ($LASTEXITCODE -ne 0) { Write-Host "Failed to push package: $($package.FullName)" -ForegroundColor Red + $anyPushFailed = $true } else { Write-Host "Successfully pushed: $($package.Name)" -ForegroundColor Green } } + if ($anyPushFailed) { + Write-Host "`nOne or more packages failed to push." -ForegroundColor Red + exit 1 + } } else { Write-Host "`n[DRY RUN] No packages were pushed. Set -dryRun `$false to push." -ForegroundColor Yellow } From 22c55d6e6c1d5eb3aed1e0fa3de100c9581742d9 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Thu, 11 Dec 2025 00:34:37 -0800 Subject: [PATCH 10/12] Update release-stage.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- eng/pipelines/common/templates/stages/release-stage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/common/templates/stages/release-stage.yml b/eng/pipelines/common/templates/stages/release-stage.yml index bd8835ac64..6e626f9b06 100644 --- a/eng/pipelines/common/templates/stages/release-stage.yml +++ b/eng/pipelines/common/templates/stages/release-stage.yml @@ -54,7 +54,7 @@ parameters: stages: - stage: Release ${{ parameters.product }} displayName: "Release (Manual)" - condition: and(succeeded(), eq(variables['Build.Reason'],'Manual'), eq(${{ parameters.runRelease }}, true)) + condition: and(succeeded(), eq('${{ variables.Build.Reason }}', 'Manual'), eq(${{ parameters.runRelease }}, true)) jobs: - template: ../jobs/publish-packages-job.yml parameters: From ad30487d3e2512e0cfda2d7a2b433f52d47f7696 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Thu, 11 Dec 2025 09:01:07 -0800 Subject: [PATCH 11/12] Update powershell task --- .../templates/steps/publish-internal-feed-step.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml index f004c79c49..b0e6d98acf 100644 --- a/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml +++ b/eng/pipelines/common/templates/steps/publish-internal-feed-step.yml @@ -21,9 +21,11 @@ parameters: type: string steps: - - script: | - pwsh ./tools/scripts/publishPackagesToAzDOFeed.ps1 ` - -dryRun ${{ parameters.dryRun }} ` - -internalFeedSource '${{ parameters.internalFeedSource }}' ` - -packagesGlob '${{ parameters.packagesGlob }}' - displayName: "Publish to Internal Feed" + - task: PowerShell@2 + displayName: Publish to Internal Feed + pwsh: true + filePath: /tools/scripts/publishPackagesToFeed.ps1 + arguments: > + -dryRun ${{ parameters.dryRun }} + -internalFeedSource '${{ parameters.internalFeedSource }}' + -packagesGlob '${{ parameters.packagesGlob }}' From e22f32041ef6db61efa536727b9832f6524ab9dd Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Thu, 11 Dec 2025 10:13:35 -0800 Subject: [PATCH 12/12] Update eng/pipelines/common/templates/steps/publish-symbols-step.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- eng/pipelines/common/templates/steps/publish-symbols-step.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/common/templates/steps/publish-symbols-step.yml b/eng/pipelines/common/templates/steps/publish-symbols-step.yml index 7dd73592af..6c7bb472ff 100644 --- a/eng/pipelines/common/templates/steps/publish-symbols-step.yml +++ b/eng/pipelines/common/templates/steps/publish-symbols-step.yml @@ -52,7 +52,7 @@ parameters: # Product name associated with the symbols # Symbols publishing Step is currently only configured for the MDS driver, as they are required to be published to 3 locations: # 1. Azure DevOps Org, - #. 2. MS Internal Symbols server + # 2. MS Internal Symbols server # 3. MS Public symbol server # For other products: Symbols are uploaded to NuGet.org symbol server via snuget package push during package publishing. - name: product