Skip to content
Open
40 changes: 40 additions & 0 deletions eng/pipelines/common/templates/jobs/approval-job.yml
Original file line number Diff line number Diff line change
@@ -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.
60 changes: 60 additions & 0 deletions eng/pipelines/common/templates/jobs/publish-packages-job.yml
Original file line number Diff line number Diff line change
@@ -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 }}
53 changes: 53 additions & 0 deletions eng/pipelines/common/templates/stages/release-stage.yml
Original file line number Diff line number Diff line change
@@ -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 }}
14 changes: 14 additions & 0 deletions eng/pipelines/common/templates/steps/list-packages-step.yml
Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
@@ -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'
Original file line number Diff line number Diff line change
@@ -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 }}'
Loading
Loading