Skip to content

Publish Python 🐍 distribution πŸ“¦ to PyPI #45

Publish Python 🐍 distribution πŸ“¦ to PyPI

Publish Python 🐍 distribution πŸ“¦ to PyPI #45

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
name: Publish Python 🐍 distribution πŸ“¦ to PyPI
on:
workflow_run:
workflows: ["Publish"] # Trigger this workflow after the "publish.yml" workflow completes
types:
- completed
workflow_dispatch:
env:
rust_msrv: "1.87"
concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}-${{ github.event_name }}
cancel-in-progress: true
permissions:
contents: read
jobs:
check-cargo-publish:
runs-on: ubuntu-latest
# Only run if the triggering workflow succeeded OR if manually triggered
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
steps:
- run: echo 'The Publish workflow passed or was manually triggered'
validate-release-tag:
runs-on: ubuntu-latest
needs: [check-cargo-publish]
outputs:
cargo-version: ${{ steps.validate.outputs.cargo-version }}
is-rc: ${{ steps.validate.outputs.is-rc }}
steps:
- name: Validate release tag format
id: validate
# Note, `workflow_run.head_branch` does not contain `refs/tags/` prefix, just the tag name, i.e. `v0.4.0` or `v0.4.0-rc.1`
# Valid formats: v<major>.<minor>.<patch> OR v<major>.<minor>.<patch>-rc.<release_candidate>
run: |
RELEASE_TAG="${{ github.event.workflow_run.head_branch }}"
echo "Validating release tag: $RELEASE_TAG"
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$ ]]; then
echo "❌ Invalid release tag format: $RELEASE_TAG"
echo "Expected format: v<major>.<minor>.<patch> OR v<major>.<minor>.<patch>-rc.<release_candidate>"
echo "Examples: v0.4.0, v1.2.3-rc.1"
exit 1
fi
echo "βœ… Release tag format is valid: $RELEASE_TAG"
# Strip 'v' prefix for cargo version
CARGO_VERSION="${RELEASE_TAG#v}"
echo "Cargo version (without v prefix): $CARGO_VERSION"
# Check if this is a release candidate
if [[ "$RELEASE_TAG" =~ -rc\.[0-9]+$ ]]; then
IS_RC="true"
echo "This is a release candidate"
else
IS_RC="false"
echo "This is a stable release"
fi
# Set outputs for other jobs to use
echo "cargo-version=$CARGO_VERSION" >> $GITHUB_OUTPUT
echo "is-rc=$IS_RC" >> $GITHUB_OUTPUT
sdist:
runs-on: ubuntu-latest
needs: [validate-release-tag]
steps:
- uses: actions/checkout@v5
- name: Install toml-cli
if: ${{ needs.validate-release-tag.outputs.is-rc == 'true' }}
run: cargo install toml-cli
- name: Set cargo version for RC
if: ${{ needs.validate-release-tag.outputs.is-rc == 'true' }}
working-directory: "bindings/python"
run: |
echo "Setting cargo version to: ${{ needs.validate-release-tag.outputs.cargo-version }}"
toml set Cargo.toml package.version ${{ needs.validate-release-tag.outputs.cargo-version }} > Cargo.toml.tmp
# doing this explicitly to avoid issue in Windows where `mv` does not overwrite existing file
rm Cargo.toml
mv Cargo.toml.tmp Cargo.toml
- uses: PyO3/maturin-action@v1
with:
working-directory: "bindings/python"
command: sdist
args: -o dist
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: wheels-sdist
path: bindings/python/dist
wheels:
runs-on: "${{ matrix.os }}"
needs: [validate-release-tag]
strategy:
matrix:
include:
- { os: windows-latest }
- { os: macos-latest, target: "universal2-apple-darwin" }
- { os: ubuntu-latest, target: "x86_64" }
- {
os: ubuntu-latest,
target: "aarch64",
manylinux: "manylinux_2_28",
}
- { os: ubuntu-latest, target: "armv7l" }
steps:
- uses: actions/checkout@v5
- name: Install toml-cli
if: ${{ needs.validate-release-tag.outputs.is-rc == 'true' }}
run: cargo install toml-cli
- name: Set cargo version for RC
if: ${{ needs.validate-release-tag.outputs.is-rc == 'true' }}
working-directory: "bindings/python"
run: |
echo "Setting cargo version to: ${{ needs.validate-release-tag.outputs.cargo-version }}"
toml set Cargo.toml package.version ${{ needs.validate-release-tag.outputs.cargo-version }} > Cargo.toml.tmp
# doing this explicitly to avoid issue in Windows where `mv` does not overwrite existing file
rm Cargo.toml
mv Cargo.toml.tmp Cargo.toml
- uses: actions/setup-python@v6
with:
python-version: 3.9
- name: Setup Rust toolchain
uses: ./.github/actions/setup-builder
with:
rust-version: ${{ env.rust_msrv }}
- uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: ${{ matrix.manylinux || 'auto' }}
working-directory: "bindings/python"
command: build
args: --release -o dist
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}-${{ matrix.target }}
path: bindings/python/dist
pypi-publish:
name: Publish Python 🐍 distribution πŸ“¦ to Pypi
needs: [sdist, wheels]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/pyiceberg-core
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v5
with:
pattern: wheels-*
merge-multiple: true
path: bindings/python/dist
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
skip-existing: true
packages-dir: bindings/python/dist