Skip to content

Implement Windows release builds in Azure Pipelines #14065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .azure-pipelines/windows-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Release_$(Build.SourceBranchName)_$(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)

# QUEUE TIME VARIABLES
# variables:
# GitRemote: python
# SourceTag:
# DoPGO: true
# SigningCertificate: 'Python Software Foundation'
# SigningDescription: 'Built: $(Build.BuildNumber)'
# DoLayout: true
# DoMSIX: true
# DoNuget: true
# DoEmbed: true
# DoMSI: true
# DoPublish: false

trigger: none
pr: none

stages:
- stage: Build
displayName: Build binaries
jobs:
- template: windows-release/stage-build.yml

- stage: Sign
displayName: Sign binaries
dependsOn: Build
jobs:
- template: windows-release/stage-sign.yml

- stage: Layout
displayName: Generate layouts
dependsOn: Sign
jobs:
- template: windows-release/stage-layout-full.yml
- template: windows-release/stage-layout-embed.yml
- template: windows-release/stage-layout-nuget.yml

- stage: Pack
dependsOn: Layout
jobs:
- template: windows-release/stage-pack-nuget.yml

- stage: Test
dependsOn: Pack
jobs:
- template: windows-release/stage-test-embed.yml
- template: windows-release/stage-test-nuget.yml

- stage: Layout_MSIX
displayName: Generate MSIX layouts
dependsOn: Sign
condition: and(succeeded(), eq(variables['DoMSIX'], 'true'))
jobs:
- template: windows-release/stage-layout-msix.yml

- stage: Pack_MSIX
displayName: Package MSIX
dependsOn: Layout_MSIX
jobs:
- template: windows-release/stage-pack-msix.yml

- stage: Build_MSI
displayName: Build MSI installer
dependsOn: Sign
condition: and(succeeded(), eq(variables['DoMSI'], 'true'))
jobs:
- template: windows-release/stage-msi.yml

- stage: Test_MSI
displayName: Test MSI installer
dependsOn: Build_MSI
jobs:
- template: windows-release/stage-test-msi.yml

- stage: PublishPyDotOrg
displayName: Publish to python.org
dependsOn: ['Test_MSI', 'Test']
condition: and(succeeded(), eq(variables['DoPublish'], 'true'))
jobs:
- template: windows-release/stage-publish-pythonorg.yml

- stage: PublishNuget
displayName: Publish to nuget.org
dependsOn: Test
condition: and(succeeded(), eq(variables['DoPublish'], 'true'))
jobs:
- template: windows-release/stage-publish-nugetorg.yml

- stage: PublishStore
displayName: Publish to Store
dependsOn: Pack_MSIX
condition: and(succeeded(), eq(variables['DoPublish'], 'true'))
jobs:
- template: windows-release/stage-publish-store.yml
83 changes: 83 additions & 0 deletions .azure-pipelines/windows-release/build-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
parameters:
ShouldPGO: false

steps:
- template: ./checkout.yml

- powershell: |
$d = (.\PCbuild\build.bat -V) | %{ if($_ -match '\s+(\w+):\s*(.+)\s*$') { @{$Matches[1] = $Matches[2];} }};
Write-Host "##vso[task.setvariable variable=VersionText]$($d.PythonVersion)"
Write-Host "##vso[task.setvariable variable=VersionNumber]$($d.PythonVersionNumber)"
Write-Host "##vso[task.setvariable variable=VersionHex]$($d.PythonVersionHex)"
Write-Host "##vso[task.setvariable variable=VersionUnique]$($d.PythonVersionUnique)"
Write-Host "##vso[build.addbuildtag]$($d.PythonVersion)"
Write-Host "##vso[build.addbuildtag]$($d.PythonVersion)-$(Name)"
displayName: 'Extract version numbers'

- ${{ if eq(parameters.ShouldPGO, 'false') }}:
- powershell: |
$env:SigningCertificate = $null
.\PCbuild\build.bat -v -p $(Platform) -c $(Configuration)
displayName: 'Run build'
env:
IncludeUwp: true
Py_OutDir: '$(Build.BinariesDirectory)\bin'

- ${{ if eq(parameters.ShouldPGO, 'true') }}:
- powershell: |
$env:SigningCertificate = $null
.\PCbuild\build.bat -v -p $(Platform) --pgo
displayName: 'Run build with PGO'
env:
IncludeUwp: true
Py_OutDir: '$(Build.BinariesDirectory)\bin'

- powershell: |
$kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10
$tool = (gci -r "$kitroot\Bin\*\x64\signtool.exe" | sort FullName -Desc | select -First 1)
if (-not $tool) {
throw "SDK is not available"
}
Write-Host "##vso[task.prependpath]$($tool.Directory)"
displayName: 'Add WinSDK tools to path'

