Main packaging #182
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-FileCopyrightText: 2026 geisserml <geisserml@gmail.com> | |
| # SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause | |
| # Maintainer's note: This workflow is registered for trusted publishing on pypdfium2's PyPI page, by filename. So if this file shall be renamed, remember to update the filename in PyPI settings as well. | |
| name: Main packaging | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| test: | |
| default: true | |
| type: boolean | |
| augment: | |
| default: false | |
| type: boolean | |
| publish: | |
| default: false | |
| type: boolean | |
| conda: | |
| default: false | |
| type: boolean | |
| py_version: | |
| default: '3.12' | |
| type: string | |
| runner: | |
| default: 'ubuntu-latest' | |
| type: string | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| build: | |
| runs-on: ${{ inputs.runner }} | |
| outputs: | |
| new_version: ${{ steps.get_version.outputs.new_version }} | |
| steps: | |
| - uses: extractions/setup-just@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ inputs.py_version }} | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: ${{ github.repository }} | |
| fetch-depth: 0 # for git describe in "Get new version" step | |
| persist-credentials: true # needed for push | |
| - name: Install/update dependencies | |
| run: python3 -m pip install -U -r req/setup.txt -r req/test.txt -r req/utilities.txt | |
| # NOTE autorelease sets a tag, but it's just temporary for informational purpose and does not match the actually published tag | |
| # We can't push the tag at this stage because we don't know the outcome of the following jobs yet | |
| # In the future, we might want to move away from using a git branch & tag at this stage, and instead transfer the changes as a patchfile. | |
| - name: Run autorelease script | |
| run: | | |
| git config user.email "geisserml@gmail.com" | |
| git config user.name "geisserml" | |
| git reset --hard HEAD | |
| # autorelease.py --register automatically switches us onto the autorelease_tmp branch | |
| python3 setupsrc/autorelease.py --register | |
| - name: Get new version | |
| id: get_version | |
| run: echo "new_version=$(git describe --abbrev=0)" >> $GITHUB_OUTPUT | |
| - name: Install pypdfium2 | |
| run: python3 -m pip install -v --no-build-isolation -e . | |
| - name: Run test suite | |
| run: python3 -m pytest tests/ | |
| # TODO make controllable whether musllinux packages are built through pdfium-binaries or cibw augmentation, consider enabling them here if inputs.augment is false | |
| - name: Run PyPI packaging script | |
| run: just packaging-pypi | |
| env: | |
| # only passed to craft.py, which uses a GH REST API that can hit rate limits otherwise | |
| GH_TOKEN: ${{ github.token }} | |
| - name: Upload release notes | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: release_notes | |
| path: RELEASE.md | |
| # https://github.com/actions/upload-artifact/issues/331 ... | |
| - name: Upload packages | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: packages | |
| path: dist/* | |
| # tag deliberately not pushed (see above) | |
| - name: Push autorelease_tmp branch | |
| run: git push -u origin autorelease_tmp | |
| test: | |
| if: ${{ inputs.test }} | |
| needs: build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ['ubuntu-latest', 'ubuntu-24.04-arm', 'macos-15-intel', 'macos-latest', 'windows-latest', 'windows-11-arm'] | |
| py: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] | |
| exclude: | |
| # not supported by setup-python action | |
| - os: windows-11-arm | |
| py: '3.8' | |
| - os: windows-11-arm | |
| py: '3.9' | |
| - os: windows-11-arm | |
| py: '3.10' | |
| include: | |
| - os: ubuntu-latest | |
| wheel: dist/*manylinux_*_x86_64*.whl | |
| - os: ubuntu-24.04-arm | |
| wheel: dist/*manylinux_*_aarch64*.whl | |
| - os: macos-15-intel | |
| wheel: dist/*macosx_*_x86_64*.whl | |
| - os: macos-latest | |
| wheel: dist/*macosx_*_arm64*.whl | |
| - os: windows-latest | |
| wheel: dist/*win_amd64.whl | |
| - os: windows-11-arm | |
| wheel: dist/*win_arm64.whl | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.py }} | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: ${{ github.repository }} | |
| ref: autorelease_tmp | |
| persist-credentials: false | |
| - name: Download packages | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: packages | |
| path: dist/ | |
| - name: Install dependencies | |
| run: | | |
| python3 -m pip install -U pip setuptools | |
| python3 -m pip install -U pytest pillow numpy | |
| - name: Install and run auditwheel (informational) | |
| if: ${{ startsWith(matrix.os, 'ubuntu') }} | |
| run: | | |
| python3 -m pip install -U auditwheel | |
| python3 -m auditwheel show $WHEEL | |
| env: | |
| WHEEL: ${{ matrix.wheel }} | |
| - name: Install pypdfium2 from artifact | |
| run: python3 -m pip install $WHEEL | |
| env: | |
| WHEEL: ${{ matrix.wheel }} | |
| - name: Run Test Suite | |
| run: python3 -m pytest tests/ | |
| augment_cibw: | |
| if: ${{ inputs.augment }} | |
| needs: build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: x86_64 | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: i686 | |
| - os: ubuntu-24.04-arm | |
| cibw_class: musllinux | |
| cibw_arch: aarch64 | |
| - os: ubuntu-24.04-arm | |
| cibw_class: musllinux | |
| cibw_arch: armv7l | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: ppc64le | |
| - os: ubuntu-latest | |
| cibw_class: manylinux | |
| cibw_arch: riscv64 | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: riscv64 | |
| - os: ubuntu-latest | |
| cibw_class: manylinux | |
| cibw_arch: loongarch64 | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: loongarch64 | |
| - os: ubuntu-latest | |
| cibw_class: manylinux | |
| cibw_arch: s390x | |
| - os: ubuntu-latest | |
| cibw_class: musllinux | |
| cibw_arch: s390x | |
| uses: ./.github/workflows/cibw_one.yaml | |
| with: | |
| os: ${{ matrix.os }} | |
| cibw_target: ${{ matrix.cibw_class }}_${{ matrix.cibw_arch }} | |
| cibw_arch: ${{ matrix.cibw_arch }} | |
| repo_tag: ${{ needs.build.outputs.new_version }} | |
| branch: autorelease_tmp | |
| test_pdfium: true | |
| # # NOTE ppc64le is now supported with pdfium-binaries, commented out. However, this strategy might be useful for other platforms in the future. | |
| # augment_sbuild: | |
| # | |
| # if: ${{ inputs.augment }} | |
| # needs: build | |
| # | |
| # strategy: | |
| # fail-fast: false | |
| # matrix: | |
| # include: | |
| # - os: ubuntu-latest | |
| # target_cpu: ppc64le | |
| # tag: manylinux_2_17_ppc64le.manylinux2014_ppc64le | |
| # | |
| # uses: ./.github/workflows/sbuild_one.yaml | |
| # with: | |
| # os: ${{ matrix.os }} | |
| # target_cpu: ${{ matrix.target_cpu }} | |
| # tag: ${{ matrix.tag }} | |
| # py_version: ${{ inputs.py_version }} | |
| # repo_tag: ${{ needs.build.outputs.new_version }} | |
| # branch: autorelease_tmp | |
| publish: | |
| needs: | |
| - build | |
| - test | |
| - augment_cibw | |
| # - augment_sbuild | |
| if: ${{ inputs.publish && !cancelled() && !contains(needs.*.result, 'failure') }} | |
| runs-on: ${{ inputs.runner }} | |
| environment: release # PyPI upload via "trusted publishing" | |
| permissions: | |
| id-token: write # PyPI upload via "trusted publishing", and GH attestation | |
| attestations: write # GH attestation | |
| contents: write # autorelease repository changes | |
| actions: write # GH pages workflow-dispatch | |
| steps: | |
| - name: Check out repository (deep) | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: ${{ github.repository }} | |
| fetch-depth: 0 | |
| persist-credentials: true # needed for push | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ inputs.py_version }} | |
| - name: Download release notes | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: release_notes | |
| - name: Download main packages | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: dist/ | |
| name: packages | |
| - name: Download extra packages (cibw) | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: dist/ | |
| merge-multiple: true | |
| pattern: cibw-* | |
| # - name: Download extra packages (sbuild) | |
| # uses: actions/download-artifact@v8 | |
| # with: | |
| # path: dist/ | |
| # merge-multiple: true | |
| # pattern: sbuild_* | |
| - name: Isolate non-PyPI builds | |
| if: ${{ inputs.augment }} | |
| run: | | |
| mkdir gh_only | |
| mv dist/*linux_*_loongarch64*.whl gh_only/ | |
| - name: Apply and push repository changes | |
| run: | | |
| git config user.email "geisserml@gmail.com" | |
| git config user.name "geisserml" | |
| git checkout main | |
| git merge origin/autorelease_tmp | |
| git tag -a "$NEW_VERSION" -m "Autorelease" | |
| git push | |
| git push --tags | |
| git checkout stable | |
| git reset --hard main | |
| git push --force | |
| git checkout main | |
| env: | |
| NEW_VERSION: ${{ needs.build.outputs.new_version }} | |
| # Upload to TestPyPI / PyPI via "trusted publishing". | |
| # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ | |
| # https://docs.pypi.org/trusted-publishers/using-a-publisher/ | |
| # https://github.com/pypa/gh-action-pypi-publish | |
| - name: Publish to TestPyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| packages-dir: dist/ # the default | |
| # https://github.com/pypa/gh-action-pypi-publish/issues/283#issuecomment-2499296440 | |
| attestations: false | |
| verbose: true | |
| - name: Attest build provenance | |
| id: provenance | |
| uses: actions/attest-build-provenance@v4 | |
| with: | |
| subject-path: 'dist/*, gh_only/*' | |
| - name: Rename provenance file | |
| run: mv "$SRC_PATH" pypdfium2-attestation.json | |
| env: | |
| SRC_PATH: ${{ steps.provenance.outputs.bundle-path }} | |
| # FIXME skip gh_only/*.whl if !inputs.augment | |
| - name: Publish to GitHub | |
| uses: ncipollo/release-action@v1 | |
| with: | |
| immutableCreate: true | |
| artifacts: 'dist/*.whl,gh_only/*.whl,dist/*.tar.gz,pypdfium2-attestation.json' | |
| bodyFile: 'RELEASE.md' | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| tag: ${{ needs.build.outputs.new_version }} | |
| prerelease: ${{ contains(needs.build.outputs.new_version, 'b') }} | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: dist/ # the default | |
| - name: Trigger GH Pages rebuild | |
| uses: benc-uk/workflow-dispatch@v1 | |
| with: | |
| workflow: gh_pages.yaml # takes no inputs | |
| conda_trigger: | |
| needs: publish # i.e. goes after, regardless if publish is active or not | |
| if: ${{ inputs.conda && !cancelled() && !contains(needs.*.result, 'failure') }} | |
| runs-on: ${{ inputs.runner }} | |
| steps: | |
| - name: Trigger conda pypdfium2_helpers build | |
| uses: benc-uk/workflow-dispatch@v1 | |
| with: | |
| workflow: conda.yaml | |
| inputs: | | |
| { | |
| "package": "helpers", | |
| "pdfium_ver": "latest", | |
| "new_only": "false", | |
| "test": "true", | |
| "publish": "${{ inputs.publish }}", | |
| "py_version": "${{ inputs.py_version }}" | |
| } | |
| cleanup: | |
| needs: [publish, conda_trigger] | |
| if: ${{ !cancelled() }} | |
| runs-on: ${{ inputs.runner }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| repository: ${{ github.repository }} | |
| persist-credentials: true # needed for push | |
| - name: Remove temporary branch | |
| run: git push origin --delete autorelease_tmp |