Skip to content

Commit ce7232d

Browse files
committed
Merged PR 6317: FEAT: Migrate Official and Dummy Release Pipelines
#### AI description (iteration 1) #### PR Classification This feature enhancement migrates both the official and dummy release pipelines to use 1ES in alignment with the linked work items. #### PR Summary This pull request introduces new release pipelines for mssql-python, removes obsolete documentation, and refactors symbol publishing steps to support the 1ES migration. - `OneBranch_Learnings/`: Removed outdated documentation files. - `OneBranchPipelines/dummy-release-pipeline.yml`: Added a new dummy/test release pipeline configured for ESRP dummy releases using Maven. - `OneBranchPipelines/official-release-pipeline.yml`: Added a new official release pipeline designed for production releases to PyPI. - `OneBranchPipelines/steps/symbol-publishing-step.yml`: Updated symbol publishing steps with enhanced PowerShell and Azure CLI integration. - `OneBranchPipelines/build-release-package-pipeline.yml` and `OneBranchPipelines/stages/build-windows-single-stage.yml`: Adjusted variable references and removed legacy symbol publishing to align with the new pipelines. <!-- GitOpsUserAgent=GitOps.Apps.Server.pullrequestcopilot --> Related work items: #38067, #38068
1 parent 9395287 commit ce7232d

File tree

3 files changed

+766
-37
lines changed

3 files changed