- powershell: |
$env:SigningCertificate = $null
.\python.bat PC\layout -vv -t "$(Build.BinariesDirectory)\catalog" --catalog "${env:CAT}.cdf" --preset-default
makecat "${env:CAT}.cdf"
del "${env:CAT}.cdf"
if (-not (Test-Path "${env:CAT}.cat")) {
throw "Failed to build catalog file"
}
displayName: 'Generate catalog'
env:
CAT: $(Build.BinariesDirectory)\bin\$(Arch)\python

- task: PublishBuildArtifacts@1
displayName: 'Publish binaries'
condition: and(succeeded(), not(and(eq(variables['Configuration'], 'Release'), variables['SigningCertificate'])))
inputs:
PathtoPublish: '$(Build.BinariesDirectory)\bin\$(Arch)'
ArtifactName: bin_$(Name)

- task: PublishBuildArtifacts@1
displayName: 'Publish binaries for signing'
condition: and(succeeded(), and(eq(variables['Configuration'], 'Release'), variables['SigningCertificate']))
inputs:
PathtoPublish: '$(Build.BinariesDirectory)\bin\$(Arch)'
ArtifactName: unsigned_bin_$(Name)

- task: CopyFiles@2
displayName: 'Layout Artifact: symbols'
inputs:
sourceFolder: $(Build.BinariesDirectory)\bin\$(Arch)
targetFolder: $(Build.ArtifactStagingDirectory)\symbols\$(Name)
flatten: true
contents: |
**\*.pdb

- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: symbols'
inputs:
PathToPublish: '$(Build.ArtifactStagingDirectory)\symbols'
ArtifactName: symbols
21 changes: 21 additions & 0 deletions .azure-pipelines/windows-release/checkout.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
parameters:
depth: 3

steps:
- checkout: none

- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(SourceTag) --single-branch https://github.com/$(GitRemote)/cpython.git .
displayName: 'git clone ($(GitRemote)/$(SourceTag))'
condition: and(succeeded(), and(variables['GitRemote'], variables['SourceTag']))

- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(SourceTag) --single-branch $(Build.Repository.Uri) .
displayName: 'git clone (<default>/$(SourceTag))'
condition: and(succeeded(), and(not(variables['GitRemote']), variables['SourceTag']))

- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(Build.SourceBranchName) --single-branch https://github.com/$(GitRemote)/cpython.git .
displayName: 'git clone ($(GitRemote)/<default>)'
condition: and(succeeded(), and(variables['GitRemote'], not(variables['SourceTag'])))

- script: git clone --progress -v --depth ${{ parameters.depth }} --branch $(Build.SourceBranchName) --single-branch $(Build.Repository.Uri) .
displayName: 'git clone'
condition: and(succeeded(), and(not(variables['GitRemote']), not(variables['SourceTag'])))
17 changes: 17 additions & 0 deletions .azure-pipelines/windows-release/find-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Locate the Windows SDK and add its binaries directory to PATH
#
# `toolname` can be overridden to use a different marker file.

parameters:
toolname: signtool.exe

steps:
- powershell: |
$kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10
$tool = (gci -r "$kitroot\Bin\*\${{ parameters.toolname }}" | sort FullName -Desc | select -First 1)
if (-not $tool) {
throw "SDK is not available"
}
Write-Host "##vso[task.prependpath]$($tool.Directory)"
Write-Host "Adding $($tool.Directory) to PATH"
displayName: 'Add WinSDK tools to path'
20 changes: 20 additions & 0 deletions .azure-pipelines/windows-release/layout-command.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
steps:
- powershell: >
Write-Host (
'##vso[task.setvariable variable=LayoutCmd]&
"{0}"
"{1}\PC\layout"
-vv
--source "{1}"
--build "{2}"
--temp "{3}"
--include-cat "{2}\python.cat"
--doc-build "{4}"'
-f (
"$(PYTHON)",
"$(Build.SourcesDirectory)",
(Split-Path -Parent "$(PYTHON)"),
"$(Build.BinariesDirectory)\layout-temp",
"$(Build.BinariesDirectory)\doc"
))
displayName: 'Set LayoutCmd'
13 changes: 13 additions & 0 deletions .azure-pipelines/windows-release/mingw-lib.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
parameters:
DllToolOpt: -m i386:x86-64
#DllToolOpt: -m i386 --as-flags=--32

