name: "Python Release" on: workflow_dispatch: inputs: tag: description: "The version to tag, without the leading 'v'. If omitted, will initiate a dry run (no uploads)." type: string sha: description: "The full sha of the commit to be released. If omitted, the latest commit on the default branch will be used." default: "" type: string pull_request: paths: # When we change pyproject.toml, we want to ensure that the maturin builds still work - py-rattler/pyproject.toml # And when we change this workflow itself... - .github/workflows/release-python.yml concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: PACKAGE_NAME: py_rattler PYTHON_VERSION: "3.11" CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 CARGO_TERM_COLOR: always RUSTUP_MAX_RETRIES: 10 jobs: sdist: name: Build sdist runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: "Build sdist" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler command: sdist args: --out dist - name: "Test sdist" run: | rustup default $(cat rust-toolchain) pip install py-rattler/dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall python -c "import rattler; print(rattler.__version__)" - name: "Upload sdist" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: sdist path: py-rattler/dist windows: runs-on: windows-latest name: Build ${{ matrix.platform.target }} strategy: fail-fast: false matrix: platform: - target: x86_64-pc-windows-msvc arch: x64 - target: i686-pc-windows-msvc arch: x86 # There are a number of issues with cross compiling ring to windows on aarch64. # For now, we just won't build a wheel, we will revisit this in the future. # - target: aarch64-pc-windows-msvc # arch: x64 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} architecture: ${{ matrix.platform.arch }} - name: "Build wheels" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.platform.target }} args: --release --out dist --no-default-features --features rustls-tls - name: "Test wheel" if: ${{ !startsWith(matrix.platform.target, 'aarch64') }} shell: bash run: | python -m pip install py-rattler/dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall python -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: windows-wheels-${{ matrix.platform.target }} path: py-rattler/dist linux: runs-on: ubuntu-latest name: Build ${{ matrix.target }} strategy: fail-fast: false matrix: target: - x86_64-unknown-linux-gnu - i686-unknown-linux-gnu steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 - name: "Build wheels" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.target }} manylinux: auto args: --release --out dist --no-default-features --features rustls-tls,pty - name: "Test wheel" if: ${{ startsWith(matrix.target, 'x86_64') }} run: | pip install py-rattler/dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall python3 -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: linux-wheels-${{ matrix.target }} path: py-rattler/dist linux-cross: runs-on: ubuntu-latest name: Build ${{ matrix.platform.target }} strategy: fail-fast: false matrix: platform: - target: aarch64-unknown-linux-gnu arch: aarch64 - target: armv7-unknown-linux-gnueabihf arch: armv7 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: "Build wheels" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.platform.target }} manylinux: "2_28" args: --release --out dist --no-default-features --features rustls-tls,pty - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 if: matrix.platform.arch != 'ppc64' name: Test wheel with: arch: ${{ matrix.platform.arch }} distro: ubuntu20.04 githubToken: ${{ github.token }} install: | apt-get update apt-get install -y --no-install-recommends python3 python3-pip pip3 install -U pip run: | pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links py-rattler/dist/ --force-reinstall python3 -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: linux-wheels-${{ matrix.platform.target }} path: py-rattler/dist linux-cross-native-tls: runs-on: ubuntu-latest name: Build ${{ matrix.platform.target }} strategy: fail-fast: false matrix: platform: # - target: s390x-unknown-linux-gnu # arch: s390x - target: powerpc64le-unknown-linux-gnu arch: ppc64le - target: powerpc64-unknown-linux-gnu arch: ppc64 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: "Build wheels" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.platform.target }} manylinux: auto args: --release --out dist --no-default-features --features native-tls,vendored-openssl,pty - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 if: matrix.platform.arch != 'ppc64' name: Test wheel with: arch: ${{ matrix.platform.arch }} distro: ubuntu20.04 githubToken: ${{ github.token }} install: | apt-get update apt-get install -y --no-install-recommends python3 python3-pip pip3 install -U pip run: | pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links py-rattler/dist/ --force-reinstall python3 -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: linux-wheels-${{ matrix.platform.target }} path: py-rattler/dist musllinux: runs-on: ubuntu-latest name: Build ${{ matrix.target }} strategy: fail-fast: false matrix: target: - x86_64-unknown-linux-musl - i686-unknown-linux-musl steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 - name: "Build wheels (rustls-tls)" if: matrix.target == 'x86_64-unknown-linux-musl' uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.target }} manylinux: musllinux_1_2 args: --release --out dist --no-default-features --features rustls-tls,pty - name: "Build wheels (native-tls)" if: matrix.target != 'x86_64-unknown-linux-musl' uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.target }} manylinux: musllinux_1_2 args: --release --out dist --no-default-features --features native-tls,vendored-openssl,pty - name: "Test wheel" if: matrix.target == 'x86_64-unknown-linux-musl' uses: addnab/docker-run-action@4f65fabd2431ebc8d299f8e5a018d79a769ae185 # v3 with: image: alpine:latest options: -v ${{ github.workspace }}:/io -w /io run: | apk add py3-pip pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/py-rattler/dist/ --force-reinstall --break-system-packages python3 -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: linux-wheels-${{ matrix.target }} path: py-rattler/dist musllinux-cross: runs-on: ubuntu-latest name: Build ${{ matrix.platform.target }} strategy: fail-fast: false matrix: platform: - target: aarch64-unknown-linux-musl arch: aarch64 - target: armv7-unknown-linux-musleabihf arch: armv7 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: "Build wheels" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: ${{ matrix.platform.target }} manylinux: musllinux_1_2 args: --release --out dist --no-default-features --features rustls-tls,pty - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1 name: Test wheel with: arch: ${{ matrix.platform.arch }} distro: alpine_latest githubToken: ${{ github.token }} install: | apk add py3-pip run: | pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links py-rattler/dist/ --force-reinstall --break-system-packages python3 -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: linux-wheels-${{ matrix.platform.target }} path: py-rattler/dist macos-x86_64: runs-on: macos-15-intel # x86_64 runner name: Build x86_64-macos steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 - name: "Build wheels - x86_64" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: working-directory: py-rattler target: x86_64 args: --release --out dist --no-default-features --features rustls-tls,pty - name: "Test wheel - x86_64" run: | pip install py-rattler/dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall python -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: macos-wheels-x86_64 path: py-rattler/dist macos-universal: runs-on: macos-latest name: Build universal2-apple-macos steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: ${{ env.PYTHON_VERSION }} architecture: x64 - name: "Build wheels - universal2" uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 with: args: --release --target universal2-apple-darwin --out dist --no-default-features --features rustls-tls,pty working-directory: py-rattler - name: "Test wheel - universal2" run: | pip install py-rattler/dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall python -c "import rattler; print(rattler.__version__)" - name: "Upload wheels" uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: macos-wheels-universal2 path: py-rattler/dist validate-tag: name: Validate tag runs-on: ubuntu-latest # If you don't set an input tag, it's a dry run (no uploads). if: ${{ inputs.tag }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: main # We checkout the main branch to check for the commit - name: Check main branch if: ${{ inputs.sha }} run: | # Fetch the main branch since a shallow checkout is used by default git fetch origin main --unshallow if ! git branch --contains ${{ inputs.sha }} | grep -E '(^|\s)main$'; then echo "The specified sha is not on the main branch" >&2 exit 1 fi - name: Check tag consistency run: | # Switch to the commit we want to release git checkout ${{ inputs.sha }} version=$(grep -m 1 "version = " py-rattler/Cargo.toml | sed -e 's/version = "\(.*\)"/\1/g') if [ "${{ inputs.tag }}" != "${version}" ]; then echo "The input tag does not match the version from Cargo.toml:" >&2 echo "${{ inputs.tag }}" >&2 echo "${version}" >&2 exit 1 else echo "Releasing ${version}" fi extract-changelog: name: Extract changelog runs-on: ubuntu-latest if: ${{ inputs.tag }} outputs: release_notes: ${{ steps.release_notes.outputs.release_notes }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} - name: Extract release notes id: release_notes uses: ffurrer2/extract-release-notes@202313ec7461b6b9e401996714484690ab1ae105 # v3 with: changelog_file: py-rattler/CHANGELOG.md - name: Verify release notes run: | if [ -z '${{ steps.release_notes.outputs.release_notes }}' ]; then echo "No release notes found for the latest version in py-rattler/CHANGELOG.md" >&2 exit 1 fi upload-release: name: Upload to PyPI runs-on: ubuntu-latest needs: - sdist - macos-universal - macos-x86_64 - windows - linux - linux-cross - linux-cross-native-tls - musllinux - musllinux-cross - validate-tag - extract-changelog # If you don't set an input tag, it's a dry run (no uploads). if: ${{ inputs.tag }} environment: name: release permissions: # For pypi trusted publishing id-token: write steps: - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: merge-multiple: true path: wheels - name: Publish to PyPi uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1 with: skip-existing: true packages-dir: wheels verbose: true tag-release: name: Tag release runs-on: ubuntu-latest needs: - upload-release - extract-changelog # If you don't set an input tag, it's a dry run (no uploads). if: ${{ inputs.tag }} permissions: # For creating the GitHub release and tag contents: write steps: - name: Create GitHub Release env: GH_TOKEN: ${{ github.token }} run: | gh release create "py-rattler-v${{ inputs.tag }}" \ --repo "${{ github.repository }}" \ --target "${{ inputs.sha || github.sha }}" \ --title "py-rattler v${{ inputs.tag }}" \ --notes '${{ needs.extract-changelog.outputs.release_notes }}' deploy-release-docs: name: Deploy release docs runs-on: ubuntu-latest needs: tag-release if: ${{ inputs.tag }} permissions: contents: write concurrency: group: gh-pages-deploy cancel-in-progress: false steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ inputs.sha }} fetch-depth: 0 submodules: recursive - uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3 with: manifest-path: py-rattler/pixi.toml environments: docs - name: Configure Git user run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - name: Set version env: INPUT_TAG: ${{ inputs.tag }} run: echo "RELEASE_VERSION=v${INPUT_TAG}" >> $GITHUB_ENV - name: Deploy with mike run: pixi run --manifest-path py-rattler/pixi.toml deploy-latest - name: Add py-rattler redirect to latest run: | git clone --branch gh-pages https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git gh-pages-repo echo '' > gh-pages-repo/py-rattler/index.html cd gh-pages-repo git config user.email "github-actions[bot]@users.noreply.github.com" git config user.name "github-actions[bot]" git add . git diff --staged --quiet || (git commit -m "docs: update py-rattler redirect" && git push)