+766
-37
lines changed
Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
# OneBranch DUMMY/TEST Release Pipeline for mssql-python
2+
# ⚠️ THIS IS A TEST PIPELINE - NOT FOR PRODUCTION RELEASES ⚠️
3+
# Downloads wheel and symbol artifacts from build pipeline, publishes symbols, and performs dummy ESRP release for testing
4+
# Uses Maven ContentType instead of PyPI to avoid accidental production releases
5+
# This pipeline is ALWAYS Official - no NonOfficial option
6+
7+
name: $(Year:YY)$(DayOfYear)$(Rev:.r)-Dummy-Release
8+
9+
# Manual trigger only - releases should be deliberate
10+
trigger: none
11+
pr: none
12+
13+
# Parameters for DUMMY release pipeline
14+
parameters:
15+
- name: packageVersion
16+
displayName: '[TEST] Package Version (e.g., 0.13.0)'
17+
type: string
18+
default: '0.13.0'
19+
20+
- name: publishSymbols
21+
displayName: '[TEST] Publish Symbols to Symbol Servers'
22+
type: boolean
23+
default: true
24+
25+
- name: performDummyRelease
26+
displayName: '[TEST] Perform Dummy ESRP Release (Maven - NOT PyPI)'
27+
type: boolean
28+
default: true # Safe to enable - uses Maven ContentType for testing
29+
30+
# Variables
31+
variables:
32+
- name: PACKAGE_VERSION
33+
value: '${{ parameters.packageVersion }}'
34+
readonly: true
35+
36+
- name: packageVersion
37+
value: '${{ parameters.packageVersion }}'
38+
readonly: true
39+
40+
# Common variables
41+
- template: /OneBranchPipelines/variables/common-variables.yml@self
42+
- template: /OneBranchPipelines/variables/onebranch-variables.yml@self
43+
44+
# Variable groups
45+
- group: 'ESRP Federated Creds (AME)' # Contains ESRP signing credentials
46+
- group: 'Symbols Publishing' # Contains SymbolServer, SymbolTokenUri variables
47+
48+
# OneBranch resources
49+
resources:
50+
repositories:
51+
- repository: templates
52+
type: git
53+
name: 'OneBranch.Pipelines/GovernedTemplates'
54+
ref: 'refs/heads/main'
55+
56+
# Reference to the build pipeline
57+
pipelines:
58+
- pipeline: buildPipeline
59+
source: 'Build-Release-Package-Pipeline' # Name of the build pipeline
60+
trigger: none # Manual trigger only
61+
62+
# Extend OneBranch official template
63+
# Always uses Official template for release pipeline
64+
extends:
65+
template: 'v2/OneBranch.Official.CrossPlat.yml@templates'
66+
67+
parameters:
68+
# Feature flags
69+
featureFlags:
70+
WindowsHostVersion:
71+
Version: '2022'
72+
73+
# Global SDL Configuration
74+
globalSdl:
75+
# Minimal SDL for release pipeline - artifacts already scanned during build
76+
binskim:
77+
enabled: true
78+
break: true
79+
80+
credscan:
81+
enabled: true
82+
suppressionsFile: '$(REPO_ROOT)/.config/CredScanSuppressions.json'
83+
84+
policheck:
85+
enabled: true
86+
break: true
87+
exclusionFile: '$(REPO_ROOT)/.config/PolicheckExclusions.xml'
88+
89+
# Publish SDL logs
90+
publishLogs:
91+
enabled: true
92+
93+
# TSA - Always enabled for Official release pipeline
94+
tsa:
95+
enabled: true
96+
configFile: '$(REPO_ROOT)/.config/tsaoptions.json'
97+
98+
# Pipeline stages
99+
stages:
100+
- stage: TestReleasePackages
101+
displayName: '[TEST] Dummy Release - Testing ESRP Workflow'
102+
103+
jobs:
104+
- job: DownloadAndTestRelease
105+
displayName: '[TEST] Download Artifacts and Perform Dummy Release'
106+
107+
pool:
108+
type: windows
109+
isCustom: true
110+
name: Django-1ES-pool
111+
vmImage: WIN22-SQL22
112+
113+
variables:
114+
ob_outputDirectory: '$(Build.ArtifactStagingDirectory)'
115+
116+
steps:
117+
# Step 1: Download consolidated artifacts from build pipeline
118+
- task: DownloadPipelineArtifact@2
119+
displayName: '[TEST] Download Consolidated Artifacts from Build Pipeline'
120+
inputs:
121+
buildType: 'specific'
122+
project: '$(System.TeamProject)'
123+
definition: 2199 # Build-Release-Package-Pipeline definition ID
124+
buildVersionToDownload: 'specific'
125+
buildId: $(resources.pipeline.buildPipeline.runID) # Use the build run selected in UI
126+
artifactName: 'drop_Consolidate_ConsolidateArtifacts' # Consolidated artifact with dist/ and symbols/
127+
targetPath: '$(Build.SourcesDirectory)/artifacts'
128+
129+
# Step 3: List downloaded artifacts for verification
130+
- task: PowerShell@2
131+
displayName: '[TEST] List Downloaded Wheel and Symbol Files'
132+
inputs:
133+
targetType: 'inline'
134+
script: |
135+
Write-Host "====================================="
136+
Write-Host "[TEST PIPELINE] Downloaded Artifacts:"
137+
Write-Host "====================================="
138+
139+
# List wheel files
140+
$wheelsPath = "$(Build.SourcesDirectory)/artifacts/dist"
141+
if (Test-Path $wheelsPath) {
142+
$wheels = Get-ChildItem -Path $wheelsPath -Filter "*.whl" -Recurse
143+
144+
Write-Host "`n[WHEELS] Total wheel files found: $($wheels.Count)"
145+
foreach ($wheel in $wheels) {
146+
$size = [math]::Round($wheel.Length / 1MB, 2)
147+
Write-Host " - $($wheel.Name) (${size} MB)"
148+
}
149+
150+
# Copy wheels to dist folder for ESRP
151+
Write-Host "`nCopying wheels to $(Build.SourcesDirectory)/dist..."
152+
New-Item -ItemType Directory -Force -Path "$(Build.SourcesDirectory)/dist" | Out-Null
153+
Copy-Item -Path "$wheelsPath/*.whl" -Destination "$(Build.SourcesDirectory)/dist/" -Force
154+
155+
} else {
156+
Write-Error "Wheel directory not found at: $wheelsPath"
157+
exit 1
158+
}
159+
160+
# List symbol files
161+
$symbolsPath = "$(Build.SourcesDirectory)/artifacts/symbols"
162+
if (Test-Path $symbolsPath) {
163+
$symbols = Get-ChildItem -Path $symbolsPath -Filter "*.pdb" -Recurse
164+
165+
Write-Host "`n[SYMBOLS] Total PDB files found: $($symbols.Count)"
166+
foreach ($symbol in $symbols) {
167+
$size = [math]::Round($symbol.Length / 1KB, 2)
168+
Write-Host " - $($symbol.Name) (${size} KB)"
169+
}
170+
171+
# Copy symbols to symbols folder for publishing
172+
Write-Host "`nCopying symbols to $(Build.SourcesDirectory)/symbols..."
173+
New-Item -ItemType Directory -Force -Path "$(Build.SourcesDirectory)/symbols" | Out-Null
174+
Copy-Item -Path "$symbolsPath/*.pdb" -Destination "$(Build.SourcesDirectory)/symbols/" -Force
175+
176+
} else {
177+
Write-Warning "Symbol directory not found at: $symbolsPath"
178+
Write-Warning "Symbol publishing will be skipped if no PDB files found"
179+
}
180+
181+
Write-Host "`n====================================="
182+
Write-Host "Summary:"
183+
Write-Host "Wheels: $($wheels.Count) files"
184+
Write-Host "Symbols: $(if ($symbols) { $symbols.Count } else { 0 }) files"
185+
Write-Host "====================================="
186+
187+
# Step 4: Verify wheel integrity
188+
- task: PowerShell@2
189+
displayName: '[TEST] Verify Wheel Integrity'
190+
inputs:
191+
targetType: 'inline'
192+
script: |
193+
Write-Host "[TEST] Verifying wheel file integrity..."
194+
195+
$wheels = Get-ChildItem -Path "$(Build.SourcesDirectory)/dist" -Filter "*.whl"
196+
$allValid = $true
197+
198+
foreach ($wheel in $wheels) {
199+
# Check if wheel is a valid ZIP file
200+
try {
201+
Add-Type -AssemblyName System.IO.Compression.FileSystem
202+
$zip = [System.IO.Compression.ZipFile]::OpenRead($wheel.FullName)
203+
$entryCount = $zip.Entries.Count
204+
$zip.Dispose()
205+
206+
Write-Host "✓ $($wheel.Name) - Valid ($entryCount entries)"
207+
}
208+
catch {
209+
Write-Error "✗ $($wheel.Name) - INVALID: $_"
210+
$allValid = $false
211+
}
212+
}
213+
214+
if (-not $allValid) {
215+
Write-Error "One or more wheel files are corrupted"
216+
exit 1
217+
}
218+
219+
Write-Host "`nAll wheels verified successfully!"
220+
221+
# Step 5: Publish Symbols (if enabled and symbols exist)
222+
- ${{ if eq(parameters.publishSymbols, true) }}:
223+
- template: /OneBranchPipelines/steps/symbol-publishing-step.yml@self
224+
parameters:
225+
SymbolsFolder: '$(Build.SourcesDirectory)/symbols'
226+
227+
# Step 6: Copy wheels to ob_outputDirectory for OneBranch artifact publishing
228+
- task: CopyFiles@2
229+
displayName: '[TEST] Stage Wheels for Dummy Release'
230+
inputs:
231+
SourceFolder: '$(Build.SourcesDirectory)/dist'
232+
Contents: '*.whl'
233+
TargetFolder: '$(ob_outputDirectory)/release'
234+
flattenFolders: true
235+
236+
# Step 7: ESRP Dummy Release Task (only if performDummyRelease is true)
237+
# ⚠️ IMPORTANT: Uses Maven ContentType for testing - NOT PyPI!
238+
- ${{ if eq(parameters.performDummyRelease, true) }}:
239+
- task: EsrpRelease@9
240+
displayName: '[TEST] ESRP Dummy Release (Maven - NOT PyPI)'
241+
inputs:
242+
connectedservicename: '$(ESRPConnectedServiceName)'
243+
usemanagedidentity: true
244+
keyvaultname: '$(AuthAKVName)'
245+
signcertname: '$(AuthSignCertName)'
246+
clientid: '$(EsrpClientId)'
247+
Intent: 'PackageDistribution'
248+
# ⚠️ CRITICAL: ContentType is Maven (NOT PyPI) for safe testing
249+
# This ensures no accidental production releases to PyPI
250+
ContentType: 'Maven'
251+
ContentSource: 'Folder'
252+
FolderLocation: '$(Build.SourcesDirectory)/dist'
253+
WaitForReleaseCompletion: true
254+
Owners: '$(owner)'
255+
Approvers: '$(approver)'
256+
ServiceEndpointUrl: 'https://api.esrp.microsoft.com'
257+
MainPublisher: 'ESRPRELPACMAN'
258+
DomainTenantId: '$(DomainTenantId)'
259+
260+
# Step 8: Show test release status
261+
- ${{ if eq(parameters.performDummyRelease, true) }}:
262+
- task: PowerShell@2
263+
displayName: '[TEST] Dummy Release Summary'
264+
inputs:
265+
targetType: 'inline'
266+
script: |
267+
Write-Host "====================================="
268+
Write-Host "⚠️ TEST PIPELINE - DUMMY RELEASE COMPLETED ⚠️"
269+
Write-Host "====================================="
270+
Write-Host "Package: mssql-python (TEST)"
271+
Write-Host "Version: ${{ parameters.packageVersion }}"
272+
Write-Host "ContentType: Maven (NOT PyPI - Safe for Testing)"
273+
Write-Host "Owners: $(owner)"
274+
Write-Host "Approvers: $(approver)"
275+
Write-Host "Symbols Published: ${{ parameters.publishSymbols }}"
276+
Write-Host "====================================="
277+
Write-Host ""
278+
Write-Host "⚠️ IMPORTANT: This was a DUMMY release using Maven ContentType"
279+
Write-Host " NO packages were released to PyPI"
280+
Write-Host ""
281+
Write-Host "What was tested:"
282+
Write-Host "✓ Artifact download from build pipeline"
283+
Write-Host "✓ Wheel integrity verification"
284+
if ("${{ parameters.publishSymbols }}" -eq "True") {
285+
Write-Host "✓ Symbol publishing to SqlClientDrivers org"
286+
}
287+
Write-Host "✓ ESRP release workflow (Maven ContentType)"
288+
Write-Host ""
289+
Write-Host "Next steps:"
290+
Write-Host "1. Verify dummy release in ESRP portal"
291+
Write-Host "2. Check ESRP approval workflow completion"
292+
Write-Host "3. Verify symbols in SqlClientDrivers org (if published)"
293+
Write-Host "4. For PRODUCTION release, use official-release-pipeline.yml"
294+
Write-Host "====================================="
295+
296+
- ${{ if eq(parameters.performDummyRelease, false) }}:
297+
- task: PowerShell@2
298+
displayName: '[TEST] Dry Run - Dummy Release Skipped'
299+
inputs:
300+
targetType: 'inline'
301+
script: |
302+
Write-Host "====================================="
303+
Write-Host "⚠️ TEST PIPELINE - DRY RUN MODE ⚠️"
304+
Write-Host "====================================="
305+
Write-Host "Package: mssql-python (TEST)"
306+
Write-Host "Version: ${{ parameters.packageVersion }}"
307+
Write-Host ""
308+
Write-Host "Actions performed:"
309+
Write-Host "✓ Downloaded wheels from build pipeline"
310+
Write-Host "✓ Verified wheel integrity"
311+
Write-Host "✓ Downloaded symbols from build pipeline"
312+
if ("${{ parameters.publishSymbols }}" -eq "True") {
313+
Write-Host "✓ Published symbols to SqlClientDrivers org"
314+
}
315+
Write-Host "✗ ESRP dummy release NOT performed (parameter disabled)"
316+
Write-Host ""
317+
Write-Host "To test ESRP workflow:"
318+
Write-Host "1. Set 'performDummyRelease' parameter to true"
319+
Write-Host "2. Re-run this TEST pipeline"
320+
Write-Host ""
321+
Write-Host "For PRODUCTION release:"
322+
Write-Host "1. Use official-release-pipeline.yml instead"
323+
Write-Host "2. Official pipeline uses PyPI ContentType"
324+
Write-Host "====================================="

0 commit comments

Comments
 (0)