diff --git a/.github/workflows/python-builder.yml b/.github/workflows/python-builder.yml index 028324b4..5277dbb2 100644 --- a/.github/workflows/python-builder.yml +++ b/.github/workflows/python-builder.yml @@ -11,6 +11,10 @@ on: description: 'Whether to publish releases' required: true default: 'false' + PLATFORMS: + description: 'Platforms for execution in "os" or "os_arch" format (arch is "x64" by default)' + required: true + default: 'ubuntu-18.04,ubuntu-20.04,macos-10.15,windows-2019_x64,windows-2019_x86' pull_request: paths-ignore: - 'versions-manifest.json' @@ -26,26 +30,40 @@ defaults: shell: pwsh jobs: + generate_matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.generate-matrix.outputs.matrix }} + steps: + - name: Generate execution matrix + id: generate-matrix + run: | + $configurations = "${{ github.event.inputs.platforms || 'ubuntu-18.04,ubuntu-20.04,macos-10.15,windows-2019_x64,windows-2019_x86' }}".Split(",").Trim() + $matrix = @() + + foreach ($configuration in $configurations) { + $parts = $configuration.Split("_") + $os = $parts[0] + $arch = if ($parts[1]) {$parts[1]} else {"x64"} + switch -wildcard ($os) { + "*ubuntu*" { $platform = $os.Replace("ubuntu","linux")} + "*macos*" { $platform = 'darwin' } + "*windows*" { $platform = 'win32' } + } + $matrix += @{ + 'platform' = $platform + 'os' = $os + 'arch' = $arch + } + } + echo "::set-output name=matrix::$($matrix | ConvertTo-Json -Compress)" + build_python: + needs: generate_matrix strategy: fail-fast: false matrix: - include: - - platform: 'linux-18.04' - os: 'ubuntu-18.04' - arch: 'x64' - - platform: 'linux-20.04' - os: 'ubuntu-20.04' - arch: 'x64' - - platform: 'darwin' - os: 'macos-10.15' - arch: 'x64' - - platform: 'win32' - os: 'windows-2019' - arch: 'x64' - - platform: 'win32' - os: 'windows-2019' - arch: 'x86' + include: ${{ fromJson(needs.generate_matrix.outputs.matrix) }} runs-on: ${{ matrix.os }} env: ARTIFACT_NAME: python-${{ github.event.inputs.VERSION || '3.9.9' }}-${{ matrix.platform }}-${{ matrix.arch }} @@ -68,26 +86,11 @@ jobs: path: ${{ runner.temp }}/artifact test_python: - needs: build_python + needs: [generate_matrix, build_python] strategy: fail-fast: false matrix: - include: - - platform: 'linux-18.04' - os: 'ubuntu-18.04' - arch: 'x64' - - platform: 'linux-20.04' - os: 'ubuntu-20.04' - arch: 'x64' - - platform: 'darwin' - os: 'macos-10.15' - arch: 'x64' - - platform: 'win32' - os: 'windows-2019' - arch: 'x64' - - platform: 'win32' - os: 'windows-2019' - arch: 'x86' + include: ${{ fromJson(needs.generate_matrix.outputs.matrix) }} runs-on: ${{ matrix.os }} env: ARTIFACT_NAME: python-${{ github.event.inputs.VERSION || '3.9.9' }}-${{ matrix.platform }}-${{ matrix.arch }} diff --git a/.github/workflows/python-versions-runner.yml b/.github/workflows/python-versions-runner.yml new file mode 100644 index 00000000..4ac53b8c --- /dev/null +++ b/.github/workflows/python-versions-runner.yml @@ -0,0 +1,31 @@ +name: Python versions runner +on: + workflow_dispatch: + inputs: + versions: + description: 'Versions to build' + required: true + default: '","' + publish-releases: + description: 'Whether to publish releases' + required: true + default: 'false' + +defaults: + run: + shell: pwsh + +jobs: + trigger_builds: + name: Trigger python build + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v2 + + - name: Trigger python workflow + run: | + $versions = ${{ github.event.inputs.versions }} + ./builders/python-versions-runner.ps1 -Versions $versions.Split(",") -PublishRelease ${{ github.event.inputs.publish-releases }} + env: + PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }} \ No newline at end of file diff --git a/azure-pipelines/build-python-packages.yml b/azure-pipelines/build-python-packages.yml deleted file mode 100644 index 12577537..00000000 --- a/azure-pipelines/build-python-packages.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: $(date:yyyyMMdd)$(rev:.r)-Python-$(VERSION) -trigger: none -pr: none - -stages: -- stage: Build_Python_MacOS - dependsOn: [] - variables: - VmImage: 'macOS-10.15' - Platform: darwin - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/build-job.yml - -- stage: Test_Python_MacOS - condition: succeeded() - dependsOn: Build_Python_MacOS - variables: - VmImage: 'macOS-10.15' - Platform: darwin - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/test-job.yml - -- stage: Build_Python_Ubuntu_1804 - dependsOn: [] - variables: - VmImage: 'ubuntu-18.04' - Platform: linux-18.04 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/build-job.yml - -- stage: Test_Python_Ubuntu_1804 - condition: succeeded() - dependsOn: Build_Python_Ubuntu_1804 - variables: - VmImage: 'ubuntu-18.04' - Platform: linux-18.04 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/test-job.yml - -- stage: Build_Python_Ubuntu_2004 - dependsOn: [] - variables: - VmImage: 'ubuntu-20.04' - Platform: linux-20.04 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/build-job.yml - -- stage: Test_Python_Ubuntu_2004 - condition: succeeded() - dependsOn: Build_Python_Ubuntu_2004 - variables: - VmImage: 'ubuntu-20.04' - Platform: linux-20.04 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/test-job.yml - -- stage: Build_Python_X64_Windows - dependsOn: [] - variables: - VmImage: 'windows-2019' - Platform: win32 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/build-job.yml - -- stage: Test_Python_x64_Windows - condition: succeeded() - dependsOn: Build_Python_X64_Windows - variables: - VmImage: 'windows-2019' - Platform: win32 - Architecture: x64 - jobs: - - template: /azure-pipelines/templates/test-job.yml - -- stage: Build_Python_x86_Windows - dependsOn: [] - variables: - VmImage: 'windows-2019' - Platform: win32 - Architecture: x86 - jobs: - - template: /azure-pipelines/templates/build-job.yml - -- stage: Test_Python_x86_Windows - condition: succeeded() - dependsOn: Build_Python_x86_Windows - variables: - VmImage: 'windows-2019' - Platform: win32 - Architecture: x86 - jobs: - - template: /azure-pipelines/templates/test-job.yml - -- stage: Publish_Release - dependsOn: [Test_Python_MacOS, Test_Python_Ubuntu_1804, Test_Python_Ubuntu_2004, Test_Python_x64_Windows, Test_Python_x86_Windows] - jobs: - - deployment: Publish_Release - pool: - name: Azure Pipelines - vmImage: ubuntu-18.04 - environment: 'Get Available Tools Versions - Publishing Approval' - strategy: - runOnce: - deploy: - steps: - - template: /azure-pipelines/templates/publish-release-steps.yml diff --git a/azure-pipelines/run-ci-builds.yml b/azure-pipelines/run-ci-builds.yml deleted file mode 100644 index 7f0cb4dd..00000000 --- a/azure-pipelines/run-ci-builds.yml +++ /dev/null @@ -1,38 +0,0 @@ -trigger: none -pr: - autoCancel: true - branches: - include: - - main - paths: - exclude: - - versions-manifest.json - -jobs: -- job: Run_Builds - pool: - name: Azure Pipelines - vmImage: 'ubuntu-latest' - timeoutInMinutes: 180 - - steps: - - checkout: self - submodules: true - - - task: PowerShell@2 - displayName: 'Run build' - inputs: - targetType: filePath - filePath: './helpers/azure-devops/run-ci-builds.ps1 ' - arguments: | - -TeamFoundationCollectionUri $(System.TeamFoundationCollectionUri) ` - -AzureDevOpsProjectName $(System.TeamProject) ` - -AzureDevOpsAccessToken $(System.AccessToken) ` - -SourceBranch $(Build.SourceBranch) ` - -DefinitionId $(DEFINITION_ID) ` - -SourceVersion $(Build.SourceVersion) ` - -ManifestLink $(MANIFEST_LINK) ` - -WaitForBuilds $(WAIT_FOR_BUILDS) ` - -ToolVersions "$(PYTHON_VERSIONS)" ` - -RetryIntervalSec $(RETRY_INTERVAL_SEC) ` - -RetryCount $(RETRY_COUNT) \ No newline at end of file diff --git a/azure-pipelines/templates/build-job.yml b/azure-pipelines/templates/build-job.yml deleted file mode 100644 index 0fef97dc..00000000 --- a/azure-pipelines/templates/build-job.yml +++ /dev/null @@ -1,23 +0,0 @@ -jobs: -- job: Build_Python - timeoutInMinutes: 90 - pool: - name: Azure Pipelines - vmImage: $(VmImage) - steps: - - checkout: self - submodules: true - - - task: PowerShell@2 - displayName: 'Build Python $(VERSION)' - inputs: - targetType: filePath - filePath: './builders/build-python.ps1' - arguments: '-Version $(VERSION) -Platform $(Platform) -Architecture $(Architecture)' - pwsh: true - - - task: PublishPipelineArtifact@1 - displayName: 'Publish Artifact: Python $(VERSION)' - inputs: - targetPath: '$(Build.ArtifactStagingDirectory)' - artifactName: 'python-$(VERSION)-$(Platform)-$(Architecture)' \ No newline at end of file diff --git a/azure-pipelines/templates/publish-release-steps.yml b/azure-pipelines/templates/publish-release-steps.yml deleted file mode 100644 index cbb041a7..00000000 --- a/azure-pipelines/templates/publish-release-steps.yml +++ /dev/null @@ -1,47 +0,0 @@ -steps: -- download: none - -- checkout: self - submodules: true - -- task: DownloadPipelineArtifact@2 - inputs: - source: 'current' - path: $(Build.BinariesDirectory) - -- task: PowerShell@2 - displayName: 'Create release Python $(VERSION)' - inputs: - TargetType: inline - script: | - $tagName = "$(VERSION)-$(Build.BuildId)" - $releaseBody = "Python $(VERSION)" - ./helpers/github/create-release.ps1 -RepositoryFullName "$(Build.Repository.Name)" ` - -AccessToken "$(GITHUB_TOKEN)" ` - -ToolVersion "$(VERSION)" ` - -TagName "$tagName" ` - -ReleaseBody "$releaseBody" ` - -EventType "$(EVENT_TYPE)" -- task: GitHubRelease@1 - displayName: 'Upload release assets' - inputs: - gitHubConnection: 'Github Connection' - action: edit - tag: '$(VERSION)-$(Build.BuildId)' - title: '$(VERSION)' - releaseNotesSource: inline - releaseNotesInline: '$(RELEASE_NOTES_CONTENT)' - assets: '$(Build.BinariesDirectory)/*/*' - assetUploadMode: replace - addChangeLog: false - -- task: PowerShell@2 - displayName: 'Trigger "Create Pull Request" workflow' - inputs: - TargetType: inline - script: | - Import-Module (Join-Path (Get-Location).Path "github-api.psm1") - $gitHubApi = Get-GitHubApi -RepositoryFullName "$(Build.Repository.Name)" -AccessToken "$(GITHUB_TOKEN)" - $gitHubApi.CreateWorkflowDispatch("$(WORKFLOW_FILE_NAME)", "$(WORKFLOW_DISPATCH_REF)", "$(INPUTS)") - Write-Host "Please find created Pull request here: $(Build.Repository.Uri)/pulls" - workingDirectory: '$(Build.SourcesDirectory)/helpers/github' \ No newline at end of file diff --git a/azure-pipelines/templates/test-job.yml b/azure-pipelines/templates/test-job.yml deleted file mode 100644 index 80975b3a..00000000 --- a/azure-pipelines/templates/test-job.yml +++ /dev/null @@ -1,91 +0,0 @@ -jobs: -- job: Test_Python - pool: - name: Azure Pipelines - vmImage: $(VmImage) - variables: - TestRunTitle: 'python-$(Platform)-$(Architecture)' - steps: - - checkout: self - submodules: true - - - task: PowerShell@2 - displayName: Fully cleanup the toolcache directory before testing - inputs: - targetType: filePath - filePath: helpers/clean-toolcache.ps1 - arguments: -ToolName "Python" - - - task: DownloadPipelineArtifact@2 - inputs: - source: 'current' - artifact: 'python-$(VERSION)-$(Platform)-$(Architecture)' - path: $(Build.BinariesDirectory) - - - task: ExtractFiles@1 - inputs: - archiveFilePatterns: '$(Build.BinariesDirectory)/python-$(VERSION)-$(Platform)-$(Architecture).*' - destinationFolder: $(Build.BinariesDirectory) - cleanDestinationFolder: false - overwriteExistingFiles: true - - - task: PowerShell@2 - displayName: 'Apply build artifact to the local machines' - inputs: - TargetType: inline - script: | - if ($env:PLATFORM -match 'win32') { powershell ./setup.ps1 } else { sh ./setup.sh } - workingDirectory: '$(Build.BinariesDirectory)' - - - task: UsePythonVersion@0 - displayName: 'Use Python $(VERSION)' - inputs: - versionSpec: '$(VERSION)' - architecture: '$(Architecture)' - - - task: PowerShell@2 - displayName: 'Verbose sysconfig dump' - inputs: - TargetType: inline - script: | - Invoke-Expression "python ./sources/python-config-output.py" - workingDirectory: '$(Build.SourcesDirectory)/tests' - condition: ne(variables['Platform'], 'win32') - - - task: PowerShell@2 - displayName: 'Verbose python binary links' - inputs: - TargetType: inline - script: | - $pythonLocation = which python - if ($env:PLATFORM -match 'darwin') { otool -L $pythonLocation } else { ldd $pythonLocation } - workingDirectory: '$(Build.BinariesDirectory)' - condition: ne(variables['Platform'], 'win32') - - - task: PowerShell@2 - displayName: 'Run tests' - inputs: - TargetType: inline - script: | - Install-Module Pester -Force -Scope CurrentUser -RequiredVersion 4.10.1 - Import-Module Pester - $pesterParams = @{ - Path="./python-tests.ps1"; - Parameters=@{ - Version="$(VERSION)"; - Platform="$(Platform)"; - } - } - Invoke-Pester -Script $pesterParams -OutputFile "test_results.xml" -OutputFormat NUnitXml - pwsh: true - workingDirectory: '$(Build.SourcesDirectory)/tests' - - - task: PublishTestResults@2 - displayName: 'Publish test results' - inputs: - testResultsFiles: '*.xml' - testResultsFormat: NUnit - searchFolder: 'tests' - failTaskOnFailedTests: true - testRunTitle: "$(TestRunTitle)" - condition: always() diff --git a/builders/invoke-workflow.psm1 b/builders/invoke-workflow.psm1 new file mode 100644 index 00000000..2b2ffb32 --- /dev/null +++ b/builders/invoke-workflow.psm1 @@ -0,0 +1,52 @@ +function Invoke-Workflow { + param ( + [string] $Version, + [string] $PublishRelease + ) + + $payload = @{ + "ref" = "main" + "inputs" = @{ + "VERSION" = "$Version" + "PUBLISH_RELEASES" = "$PublishRelease" + } + } | ConvertTo-Json + $headers = @{ + Authorization="Bearer $env:PERSONAL_TOKEN" + } + $actionsRepoUri = "$env:GITHUB_API_URL/repos/$env:GITHUB_REPOSITORY/actions" + Invoke-RestMethod -uri "$actionsRepoUri/workflows/python-builder.yml/dispatches" -method POST -headers $headers -body $payload + + $result = [PSCustomObject]@{ + Version = $Version + Conclusion = "failure" + Url = "Not run" + } + # Triggering workflow and verifying that it has been triggered with retries + while (-not $workflowToCheck) { + Start-Sleep -seconds 40 + $workflowRuns = (Invoke-RestMethod "$actionsRepoUri/runs").workflow_runs | Where-Object {$_.status -like "*progress*" -and $_.id -ne $env:GITHUB_RUN_ID} + $workflowToCheck = $workflowRuns | Where-Object { + (Invoke-RestMethod "$actionsRepoUri/runs/$($_.id)/jobs").jobs.steps.name -like "*$Version" + } + $retries++ + if ($retries -gt 10) { + Write-Host "Workflow triggered for version '$Version' not found or something went wrong with fetching the workflow status" + return $result + } + } + # Waiting for workflow to complete + while ($workflowToCheck.status -ne "completed") { + Start-Sleep -Seconds 120 + $workflowToCheck = Invoke-RestMethod "$actionsRepoUri/runs/$($workflowToCheck.id)" + Write-Host "Workflow run with Id: $($workflowToCheck.id) for version '$Version' - status '$($workflowToCheck.status)'" + } + $result.Conclusion = $workflowToCheck.conclusion + $result.Url = $workflowToCheck.html_url + if ($workflowToCheck.conclusion -ne "success") { + Write-Host "Triggered workflow for version '$Version' completed unsuccessfully with result '$($workflowToCheck.conclusion)'. Check the logs: $($workflowToCheck.html_url)" + return $result + } + Write-Host "Triggered workflow for version '$Version' succeeded; Url: $($workflowToCheck.html_url)" + return $result +} \ No newline at end of file diff --git a/builders/python-versions-runner.ps1 b/builders/python-versions-runner.ps1 new file mode 100644 index 00000000..d84dd1af --- /dev/null +++ b/builders/python-versions-runner.ps1 @@ -0,0 +1,31 @@ +<# +.SYNOPSIS +Generate Python artifact. + +.DESCRIPTION +Script that triggering and fetching the result of the "Build python package" workflows with provided python versions + +.PARAMETER Version +Required parameter. Python versions to trigger builds for. + +.PARAMETER PublishRelease +Switch parameter. Whether to publish release for built version. + +#> + +param( + [Parameter (Mandatory=$true, HelpMessage="Python version to trigger build for")] + [array] $Versions, + [Parameter (Mandatory=$false, HelpMessage="Whether to publish release for built version")] + [string] $PublishRelease +) + +$summary = $Versions | ForEach-Object -Parallel { + Import-Module "./builders/invoke-workflow.psm1" + Invoke-Workflow -Version $_ -PublishRelease $Using:PublishRelease +} +Write-Host "Results of triggered workflows:" +$summary | Out-String +if ($summary.Conclusion -contains "failure" -or $summary.Conclusion -contains "cancelled") { + exit 1 +} \ No newline at end of file diff --git a/versions-manifest.json b/versions-manifest.json index d9011815..3ebdc333 100644 --- a/versions-manifest.json +++ b/versions-manifest.json @@ -194,30 +194,81 @@ } ] }, + { + "version": "3.10.3", + "stable": true, + "release_url": "https://github.com/actions/python-versions/releases/tag/3.10.3-1996446651", + "files": [ + { + "filename": "python-3.10.3-darwin-x64.tar.gz", + "arch": "x64", + "platform": "darwin", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.3-1996446651/python-3.10.3-darwin-x64.tar.gz" + }, + { + "filename": "python-3.10.3-linux-18.04-x64.tar.gz", + "arch": "x64", + "platform": "linux", + "platform_version": "18.04", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.3-1996446651/python-3.10.3-linux-18.04-x64.tar.gz" + }, + { + "filename": "python-3.10.3-linux-20.04-x64.tar.gz", + "arch": "x64", + "platform": "linux", + "platform_version": "20.04", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.3-1996446651/python-3.10.3-linux-20.04-x64.tar.gz" + }, + { + "filename": "python-3.10.3-win32-x64.zip", + "arch": "x64", + "platform": "win32", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.3-1996446651/python-3.10.3-win32-x64.zip" + }, + { + "filename": "python-3.10.3-win32-x86.zip", + "arch": "x86", + "platform": "win32", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.3-1996446651/python-3.10.3-win32-x86.zip" + } + ] + }, { "version": "3.10.2", "stable": true, - "release_url": "https://github.com/actions/python-versions/releases/tag/3.10.2-121429", + "release_url": "https://github.com/actions/python-versions/releases/tag/3.10.2-1805098134", "files": [ { "filename": "python-3.10.2-darwin-x64.tar.gz", "arch": "x64", "platform": "darwin", - "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-121429/python-3.10.2-darwin-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-1805098134/python-3.10.2-darwin-x64.tar.gz" }, { "filename": "python-3.10.2-linux-18.04-x64.tar.gz", "arch": "x64", "platform": "linux", "platform_version": "18.04", - "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-121429/python-3.10.2-linux-18.04-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-1805098134/python-3.10.2-linux-18.04-x64.tar.gz" }, { "filename": "python-3.10.2-linux-20.04-x64.tar.gz", "arch": "x64", "platform": "linux", "platform_version": "20.04", - "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-121429/python-3.10.2-linux-20.04-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-1805098134/python-3.10.2-linux-20.04-x64.tar.gz" + }, + { + "filename": "python-3.10.2-win32-x64.zip", + "arch": "x64", + "platform": "win32", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-1805098134/python-3.10.2-win32-x64.zip" + }, + { + "filename": "python-3.10.2-win32-x86.zip", + "arch": "x86", + "platform": "win32", + "download_url": "https://github.com/actions/python-versions/releases/download/3.10.2-1805098134/python-3.10.2-win32-x86.zip" } ] }, @@ -996,46 +1047,39 @@ { "version": "3.9.7", "stable": true, - "release_url": "https://github.com/actions/python-versions/releases/tag/3.9.7-116077", + "release_url": "https://github.com/actions/python-versions/releases/tag/3.9.7-1812317133", "files": [ { "filename": "python-3.9.7-darwin-x64.tar.gz", "arch": "x64", "platform": "darwin", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-darwin-x64.tar.gz" - }, - { - "filename": "python-3.9.7-linux-16.04-x64.tar.gz", - "arch": "x64", - "platform": "linux", - "platform_version": "16.04", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-linux-16.04-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-1812317133/python-3.9.7-darwin-x64.tar.gz" }, { "filename": "python-3.9.7-linux-18.04-x64.tar.gz", "arch": "x64", "platform": "linux", "platform_version": "18.04", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-linux-18.04-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-1812317133/python-3.9.7-linux-18.04-x64.tar.gz" }, { "filename": "python-3.9.7-linux-20.04-x64.tar.gz", "arch": "x64", "platform": "linux", "platform_version": "20.04", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-linux-20.04-x64.tar.gz" + "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-1812317133/python-3.9.7-linux-20.04-x64.tar.gz" }, { "filename": "python-3.9.7-win32-x64.zip", "arch": "x64", "platform": "win32", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-win32-x64.zip" + "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-1812317133/python-3.9.7-win32-x64.zip" }, { "filename": "python-3.9.7-win32-x86.zip", "arch": "x86", "platform": "win32", - "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-116077/python-3.9.7-win32-x86.zip" + "download_url": "https://github.com/actions/python-versions/releases/download/3.9.7-1812317133/python-3.9.7-win32-x86.zip" } ] },