steps:
- powershell: |
git clone https://github.com/python/cpython-bin-deps --branch binutils --single-branch --depth 1 --progress -v "binutils"
gci "bin\$(Arch)\python*.dll" | %{
& "binutils\gendef.exe" $_ | Out-File -Encoding ascii tmp.def
& "binutils\dlltool.exe" --dllname $($_.BaseName).dll --def tmp.def --output-lib "$($_.Directory)\lib$($_.BaseName).a" ${{ parameters.DllToolOpt }}
}
displayName: 'Generate MinGW import library'
workingDirectory: $(Build.BinariesDirectory)
142 changes: 142 additions & 0 deletions .azure-pipelines/windows-release/msi-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
steps:
- template: ./checkout.yml

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: doc'
inputs:
artifactName: doc
downloadPath: $(Build.BinariesDirectory)

- task: CopyFiles@2
displayName: 'Merge documentation files'
inputs:
sourceFolder: $(Build.BinariesDirectory)\doc
targetFolder: $(Build.SourcesDirectory)\Doc\build
contents: |
htmlhelp\*.chm

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: bin_win32'
inputs:
artifactName: bin_win32
downloadPath: $(Build.BinariesDirectory)

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: bin_win32_d'
inputs:
artifactName: bin_win32_d
downloadPath: $(Build.BinariesDirectory)

- task: CopyFiles@2
displayName: 'Merge win32 debug files'
inputs:
sourceFolder: $(Build.BinariesDirectory)\bin_win32_d
targetFolder: $(Build.BinariesDirectory)\bin_win32
contents: |
**\*_d.*

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: bin_amd64'
inputs:
artifactName: bin_amd64
downloadPath: $(Build.BinariesDirectory)

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: bin_amd64_d'
inputs:
artifactName: bin_amd64_d
downloadPath: $(Build.BinariesDirectory)

- task: CopyFiles@2
displayName: 'Merge amd64 debug files'
inputs:
sourceFolder: $(Build.BinariesDirectory)\bin_amd64_d
targetFolder: $(Build.BinariesDirectory)\bin_amd64
contents: |
**\*_d.*

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: tcltk_lib_win32'
inputs:
artifactName: tcltk_lib_win32
downloadPath: $(Build.BinariesDirectory)

- task: DownloadBuildArtifacts@0
displayName: 'Download artifact: tcltk_lib_amd64'
inputs:
artifactName: tcltk_lib_amd64
downloadPath: $(Build.BinariesDirectory)

- script: |
ren bin_win32 win32
ren bin_amd64 amd64
displayName: 'Correct artifact directory names'
workingDirectory: $(Build.BinariesDirectory)

- script: |
call Tools\msi\get_externals.bat
call PCbuild\find_python.bat
echo ##vso[task.setvariable variable=PYTHON]%PYTHON%
call PCbuild/find_msbuild.bat
echo ##vso[task.setvariable variable=MSBUILD]%MSBUILD%
displayName: 'Get external dependencies'

- script: |
%PYTHON% -m pip install blurb
%PYTHON% -m blurb merge -f Misc\NEWS
displayName: 'Merge NEWS file'

- script: |
%MSBUILD% Tools\msi\launcher\launcher.wixproj
displayName: 'Build launcher installer'
env:
Platform: x86
Py_OutDir: $(Build.BinariesDirectory)

- script: |
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true /p:BuildForRelease=true
%MSBUILD% Tools\msi\bundle\releaseweb.wixproj /t:Rebuild /p:RebuildAll=false /p:BuildForRelease=true
displayName: 'Build win32 installer'
env:
Platform: x86
Py_OutDir: $(Build.BinariesDirectory)
PYTHON: $(Build.BinariesDirectory)\win32\python.exe
PYTHONHOME: $(Build.SourcesDirectory)
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_win32

- script: |
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true /p:BuildForRelease=true
%MSBUILD% Tools\msi\bundle\releaseweb.wixproj /t:Rebuild /p:RebuildAll=false /p:BuildForRelease=true
displayName: 'Build amd64 installer'
env:
Platform: x64
Py_OutDir: $(Build.BinariesDirectory)
PYTHON: $(Build.BinariesDirectory)\amd64\python.exe
PYTHONHOME: $(Build.SourcesDirectory)
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_amd64

- task: CopyFiles@2
displayName: 'Assemble artifact: msi (1/2)'
inputs:
sourceFolder: $(Build.BinariesDirectory)\win32\en-us
targetFolder: $(Build.ArtifactStagingDirectory)\msi\win32
contents: |
*.msi
*.cab
*.exe

- task: CopyFiles@2
displayName: 'Assemble artifact: msi (2/2)'
inputs:
sourceFolder: $(Build.BinariesDirectory)\amd64\en-us
targetFolder: $(Build.ArtifactStagingDirectory)\msi\amd64
contents: |
*.msi
*.cab
*.exe

- task: PublishBuildArtifacts@1
displayName: 'Publish MSI'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\msi'
ArtifactName: msi
Loading