77name : $(Build.SourceBranchName)-$(Date:yyyyMMdd).$(Rev:r)
88
99parameters :
10- - name : Sign
11- displayName : " Signed"
12- type : boolean
13- default : false
10+ - name : SigningCertificate
11+ displayName : " Code signing certificate"
12+ type : string
13+ default : ' Unsigned'
14+ values :
15+ - ' PythonSoftwareFoundation'
16+ - ' TestSign'
17+ - ' Unsigned'
1418- name : Publish
1519 displayName : " Publish"
1620 type : boolean
@@ -31,10 +35,10 @@ parameters:
3135 displayName : " Force version (else uses tag)"
3236 type : string
3337 default : (tag)
34- - name : TestSign
35- displayName : " Test Signed "
36- type : boolean
37- default : false
38+ - name : SigningDescription
39+ displayName : " Signature description "
40+ type : string
41+ default : ' (default) '
3842
3943
4044variables :
@@ -45,12 +49,12 @@ variables:
4549 PIP_REQUIRE_VIRTUALENV : false
4650 PIP_VERBOSE : true
4751 PYMSBUILD_VERBOSE : true
48- PYMSBUILD_TEMP_DIR : $(Build.BinariesDirectory)
49- DIST_DIR : $(Build.ArtifactStagingDirectory)
50- LAYOUT_DIR : $(Build.BinariesDirectory)\layout
51- TEST_MSIX_DIR : $(Build.BinariesDirectory)\test_msix
5252 ${{ if ne(parameters.OverrideRef, '(tag)') }} :
5353 OVERRIDE_REF : refs/tags/${{ parameters.OverrideRef }}
54+ ${{ if eq(parameters.SigningDescription, '(default)') }} :
55+ SigningDescription : " PyManager $(Build.BuildNumber)"
56+ ${{ else }} :
57+ SigningDescription : ${{ parameters.SigningDescription }}
5458
5559
5660stages :
@@ -64,12 +68,16 @@ stages:
6468 vmImage : ' windows-latest'
6569
6670 variables :
67- - ${{ if eq(parameters.TestSign, 'true') }} :
71+ - name : DIST_DIR
72+ value : $(Build.ArtifactStagingDirectory)
73+ - name : PYMSBUILD_TEMP_DIR
74+ value : $(Build.BinariesDirectory)
75+ - name : LAYOUT_DIR
76+ value : $(Build.BinariesDirectory)\layout
77+ - ${{ if eq(parameters.SigningCertificate, 'TestSign') }} :
6878 - group : CPythonTestSign
69- - ${{ elseif eq(parameters.Sign , 'true ') }} :
79+ - ${{ elseif eq(parameters.SigningCertificate , 'PythonSoftwareFoundation ') }} :
7080 - group : CPythonSign
71- - ${{ if eq(parameters.Publish, 'true') }} :
72- - group : PythonOrgPublish
7381
7482
7583 steps :
@@ -118,39 +126,6 @@ stages:
118126 python -m pytest -vv
119127 displayName: 'Run pre-test'
120128
121- - ${{ if or(eq(parameters.Sign, 'true'), eq(parameters.TestSign, 'true')) }} :
122- - powershell : |
123- dotnet tool install --global --prerelease sign
124- cd (mkdir -Force signing)
125- "*.exe", "*.pyd" | Out-File -Encoding UTF8 "signlist1.txt"
126- Write-Host "##vso[task.setvariable variable=SIGNLIST1]$(gi signlist1.txt)"
127- "*.msix" | Out-File -Encoding UTF8 "signlist2.txt"
128- Write-Host "##vso[task.setvariable variable=SIGNLIST2]$(gi signlist2.txt)"
129- "*.msi" | Out-File -Encoding UTF8 "signlist3.txt"
130- Write-Host "##vso[task.setvariable variable=SIGNLIST3]$(gi signlist3.txt)"
131- displayName: 'Install signing tool and generate files'
132- workingDirectory: $(Build.BinariesDirectory)
133-
134- - task : AzureCLI@2
135- displayName : ' Azure Login (1/2)'
136- inputs :
137- azureSubscription : ' Python Signing'
138- scriptType : ' ps'
139- scriptLocation : ' inlineScript'
140- inlineScript : |
141- "##vso[task.setvariable variable=AZURE_CLIENT_ID;issecret=true]${env:servicePrincipalId}"
142- "##vso[task.setvariable variable=AZURE_ID_TOKEN;issecret=true]${env:idToken}"
143- "##vso[task.setvariable variable=AZURE_TENANT_ID;issecret=true]${env:tenantId}"
144- addSpnToEnvironment : true
145-
146- - powershell : >
147- az login --service-principal
148- -u $(AZURE_CLIENT_ID)
149- --tenant $(AZURE_TENANT_ID)
150- --allow-no-subscriptions
151- --federated-token $(AZURE_ID_TOKEN)
152- displayName: 'Azure Login (2/2)'
153-
154129 - powershell : |
155130 python make.py
156131 displayName: 'Build package'
@@ -160,17 +135,13 @@ stages:
160135 ${{ if or(eq(parameters.Sign, 'true'), eq(parameters.TestSign, 'true')) }}:
161136 PYMANAGER_APPX_PUBLISHER: $(TrustedSigningCertificateSubject)
162137
163- - ${{ if or(eq(parameters.Sign, 'true'), eq(parameters.TestSign, 'true')) }} :
164- - powershell : >
165- dir -r *.exe, *.pyd | %{
166- sign code trusted-signing "$_"
167- -fd sha256 -t http://timestamp.acs.microsoft.com -td sha256
168- -tse "$(TrustedSigningUri)" -tsa "$(TrustedSigningAccount)" -tscp "$(TrustedSigningCertificateName)"
169- -d "PyManager $(Build.BuildNumber)"
170- -fl $env:SIGNLIST1
171- }
172- displayName: 'Sign binaries'
173- workingDirectory: $(LAYOUT_DIR)
138+ - template : sign-files.yml
139+ parameters :
140+ Include : " *.exe, *.pyd"
141+ Filter : " *.exe;*.pyd"
142+ # Only install the first time
143+ InstallTool : true
144+ SigningCertificate : ${{ parameters.SigningCertificate }}
174145
175146 - powershell : |
176147 python make-msix.py
@@ -191,57 +162,71 @@ stages:
191162 ${{ if or(eq(parameters.Sign, 'true'), eq(parameters.TestSign, 'true')) }}:
192163 PYMANAGER_APPX_PUBLISHER: $(TrustedSigningCertificateSubject)
193164
194- - ${{ if or(eq(parameters.Sign, 'true'), eq(parameters.TestSign, 'true')) }} :
195- - powershell : >
196- dir *.msix | %{
197- sign code trusted-signing "$_"
198- -fd sha256 -t http://timestamp.acs.microsoft.com -td sha256
199- -tse "$(TrustedSigningUri)" -tsa "$(TrustedSigningAccount)" -tscp "$(TrustedSigningCertificateName)"
200- -d "PyManager $(Build.BuildNumber)"
201- -fl $env:SIGNLIST2
202- }
203- displayName: 'Sign MSIX package'
204- workingDirectory: $(DIST_DIR)
205-
206- - powershell : >
207- dir *.msi | %{
208- sign code trusted-signing "$_"
209- -fd sha256 -t http://timestamp.acs.microsoft.com -td sha256
210- -tse "$(TrustedSigningUri)" -tsa "$(TrustedSigningAccount)" -tscp "$(TrustedSigningCertificateName)"
211- -d "PyManager $(Build.BuildNumber)"
212- -fl $env:SIGNLIST3
213- }
214- displayName: 'Sign MSI package'
215- workingDirectory: $(DIST_DIR)
216-
217- - ${{ if eq(parameters.TestSign, 'true') }} :
165+ - template : sign-files.yml
166+ parameters :
167+ Include : " *.msix"
168+ Filter : " *.msix"
169+ InstallTool : false
170+ SigningCertificate : ${{ parameters.SigningCertificate }}
171+ WorkingDir : $(DIST_DIR)
172+
173+ - template : sign-files.yml
174+ parameters :
175+ Include : " *.msi"
176+ Filter : " *.msi"
177+ InstallTool : false
178+ SigningCertificate : ${{ parameters.SigningCertificate }}
179+ WorkingDir : $(DIST_DIR)
180+
181+ - ${{ if eq(parameters.SigningCertificate, 'TestSign') }} :
218182 - powershell : Write-Host "##vso[build.addbuildtag]test-signed"
219183 displayName : ' Add test-signed build tag'
220- - ${{ elseif eq(parameters.Sign , 'true ') }} :
184+ - ${{ elseif eq(parameters.SigningCertificate , 'PythonSoftwareFoundation ') }} :
221185 - powershell : Write-Host "##vso[build.addbuildtag]signed"
222186 displayName : ' Add signed build tag'
223187
224188 - publish : $(DIST_DIR)
225189 artifact : dist
226190 displayName : Publish distribution artifacts
227191
228- - ${{ if eq(parameters.PostTest, 'true') }} :
229- - ${{ if and(ne(parameters.TestSign, 'true'), eq(parameters.Sign, 'true')) }} :
230- - powershell : |
231- $msix = dir "$(DIST_DIR)\*.msix" | ?{ -not ($_.BaseName -match '.+-store') } | select -first 1
232- Add-AppxPackage $msix
233- displayName: 'Install signed MSIX'
192+ - job : PostTest
193+ dependsOn : Build
234194
235- - ${{ else }} :
236- - powershell : |
237- $msix = dir "$(DIST_DIR)\*.msix" | ?{ -not ($_.BaseName -match '.+-store') } | select -first 1
238- cp $msix "${msix}.zip"
239- Expand-Archive "${msix}.zip" (mkdir -Force $env:TEST_MSIX)
240- Add-AppxPackage -Register "${env:TEST_MSIX}\appxmanifest.xml"
241- displayName: 'Register unsigned MSIX'
242- env:
243- TEST_MSIX: $(TEST_MSIX_DIR)
195+ pool :
196+ vmImage : ' windows-latest '
197+
198+ variables :
199+ DIST_DIR : $(Pipeline.Workspace)\dist
200+
201+ steps :
202+ - checkout : none
203+ - download : dist
244204
205+ - powershell : |
206+ # Ensure we aren't currently installed
207+ $msix = Get-AppxPackage PythonSoftwareFoundation.PythonManager -EA SilentlyContinue
208+ if ($msix) {
209+ Remove-AppxPackage $msix
210+ }
211+ displayName: 'Remove existing PyManager install'
212+
213+ - ${{ if eq(parameters.SigningCertificate, 'PythonSoftwareFoundation') }} :
214+ - powershell : |
215+ $msix = dir "$(DIST_DIR)\*.msix" | ?{ -not ($_.BaseName -match '.+-store') } | select -first 1
216+ Add-AppxPackage $msix
217+ displayName: 'Install signed MSIX'
218+
219+ - ${{ else }} :
220+ - powershell : |
221+ $msix = dir "$(DIST_DIR)\*.msix" | ?{ -not ($_.BaseName -match '.+-store') } | select -first 1
222+ cp $msix "${msix}.zip"
223+ Expand-Archive "${msix}.zip" (mkdir -Force $env:TEST_MSIX)
224+ Add-AppxPackage -Register "${env:TEST_MSIX}\appxmanifest.xml"
225+ displayName: 'Register unsigned MSIX'
226+ env:
227+ TEST_MSIX: $(TEST_MSIX_DIR)
228+
229+ - ${{ if eq(parameters.PostTest, 'true') }} :
245230 - powershell : |
246231 $p = Get-AppxPackage PythonSoftwareFoundation.PythonManager
247232 $p
@@ -352,21 +337,46 @@ stages:
352337 Get-AppxPackage PythonSoftwareFoundation.PythonManager | Remove-AppxPackage
353338 displayName: 'Remove MSIX'
354339
355- - powershell : |
356- $files = gci -File * -EA SilentlyContinue
357- $hashes = $files | `
358- Sort-Object Name | `
359- Format-Table Name, @{
360- Label="SHA256";
361- Expression={(Get-FileHash $_ -Algorithm SHA256).Hash}
362- }, Length -AutoSize | `
363- Out-String -Width 4096
364- $hashes
365- workingDirectory: $(DIST_DIR)
366- displayName: 'Generate hashes (SHA256)'
367-
368- - ${{ if eq(parameters.Publish, 'true') }} :
369- - ${{ if eq(parameters.Sign, 'true') }} :
340+
341+ - ${{ if eq(parameters.Publish, 'true') }} :
342+ - job : Publish
343+ dependsOn : PostTest
344+
345+ pool :
346+ vmImage : ' windows-latest'
347+
348+ variables :
349+ - ${{ if eq(parameters.Publish, 'true') }} :
350+ - group : PythonOrgPublish
351+
352+ steps :
353+ - checkout : self
354+
355+ - task : NugetToolInstaller@0
356+ displayName : ' Install Nuget'
357+
358+ - powershell : |
359+ nuget install python -x -noninteractive -o host_python
360+ $py = Get-Item host_python\python\tools
361+ Write-Host "Adding $py to PATH"
362+ Write-Host "##vso[task.prependpath]$py"
363+ displayName: Set up Python for scripts
364+ workingDirectory: $(Build.BinariesDirectory)
365+
366+ - powershell : |
367+ $files = gci -File * -EA SilentlyContinue
368+ $hashes = $files | `
369+ Sort-Object Name | `
370+ Format-Table Name, @{
371+ Label="SHA256";
372+ Expression={(Get-FileHash $_ -Algorithm SHA256).Hash}
373+ }, Length -AutoSize | `
374+ Out-String -Width 4096
375+ $hashes
376+ workingDirectory: $(DIST_DIR)
377+ displayName: 'Generate hashes (SHA256)'
378+
379+ - ${{ if eq(parameters.SigningCertificate, 'PythonSoftwareFoundation') }} :
370380 - task : DownloadSecureFile@1
371381 name : sshkey
372382 inputs :
@@ -404,10 +414,10 @@ stages:
404414 UPLOAD_HOST_KEY: $(PyDotOrgHostKey)
405415 UPLOAD_USER: $(PyDotOrgUsername)
406416 UPLOAD_KEYFILE: $(sshkey.secureFilePath)
407- ${{ if ne(parameters.Sign , 'true ') }}:
417+ ${{ if ne(parameters.SigningCertificate , 'PythonSoftwareFoundation ') }}:
408418 NO_UPLOAD: 1
409419
410- - ${{ if eq(parameters.Sign , 'true ') }} :
420+ - ${{ if eq(parameters.SigningCertificate , 'PythonSoftwareFoundation ') }} :
411421 - powershell : Write-Host "##vso[build.addbuildtag]published"
412422 displayName : ' Add published tag'
413423 - ${{ else }} :
0 commit comments