summaryrefslogtreecommitdiff
path: root/.azure-pipelines
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2019-06-14 08:29:20 -0700
committerGitHub <noreply@github.com>2019-06-14 08:29:20 -0700
commit21a92f8cda525d25a165b773fbe1bfffd303a000 (patch)
tree84d08fcb306ee46d6f5147d734745af0c3f64b7b /.azure-pipelines
parentf0749da9a535375f05a2015e8960e8ae54877349 (diff)
downloadcpython-git-21a92f8cda525d25a165b773fbe1bfffd303a000.tar.gz
Implement Windows release builds in Azure Pipelines (GH-14065)
Diffstat (limited to '.azure-pipelines')
-rw-r--r--.azure-pipelines/windows-release.yml96
-rw-r--r--.azure-pipelines/windows-release/build-steps.yml83
-rw-r--r--.azure-pipelines/windows-release/checkout.yml21
-rw-r--r--.azure-pipelines/windows-release/find-sdk.yml17
-rw-r--r--.azure-pipelines/windows-release/layout-command.yml20
-rw-r--r--.azure-pipelines/windows-release/mingw-lib.yml13
-rw-r--r--.azure-pipelines/windows-release/msi-steps.yml142
-rw-r--r--.azure-pipelines/windows-release/stage-build.yml157
-rw-r--r--.azure-pipelines/windows-release/stage-layout-embed.yml56
-rw-r--r--.azure-pipelines/windows-release/stage-layout-full.yml62
-rw-r--r--.azure-pipelines/windows-release/stage-layout-msix.yml86
-rw-r--r--.azure-pipelines/windows-release/stage-layout-nuget.yml44
-rw-r--r--.azure-pipelines/windows-release/stage-msi.yml36
-rw-r--r--.azure-pipelines/windows-release/stage-pack-msix.yml127
-rw-r--r--.azure-pipelines/windows-release/stage-pack-nuget.yml41
-rw-r--r--.azure-pipelines/windows-release/stage-publish-nugetorg.yml28
-rw-r--r--.azure-pipelines/windows-release/stage-publish-pythonorg.yml34
-rw-r--r--.azure-pipelines/windows-release/stage-publish-store.yml22
-rw-r--r--.azure-pipelines/windows-release/stage-sign.yml113
-rw-r--r--.azure-pipelines/windows-release/stage-test-embed.yml40
-rw-r--r--.azure-pipelines/windows-release/stage-test-msi.yml108
-rw-r--r--.azure-pipelines/windows-release/stage-test-nuget.yml58
22 files changed, 1404 insertions, 0 deletions
diff --git a/.azure-pipelines/windows-release.yml b/.azure-pipelines/windows-release.yml
new file mode 100644
index 0000000000..7745857924
--- /dev/null
+++ b/.azure-pipelines/windows-release.yml
@@ -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
diff --git a/.azure-pipelines/windows-release/build-steps.yml b/.azure-pipelines/windows-release/build-steps.yml
new file mode 100644
index 0000000000..508d73b086
--- /dev/null
+++ b/.azure-pipelines/windows-release/build-steps.yml
@@ -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
diff --git a/.azure-pipelines/windows-release/checkout.yml b/.azure-pipelines/windows-release/checkout.yml
new file mode 100644
index 0000000000..d42d55fff0
--- /dev/null
+++ b/.azure-pipelines/windows-release/checkout.yml
@@ -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'])))
diff --git a/.azure-pipelines/windows-release/find-sdk.yml b/.azure-pipelines/windows-release/find-sdk.yml
new file mode 100644
index 0000000000..e4de78555b
--- /dev/null
+++ b/.azure-pipelines/windows-release/find-sdk.yml
@@ -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'
diff --git a/.azure-pipelines/windows-release/layout-command.yml b/.azure-pipelines/windows-release/layout-command.yml
new file mode 100644
index 0000000000..3ec9b69ad7
--- /dev/null
+++ b/.azure-pipelines/windows-release/layout-command.yml
@@ -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'
diff --git a/.azure-pipelines/windows-release/mingw-lib.yml b/.azure-pipelines/windows-release/mingw-lib.yml
new file mode 100644
index 0000000000..30f7d34fa6
--- /dev/null
+++ b/.azure-pipelines/windows-release/mingw-lib.yml
@@ -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)
diff --git a/.azure-pipelines/windows-release/msi-steps.yml b/.azure-pipelines/windows-release/msi-steps.yml
new file mode 100644
index 0000000000..2f80c34eeb
--- /dev/null
+++ b/.azure-pipelines/windows-release/msi-steps.yml
@@ -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
diff --git a/.azure-pipelines/windows-release/stage-build.yml b/.azure-pipelines/windows-release/stage-build.yml
new file mode 100644
index 0000000000..121e4b1a27
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-build.yml
@@ -0,0 +1,157 @@
+jobs:
+- job: Build_Docs
+ displayName: Docs build
+ pool:
+ name: 'Windows Release'
+ #vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ steps:
+ - template: ./checkout.yml
+
+ - script: Doc\make.bat html
+ displayName: 'Build HTML docs'
+ env:
+ BUILDDIR: $(Build.BinariesDirectory)\Doc
+
+ #- powershell: iwr "https://www.python.org/ftp/python/3.7.3/python373.chm" -OutFile "$(Build.BinariesDirectory)\python390a0.chm"
+ # displayName: 'Cheat at building CHM docs'
+
+ - script: Doc\make.bat htmlhelp
+ displayName: 'Build CHM docs'
+ env:
+ BUILDDIR: $(Build.BinariesDirectory)\Doc
+
+ - task: CopyFiles@2
+ displayName: 'Assemble artifact: Doc'
+ inputs:
+ sourceFolder: $(Build.BinariesDirectory)\Doc
+ targetFolder: $(Build.ArtifactStagingDirectory)\Doc
+ contents: |
+ html\**\*
+ htmlhelp\*.chm
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish artifact: doc'
+ inputs:
+ PathtoPublish: $(Build.ArtifactStagingDirectory)\Doc
+ ArtifactName: doc
+
+- job: Build_Python
+ displayName: Python build
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ Arch: win32
+ Platform: x86
+ Configuration: Release
+ win32_d:
+ Name: win32_d
+ Arch: win32
+ Platform: x86
+ Configuration: Debug
+ amd64_d:
+ Name: amd64_d
+ Arch: amd64
+ Platform: x64
+ Configuration: Debug
+
+ steps:
+ - template: ./build-steps.yml
+
+- job: Build_Python_NonPGO
+ displayName: Python non-PGO build
+ condition: and(succeeded(), ne(variables['DoPGO'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ amd64:
+ Name: amd64
+ Arch: amd64
+ Platform: x64
+ Configuration: Release
+
+ steps:
+ - template: ./build-steps.yml
+
+
+- job: Build_Python_PGO
+ displayName: Python PGO build
+ condition: and(succeeded(), eq(variables['DoPGO'], 'true'))
+
+ pool:
+ name: 'Windows Release'
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ amd64:
+ Name: amd64
+ Arch: amd64
+ Platform: x64
+ Configuration: Release
+
+ steps:
+ - template: ./build-steps.yml
+ parameters:
+ ShouldPGO: true
+
+
+- job: TclTk_Lib
+ displayName: Publish Tcl/Tk Library
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ steps:
+ - template: ./checkout.yml
+
+ - script: PCbuild\get_externals.bat --no-openssl --no-libffi
+ displayName: 'Get external dependencies'
+
+ - task: MSBuild@1
+ displayName: 'Copy Tcl/Tk lib for publish'
+ inputs:
+ solution: PCbuild\tcltk.props
+ platform: x86
+ msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_win32"
+
+ - task: MSBuild@1
+ displayName: 'Copy Tcl/Tk lib for publish'
+ inputs:
+ solution: PCbuild\tcltk.props
+ platform: x64
+ msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_amd64"
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish artifact: tcltk_lib_win32'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\tcl_win32'
+ ArtifactName: tcltk_lib_win32
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish artifact: tcltk_lib_amd64'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\tcl_amd64'
+ ArtifactName: tcltk_lib_amd64
diff --git a/.azure-pipelines/windows-release/stage-layout-embed.yml b/.azure-pipelines/windows-release/stage-layout-embed.yml
new file mode 100644
index 0000000000..c9d58b6b30
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-layout-embed.yml
@@ -0,0 +1,56 @@
+jobs:
+- job: Make_Embed_Layout
+ displayName: Make embeddable layout
+ condition: and(succeeded(), eq(variables['DoEmbed'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+ amd64:
+ Name: amd64
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+
+ steps:
+ - template: ./checkout.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)'
+ inputs:
+ artifactName: bin_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - template: ./layout-command.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)"
+ displayName: 'Extract version numbers'
+
+ - powershell: >
+ $(LayoutCmd)
+ --copy "$(Build.ArtifactStagingDirectory)\layout"
+ --zip "$(Build.ArtifactStagingDirectory)\embed\$(VersionText)-embed-$(Name).zip"
+ --preset-embed
+ displayName: 'Generate embeddable layout'
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: layout_embed_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\layout'
+ ArtifactName: layout_embed_$(Name)
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: embed'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\embed'
+ ArtifactName: embed
diff --git a/.azure-pipelines/windows-release/stage-layout-full.yml b/.azure-pipelines/windows-release/stage-layout-full.yml
new file mode 100644
index 0000000000..3593cf0a3f
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-layout-full.yml
@@ -0,0 +1,62 @@
+jobs:
+- job: Make_Layouts
+ displayName: Make layouts
+ condition: and(succeeded(), eq(variables['DoLayout'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+ amd64:
+ Name: amd64
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+
+ steps:
+ - template: ./checkout.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)'
+ inputs:
+ artifactName: bin_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)_d'
+ inputs:
+ artifactName: bin_$(Name)_d
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: doc'
+ inputs:
+ artifactName: doc
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: tcltk_lib_$(Name)'
+ inputs:
+ artifactName: tcltk_lib_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - template: ./layout-command.yml
+
+ - powershell: |
+ $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\layout" --preset-default
+ displayName: 'Generate full layout'
+ env:
+ TCL_LIBRARY: $(Build.BinariesDirectory)\tcltk_lib_$(Name)\tcl8
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: layout_full_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\layout'
+ ArtifactName: layout_full_$(Name)
diff --git a/.azure-pipelines/windows-release/stage-layout-msix.yml b/.azure-pipelines/windows-release/stage-layout-msix.yml
new file mode 100644
index 0000000000..1a1e0a2fd6
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-layout-msix.yml
@@ -0,0 +1,86 @@
+jobs:
+- job: Make_MSIX_Layout
+ displayName: Make MSIX layout
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ #win32:
+ # Name: win32
+ # Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ # PYTHONHOME: $(Build.SourcesDirectory)
+ amd64:
+ Name: amd64
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+
+ steps:
+ - template: ./checkout.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)'
+ inputs:
+ artifactName: bin_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)_d'
+ inputs:
+ artifactName: bin_$(Name)_d
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: tcltk_lib_$(Name)'
+ inputs:
+ artifactName: tcltk_lib_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - template: ./layout-command.yml
+
+ - powershell: |
+ Remove-Item "$(Build.ArtifactStagingDirectory)\appx-store" -Recurse -Force -EA 0
+ $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\appx-store" --preset-appx --precompile
+ displayName: 'Generate store APPX layout'
+ env:
+ TCL_LIBRARY: $(Build.BinariesDirectory)\tcltk_lib_$(Name)\tcl8
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: layout_appxstore_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\appx-store'
+ ArtifactName: layout_appxstore_$(Name)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: cert'
+ condition: and(succeeded(), variables['SigningCertificate'])
+ inputs:
+ artifactName: cert
+ downloadPath: $(Build.BinariesDirectory)
+
+ - powershell: |
+ $info = (gc "$(Build.BinariesDirectory)\cert\certinfo.json" | ConvertFrom-JSON)
+ Write-Host "Side-loadable APPX must be signed with '$($info.Subject)'"
+ Write-Host "##vso[task.setvariable variable=APPX_DATA_PUBLISHER]$($info.Subject)"
+ Write-Host "##vso[task.setvariable variable=APPX_DATA_SHA256]$($info.SHA256)"
+ displayName: 'Override signing parameters'
+ condition: and(succeeded(), variables['SigningCertificate'])
+
+ - powershell: |
+ Remove-Item "$(Build.ArtifactStagingDirectory)\appx" -Recurse -Force -EA 0
+ $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\appx" --preset-appx --precompile --include-symbols --include-tests
+ displayName: 'Generate sideloading APPX layout'
+ env:
+ TCL_LIBRARY: $(Build.BinariesDirectory)\tcltk_lib_$(Name)\tcl8
+ APPX_DATA_PUBLISHER: $(APPX_DATA_PUBLISHER)
+ APPX_DATA_SHA256: $(APPX_DATA_SHA256)
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: layout_appx_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\appx'
+ ArtifactName: layout_appx_$(Name)
diff --git a/.azure-pipelines/windows-release/stage-layout-nuget.yml b/.azure-pipelines/windows-release/stage-layout-nuget.yml
new file mode 100644
index 0000000000..ca4213d9e5
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-layout-nuget.yml
@@ -0,0 +1,44 @@
+jobs:
+- job: Make_Nuget_Layout
+ displayName: Make Nuget layout
+ condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+ amd64:
+ Name: amd64
+ Python: $(Build.BinariesDirectory)\bin_$(Name)\python.exe
+ PYTHONHOME: $(Build.SourcesDirectory)
+
+ steps:
+ - template: ./checkout.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: bin_$(Name)'
+ inputs:
+ artifactName: bin_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - template: ./layout-command.yml
+
+ - powershell: |
+ $(LayoutCmd) --copy "$(Build.ArtifactStagingDirectory)\nuget" --preset-nuget
+ displayName: 'Generate nuget layout'
+ env:
+ TCL_LIBRARY: $(Build.BinariesDirectory)\bin_$(Name)\tcl\tcl8
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: layout_nuget_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\nuget'
+ ArtifactName: layout_nuget_$(Name)
diff --git a/.azure-pipelines/windows-release/stage-msi.yml b/.azure-pipelines/windows-release/stage-msi.yml
new file mode 100644
index 0000000000..7afc816a0c
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-msi.yml
@@ -0,0 +1,36 @@
+jobs:
+- job: Make_MSI
+ displayName: Make MSI
+ condition: and(succeeded(), not(variables['SigningCertificate']))
+
+ pool:
+ vmName: win2016-vs2017
+
+ variables:
+ ReleaseUri: http://www.python.org/{arch}
+ DownloadUrl: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi}
+ Py_OutDir: $(Build.BinariesDirectory)
+
+ workspace:
+ clean: all
+
+ steps:
+ - template: msi-steps.yml
+
+- job: Make_Signed_MSI
+ displayName: Make signed MSI
+ condition: and(succeeded(), variables['SigningCertificate'])
+
+ pool:
+ name: 'Windows Release'
+
+ variables:
+ ReleaseUri: http://www.python.org/{arch}
+ DownloadUrl: https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi}
+ Py_OutDir: $(Build.BinariesDirectory)
+
+ workspace:
+ clean: all
+
+ steps:
+ - template: msi-steps.yml
diff --git a/.azure-pipelines/windows-release/stage-pack-msix.yml b/.azure-pipelines/windows-release/stage-pack-msix.yml
new file mode 100644
index 0000000000..6f1846e581
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-pack-msix.yml
@@ -0,0 +1,127 @@
+jobs:
+- job: Pack_MSIX
+ displayName: Pack MSIX bundles
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ amd64:
+ Name: amd64
+ Artifact: appx
+ Suffix:
+ ShouldSign: true
+ amd64_store:
+ Name: amd64
+ Artifact: appxstore
+ Suffix: -store
+ Upload: true
+
+ steps:
+ - template: ./checkout.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: layout_$(Artifact)_$(Name)'
+ inputs:
+ artifactName: layout_$(Artifact)_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: symbols'
+ inputs:
+ artifactName: symbols
+ downloadPath: $(Build.BinariesDirectory)
+
+ - 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[task.setvariable variable=Filename]python-$($d.PythonVersion)-$(Name)$(Suffix)"
+ displayName: 'Extract version numbers'
+
+ - powershell: |
+ ./Tools/msi/make_appx.ps1 -layout "$(Build.BinariesDirectory)\layout_$(Artifact)_$(Name)" -msix "$(Build.ArtifactStagingDirectory)\msix\$(Filename).msix"
+ displayName: 'Build msix'
+
+ - powershell: |
+ 7z a -tzip "$(Build.ArtifactStagingDirectory)\msix\$(Filename).appxsym" *.pdb
+ displayName: 'Build appxsym'
+ workingDirectory: $(Build.BinariesDirectory)\symbols\$(Name)
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: MSIX'
+ condition: and(succeeded(), or(ne(variables['ShouldSign'], 'true'), not(variables['SigningCertificate'])))
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\msix'
+ ArtifactName: msix
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: MSIX'
+ condition: and(succeeded(), and(eq(variables['ShouldSign'], 'true'), variables['SigningCertificate']))
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\msix'
+ ArtifactName: unsigned_msix
+
+ - powershell: |
+ 7z a -tzip "$(Build.ArtifactStagingDirectory)\msixupload\$(Filename).msixupload" *
+ displayName: 'Build msixupload'
+ condition: and(succeeded(), eq(variables['Upload'], 'true'))
+ workingDirectory: $(Build.ArtifactStagingDirectory)\msix
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: MSIXUpload'
+ condition: and(succeeded(), eq(variables['Upload'], 'true'))
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\msixupload'
+ ArtifactName: msixupload
+
+
+- job: Sign_MSIX
+ displayName: Sign side-loadable MSIX bundles
+ dependsOn:
+ - Pack_MSIX
+ condition: and(succeeded(), variables['SigningCertificate'])
+
+ pool:
+ name: 'Windows Release'
+
+ workspace:
+ clean: all
+
+ steps:
+ - checkout: none
+ - template: ./find-sdk.yml
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download Artifact: unsigned_msix'
+ inputs:
+ artifactName: unsigned_msix
+ downloadPath: $(Build.BinariesDirectory)
+
+ - powershell: |
+ $failed = $true
+ foreach ($retry in 1..3) {
+ signtool sign /a /n "$(SigningCertificate)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "$(SigningDescription)" (gi *.msix)
+ if ($?) {
+ $failed = $false
+ break
+ }
+ sleep 1
+ }
+ if ($failed) {
+ throw "Failed to sign MSIX"
+ }
+ displayName: 'Sign MSIX'
+ workingDirectory: $(Build.BinariesDirectory)\unsigned_msix
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: MSIX'
+ inputs:
+ PathtoPublish: '$(Build.BinariesDirectory)\unsigned_msix'
+ ArtifactName: msix
diff --git a/.azure-pipelines/windows-release/stage-pack-nuget.yml b/.azure-pipelines/windows-release/stage-pack-nuget.yml
new file mode 100644
index 0000000000..5aa394fa48
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-pack-nuget.yml
@@ -0,0 +1,41 @@
+jobs:
+- job: Pack_Nuget
+ displayName: Pack Nuget bundles
+ condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ amd64:
+ Name: amd64
+ win32:
+ Name: win32
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: layout_nuget_$(Name)'
+ inputs:
+ artifactName: layout_nuget_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: NugetToolInstaller@0
+ displayName: 'Install Nuget'
+ inputs:
+ versionSpec: '>=5.0'
+
+ - powershell: |
+ nuget pack "$(Build.BinariesDirectory)\layout_nuget_$(Name)\python.nuspec" -OutputDirectory $(Build.ArtifactStagingDirectory) -NoPackageAnalysis -NonInteractive
+ displayName: 'Create nuget package'
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: nuget'
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)'
+ ArtifactName: nuget
diff --git a/.azure-pipelines/windows-release/stage-publish-nugetorg.yml b/.azure-pipelines/windows-release/stage-publish-nugetorg.yml
new file mode 100644
index 0000000000..7586d850f3
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-publish-nugetorg.yml
@@ -0,0 +1,28 @@
+jobs:
+- job: Publish_Nuget
+ displayName: Publish Nuget packages
+ condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: nuget'
+ inputs:
+ artifactName: nuget
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: NuGetCommand@2
+ displayName: Push packages
+ condition: and(succeeded(), eq(variables['SigningCertificate'], 'Python Software Foundation'))
+ inputs:
+ command: push
+ packagesToPush: $(Build.BinariesDirectory)\nuget\*.nupkg'
+ nuGetFeedType: external
+ publishFeedCredentials: 'Python on Nuget'
diff --git a/.azure-pipelines/windows-release/stage-publish-pythonorg.yml b/.azure-pipelines/windows-release/stage-publish-pythonorg.yml
new file mode 100644
index 0000000000..2215a56d4b
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-publish-pythonorg.yml
@@ -0,0 +1,34 @@
+jobs:
+- job: Publish_Python
+ displayName: Publish python.org packages
+ condition: and(succeeded(), and(eq(variables['DoMSI'], 'true'), eq(variables['DoEmbed'], 'true')))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: Doc'
+ inputs:
+ artifactName: Doc
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: msi'
+ inputs:
+ artifactName: msi
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: embed'
+ inputs:
+ artifactName: embed
+ downloadPath: $(Build.BinariesDirectory)
+
+ # TODO: eq(variables['SigningCertificate'], 'Python Software Foundation')
+ # If we are not real-signed, DO NOT PUBLISH
diff --git a/.azure-pipelines/windows-release/stage-publish-store.yml b/.azure-pipelines/windows-release/stage-publish-store.yml
new file mode 100644
index 0000000000..06884c4f35
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-publish-store.yml
@@ -0,0 +1,22 @@
+jobs:
+- job: Publish_Store
+ displayName: Publish Store packages
+ condition: and(succeeded(), eq(variables['DoMSIX'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: msixupload'
+ inputs:
+ artifactName: msixupload
+ downloadPath: $(Build.BinariesDirectory)
+
+ # TODO: eq(variables['SigningCertificate'], 'Python Software Foundation')
+ # If we are not real-signed, DO NOT PUBLISH
diff --git a/.azure-pipelines/windows-release/stage-sign.yml b/.azure-pipelines/windows-release/stage-sign.yml
new file mode 100644
index 0000000000..3d6ca9457f
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-sign.yml
@@ -0,0 +1,113 @@
+jobs:
+- job: Sign_Python
+ displayName: Sign Python binaries
+ condition: and(succeeded(), variables['SigningCertificate'])
+
+ pool:
+ name: 'Windows Release'
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ amd64:
+ Name: amd64
+
+ steps:
+ - checkout: none
+ - template: ./find-sdk.yml
+
+ - powershell: |
+ Write-Host "##vso[build.addbuildtag]signed"
+ displayName: 'Add build tags'
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: unsigned_bin_$(Name)'
+ inputs:
+ artifactName: unsigned_bin_$(Name)
+ downloadPath: $(Build.BinariesDirectory)
+
+ - powershell: |
+ $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*)
+ signtool sign /a /n "$(SigningCertificate)" /fd sha256 /d "$(SigningDescription)" $files
+ displayName: 'Sign binaries'
+ workingDirectory: $(Build.BinariesDirectory)\unsigned_bin_$(Name)
+
+ - powershell: |
+ $files = (gi *.exe, *.dll, *.pyd, *.cat -Exclude vcruntime*, libffi*, libcrypto*, libssl*)
+ $failed = $true
+ foreach ($retry in 1..10) {
+ signtool timestamp /t http://timestamp.verisign.com/scripts/timestamp.dll $files
+ if ($?) {
+ $failed = $false
+ break
+ }
+ sleep 5
+ }
+ if ($failed) {
+ Write-Host "##vso[task.logissue type=error]Failed to timestamp files"
+ }
+ displayName: 'Timestamp binaries'
+ workingDirectory: $(Build.BinariesDirectory)\unsigned_bin_$(Name)
+ continueOnError: true
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish artifact: bin_$(Name)'
+ inputs:
+ PathtoPublish: '$(Build.BinariesDirectory)\unsigned_bin_$(Name)'
+ ArtifactName: bin_$(Name)
+
+
+- job: Dump_CertInfo
+ displayName: Capture certificate info
+ condition: and(succeeded(), variables['SigningCertificate'])
+
+ pool:
+ name: 'Windows Release'
+
+ steps:
+ - checkout: none
+
+ - powershell: |
+ $m = 'CN=$(SigningCertificate)'
+ $c = ((gci Cert:\CurrentUser\My), (gci Cert:\LocalMachine\My)) | %{ $_ } | `
+ ?{ $_.Subject -match $m } | `
+ select -First 1
+ if (-not $c) {
+ Write-Host "Failed to find certificate for $(SigningCertificate)"
+ exit
+ }
+ $d = mkdir "$(Build.BinariesDirectory)\tmp" -Force
+ $cf = "$d\cert.cer"
+ [IO.File]::WriteAllBytes($cf, $c.Export("Cer"))
+ $csha = (certutil -dump $cf | sls "Cert Hash\(sha256\): (.+)").Matches.Groups[1].Value
+
+ $info = @{ Subject=$c.Subject; SHA256=$csha; }
+
+ $d = mkdir "$(Build.BinariesDirectory)\cert" -Force
+ $info | ConvertTo-JSON -Compress | Out-File -Encoding utf8 "$d\certinfo.json"
+ displayName: "Extract certificate info"
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish artifact: cert'
+ inputs:
+ PathtoPublish: '$(Build.BinariesDirectory)\cert'
+ ArtifactName: cert
+
+
+- job: Mark_Unsigned
+ displayName: Tag unsigned build
+ condition: and(succeeded(), not(variables['SigningCertificate']))
+
+ pool:
+ vmName: win2016-vs2017
+
+ steps:
+ - checkout: none
+
+ - powershell: |
+ Write-Host "##vso[build.addbuildtag]unsigned"
+ displayName: 'Add build tag'
diff --git a/.azure-pipelines/windows-release/stage-test-embed.yml b/.azure-pipelines/windows-release/stage-test-embed.yml
new file mode 100644
index 0000000000..ab377fdfa8
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-test-embed.yml
@@ -0,0 +1,40 @@
+jobs:
+- job: Test_Embed
+ displayName: Test Embed
+ condition: and(succeeded(), eq(variables['DoEmbed'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Name: win32
+ amd64:
+ Name: amd64
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: embed'
+ inputs:
+ artifactName: embed
+ downloadPath: $(Build.BinariesDirectory)
+
+ - powershell: |
+ Expand-Archive -Path "$(Build.BinariesDirectory)\embed\embed-$(Name).zip" -DestinationPath "$(Build.BinariesDirectory)\Python"
+ $p = gi "$(Build.BinariesDirectory)\Python\python.exe"
+ Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
+ displayName: 'Install Python and add to PATH'
+
+ - script: |
+ python -c "import sys; print(sys.version)"
+ displayName: 'Collect version number'
+
+ - script: |
+ python -m site
+ displayName: 'Collect site'
diff --git a/.azure-pipelines/windows-release/stage-test-msi.yml b/.azure-pipelines/windows-release/stage-test-msi.yml
new file mode 100644
index 0000000000..10039295a1
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-test-msi.yml
@@ -0,0 +1,108 @@
+jobs:
+- job: Test_MSI
+ displayName: Test MSI
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32_User:
+ ExeMatch: 'python-[\dabrc.]+-webinstall\.exe'
+ Logs: $(Build.ArtifactStagingDirectory)\logs\win32_User
+ InstallAllUsers: 0
+ win32_Machine:
+ ExeMatch: 'python-[\dabrc.]+-webinstall\.exe'
+ Logs: $(Build.ArtifactStagingDirectory)\logs\win32_Machine
+ InstallAllUsers: 1
+ amd64_User:
+ ExeMatch: 'python-[\dabrc.]+-amd64-webinstall\.exe'
+ Logs: $(Build.ArtifactStagingDirectory)\logs\amd64_User
+ InstallAllUsers: 0
+ amd64_Machine:
+ ExeMatch: 'python-[\dabrc.]+-amd64-webinstall\.exe'
+ Logs: $(Build.ArtifactStagingDirectory)\logs\amd64_Machine
+ InstallAllUsers: 1
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: msi'
+ inputs:
+ artifactName: msi
+ downloadPath: $(Build.BinariesDirectory)
+
+ - powershell: |
+ $p = (gci -r *.exe | ?{ $_.Name -match '$(ExeMatch)' } | select -First 1)
+ Write-Host "##vso[task.setvariable variable=SetupExe]$($p.FullName)"
+ Write-Host "##vso[task.setvariable variable=SetupExeName]$($p.Name)"
+ displayName: 'Find installer executable'
+ workingDirectory: $(Build.BinariesDirectory)\msi
+
+ - script: >
+ "$(SetupExe)"
+ /passive
+ /log "$(Logs)\install\log.txt"
+ TargetDir="$(Build.BinariesDirectory)\Python"
+ Include_debug=1
+ Include_symbols=1
+ InstallAllUsers=$(InstallAllUsers)
+ displayName: 'Install Python'
+
+ - powershell: |
+ $p = gi "$(Build.BinariesDirectory)\Python\python.exe"
+ Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
+ displayName: 'Add test Python to PATH'
+
+ - script: |
+ python -c "import sys; print(sys.version)"
+ displayName: 'Collect version number'
+
+ - script: |
+ python -m site
+ displayName: 'Collect site'
+
+ - powershell: |
+ gci -r "${env:PROGRAMDATA}\Microsoft\Windows\Start Menu\Programs\Python*"
+ displayName: 'Capture per-machine Start Menu items'
+ - powershell: |
+ gci -r "${env:APPDATA}\Microsoft\Windows\Start Menu\Programs\Python*"
+ displayName: 'Capture per-user Start Menu items'
+
+ - powershell: |
+ gci -r "HKLM:\Software\WOW6432Node\Python"
+ displayName: 'Capture per-machine 32-bit registry'
+ - powershell: |
+ gci -r "HKLM:\Software\Python"
+ displayName: 'Capture per-machine native registry'
+ - powershell: |
+ gci -r "HKCU:\Software\Python"
+ displayName: 'Capture current-user registry'
+
+ - script: |
+ python -m pip install "azure<0.10"
+ python -m pip uninstall -y azure python-dateutil six
+ displayName: 'Test (un)install package'
+
+ - script: |
+ python -m test -uall -v test_ttk_guionly test_tk test_idle
+ displayName: 'Test Tkinter and Idle'
+
+ - script: >
+ "$(SetupExe)"
+ /passive
+ /uninstall
+ /log "$(Logs)\uninstall\log.txt"
+ displayName: 'Uninstall Python'
+
+ - task: PublishBuildArtifacts@1
+ displayName: 'Publish Artifact: logs'
+ condition: true
+ continueOnError: true
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)\logs'
+ ArtifactName: msi_testlogs
diff --git a/.azure-pipelines/windows-release/stage-test-nuget.yml b/.azure-pipelines/windows-release/stage-test-nuget.yml
new file mode 100644
index 0000000000..1f8b601d0d
--- /dev/null
+++ b/.azure-pipelines/windows-release/stage-test-nuget.yml
@@ -0,0 +1,58 @@
+jobs:
+- job: Test_Nuget
+ displayName: Test Nuget
+ condition: and(succeeded(), eq(variables['DoNuget'], 'true'))
+
+ pool:
+ vmName: win2016-vs2017
+
+ workspace:
+ clean: all
+
+ strategy:
+ matrix:
+ win32:
+ Package: pythonx86
+ amd64:
+ Package: python
+
+ steps:
+ - checkout: none
+
+ - task: DownloadBuildArtifacts@0
+ displayName: 'Download artifact: nuget'
+ inputs:
+ artifactName: nuget
+ downloadPath: $(Build.BinariesDirectory)
+
+ - task: NugetToolInstaller@0
+ inputs:
+ versionSpec: '>= 5'
+
+ - powershell: >
+ nuget install
+ $(Package)
+ -Source "$(Build.BinariesDirectory)\nuget"
+ -OutputDirectory "$(Build.BinariesDirectory)\install"
+ -Prerelease
+ -ExcludeVersion
+ -NonInteractive
+ displayName: 'Install Python'
+
+ - powershell: |
+ $p = gi "$(Build.BinariesDirectory)\install\$(Package)\tools\python.exe"
+ Write-Host "##vso[task.prependpath]$(Split-Path -Parent $p)"
+ displayName: 'Add test Python to PATH'
+
+ - script: |
+ python -c "import sys; print(sys.version)"
+ displayName: 'Collect version number'
+
+ - script: |
+ python -m site
+ displayName: 'Collect site'
+
+ - script: |
+ python -m pip install "azure<0.10"
+ python -m pip uninstall -y azure python-dateutil six
+ displayName: 'Test (un)install package'