name: Build python package on: workflow_dispatch: inputs: VERSION: description: 'Python version to build and upload' default: '3.9.9' required: true PUBLISH_RELEASES: 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,ubuntu-22.04,macos-10.15,windows-2019_x64,windows-2019_x86' pull_request: paths-ignore: - 'versions-manifest.json' - 'LICENSE' - '**.md' branches: - 'main' env: VERSION: ${{ github.event.inputs.VERSION || '3.9.9' }} defaults: run: 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,ubuntu-22.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: ${{ 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 }} steps: - name: Check out repository code uses: actions/checkout@v2 with: submodules: true - name: Build Python ${{ env.VERSION }} run: | ./builders/build-python.ps1 -Version $env:VERSION ` -Platform ${{ matrix.platform }} -Architecture ${{ matrix.arch }} - name: Publish artifact uses: actions/upload-artifact@v2 with: name: ${{ env.ARTIFACT_NAME }} path: ${{ runner.temp }}/artifact test_python: needs: [generate_matrix, build_python] strategy: fail-fast: false matrix: 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 }} steps: - name: Check out repository code uses: actions/checkout@v2 with: submodules: true - name: Fully cleanup the toolcache directory before testing run: ./helpers/clean-toolcache.ps1 -ToolName "Python" - name: Download artifact uses: actions/download-artifact@v2 with: path: ${{ runner.temp }} - name: Extract files run: | if ('${{ matrix.platform }}' -eq 'win32') { $artifactName = "${{ env.ARTIFACT_NAME }}.zip" 7z.exe x "$artifactName" -y | Out-Null } else { $artifactName = "${{ env.ARTIFACT_NAME }}.tar.gz" tar -xzf $artifactName } working-directory: ${{ runner.temp }}/${{ env.ARTIFACT_NAME }} - name: Apply build artifact to the local machine run: | if ('${{ matrix.platform }}' -eq 'win32') { powershell ./setup.ps1 } else { sh ./setup.sh cp ${{ runner.temp }}/${{ env.ARTIFACT_NAME }}/build_output.txt ${{ runner.temp }} } working-directory: ${{ runner.temp }}/${{ env.ARTIFACT_NAME }} - name: Setup Python ${{ env.VERSION }} uses: actions/setup-python@v2 with: python-version: ${{ env.VERSION }} architecture: ${{ matrix.arch }} - name: Verbose sysconfig dump if: runner.os == 'Linux' || runner.os == 'macOS' run: python ./sources/python-config-output.py working-directory: ${{ github.workspace }}/tests - name: Verbose python binary links if: runner.os == 'Linux' || runner.os == 'macOS' run: | $pythonLocation = which python if ('${{ matrix.platform }}' -eq 'darwin') { otool -L $pythonLocation } else { ldd $pythonLocation } - name: Run tests run: | Install-Module Pester -Force -Scope CurrentUser Import-Module Pester $pesterContainer = New-PesterContainer -Path './python-tests.ps1' -Data @{ Version="${{ env.VERSION }}"; Platform="${{ matrix.platform }}"; } $Result = Invoke-Pester -Container $pesterContainer -PassThru if ($Result.FailedCount -gt 0) { $host.SetShouldExit($Result.FailedCount) exit $Result.FailedCount } working-directory: ${{ github.workspace }}/tests publish_release: name: Publish release if: github.event_name == 'workflow_dispatch' && github.event.inputs.PUBLISH_RELEASES == 'true' needs: test_python runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v2 - name: Publish Release ${{ env.VERSION }} id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ env.VERSION }}-${{ github.run_id }} release_name: ${{ env.VERSION }} body: | Python ${{ env.VERSION }} - name: Upload release assets uses: actions/github-script@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const fs = require('fs'); for (let artifactDir of fs.readdirSync('.')) { let artifactName = fs.readdirSync(`${artifactDir}`)[0]; console.log(`Upload ${artifactName} asset`); github.repos.uploadReleaseAsset({ owner: context.repo.owner, repo: context.repo.repo, release_id: ${{ steps.create_release.outputs.id }}, name: artifactName, data: fs.readFileSync(`./${artifactDir}/${artifactName}`) }); } trigger_pr: name: Trigger "Create Pull Request" workflow needs: publish_release runs-on: ubuntu-latest steps: - name: Trigger "Create Pull Request" workflow uses: actions/github-script@v3 with: github-token: ${{ secrets.PERSONAL_TOKEN }} script: | github.actions.createWorkflowDispatch({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'create-pr.yml', ref: 'main' });