| # 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: Python Release Build |
| on: |
| pull_request: |
| branches: ["main"] |
| push: |
| tags: ["*-rc*"] |
| branches: ["branch-*"] |
| |
| jobs: |
| build: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v5 |
| - name: Install Python |
| uses: actions/setup-python@v6 |
| with: |
| python-version: "3.12" |
| |
| - uses: astral-sh/setup-uv@v7 |
| with: |
| enable-cache: true |
| |
| # Use the --no-install-package to only install the dependencies |
| # but do not yet build the rust library |
| - name: Install dependencies |
| run: uv sync --dev --no-install-package datafusion |
| |
| # Update output format to enable automatic inline annotations. |
| - name: Run Ruff |
| run: | |
| uv run --no-project ruff check --output-format=github python/ |
| uv run --no-project ruff format --check python/ |
| |
| - name: Run codespell |
| run: | |
| uv run --no-project codespell --toml pyproject.toml |
| |
| generate-license: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v5 |
| - uses: astral-sh/setup-uv@v7 |
| with: |
| enable-cache: true |
| |
| - name: Generate license file |
| run: uv run --no-project python ./dev/create_license.py |
| - uses: actions/upload-artifact@v4 |
| with: |
| name: python-wheel-license |
| path: LICENSE.txt |
| |
| build-python-mac-win: |
| needs: [generate-license] |
| name: Mac/Win |
| runs-on: ${{ matrix.os }} |
| strategy: |
| fail-fast: false |
| matrix: |
| python-version: ["3.10"] |
| os: [macos-latest, windows-latest] |
| steps: |
| - uses: actions/checkout@v5 |
| |
| - uses: actions/setup-python@v6 |
| with: |
| python-version: ${{ matrix.python-version }} |
| |
| - uses: dtolnay/rust-toolchain@stable |
| |
| - run: rm LICENSE.txt |
| - name: Download LICENSE.txt |
| uses: actions/download-artifact@v5 |
| with: |
| name: python-wheel-license |
| path: . |
| |
| - name: Install Protoc |
| uses: arduino/setup-protoc@v3 |
| with: |
| version: "27.4" |
| repo-token: ${{ secrets.GITHUB_TOKEN }} |
| |
| - uses: astral-sh/setup-uv@v7 |
| with: |
| enable-cache: true |
| |
| - name: Build Python package |
| run: | |
| uv sync --dev --no-install-package datafusion |
| uv run --no-project maturin build --release --strip --features substrait |
| |
| - name: List Windows wheels |
| if: matrix.os == 'windows-latest' |
| run: dir target\wheels\ |
| # since the runner is dynamic shellcheck (from actionlint) can't infer this is powershell |
| # so we specify it explicitly |
| shell: powershell |
| |
| - name: List Mac wheels |
| if: matrix.os != 'windows-latest' |
| run: find target/wheels/ |
| |
| - name: Archive wheels |
| uses: actions/upload-artifact@v4 |
| with: |
| name: dist-${{ matrix.os }} |
| path: target/wheels/* |
| |
| build-macos-x86_64: |
| needs: [generate-license] |
| name: Mac x86_64 |
| runs-on: macos-15-intel |
| strategy: |
| fail-fast: false |
| matrix: |
| python-version: ["3.10"] |
| steps: |
| - uses: actions/checkout@v5 |
| |
| - uses: actions/setup-python@v6 |
| with: |
| python-version: ${{ matrix.python-version }} |
| |
| - uses: dtolnay/rust-toolchain@stable |
| |
| - run: rm LICENSE.txt |
| - name: Download LICENSE.txt |
| uses: actions/download-artifact@v5 |
| with: |
| name: python-wheel-license |
| path: . |
| |
| - name: Install Protoc |
| uses: arduino/setup-protoc@v3 |
| with: |
| version: "27.4" |
| repo-token: ${{ secrets.GITHUB_TOKEN }} |
| |
| - uses: astral-sh/setup-uv@v7 |
| with: |
| enable-cache: true |
| |
| - name: Build Python package |
| run: | |
| uv sync --dev --no-install-package datafusion |
| uv run --no-project maturin build --release --strip --features substrait |
| |
| - name: List Mac wheels |
| run: find target/wheels/ |
| |
| - name: Archive wheels |
| uses: actions/upload-artifact@v4 |
| with: |
| name: dist-macos-aarch64 |
| path: target/wheels/* |
| |
| build-manylinux-x86_64: |
| needs: [generate-license] |
| name: Manylinux x86_64 |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v5 |
| - run: rm LICENSE.txt |
| - name: Download LICENSE.txt |
| uses: actions/download-artifact@v5 |
| with: |
| name: python-wheel-license |
| path: . |
| - run: cat LICENSE.txt |
| - name: Build wheels |
| uses: PyO3/maturin-action@v1 |
| env: |
| RUST_BACKTRACE: 1 |
| with: |
| rust-toolchain: nightly |
| target: x86_64 |
| manylinux: auto |
| rustup-components: rust-std rustfmt # Keep them in one line due to https://github.com/PyO3/maturin-action/issues/153 |
| args: --release --manylinux 2014 --features protoc,substrait |
| - name: Archive wheels |
| uses: actions/upload-artifact@v4 |
| with: |
| name: dist-manylinux-x86_64 |
| path: target/wheels/* |
| |
| build-manylinux-aarch64: |
| needs: [generate-license] |
| name: Manylinux arm64 |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v5 |
| - run: rm LICENSE.txt |
| - name: Download LICENSE.txt |
| uses: actions/download-artifact@v5 |
| with: |
| name: python-wheel-license |
| path: . |
| - run: cat LICENSE.txt |
| - name: Build wheels |
| uses: PyO3/maturin-action@v1 |
| env: |
| RUST_BACKTRACE: 1 |
| with: |
| rust-toolchain: nightly |
| target: aarch64 |
| # Use manylinux_2_28-cross because the manylinux2014-cross has GCC 4.8.5, which causes the build to fail |
| manylinux: 2_28 |
| rustup-components: rust-std rustfmt # Keep them in one line due to https://github.com/PyO3/maturin-action/issues/153 |
| args: --release --features protoc,substrait |
| - name: Archive wheels |
| uses: actions/upload-artifact@v4 |
| with: |
| name: dist-manylinux-aarch64 |
| path: target/wheels/* |
| |
| build-sdist: |
| needs: [generate-license] |
| name: Source distribution |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v5 |
| - run: rm LICENSE.txt |
| - name: Download LICENSE.txt |
| uses: actions/download-artifact@v5 |
| with: |
| name: python-wheel-license |
| path: . |
| - run: cat LICENSE.txt |
| - name: Build sdist |
| uses: PyO3/maturin-action@v1 |
| with: |
| rust-toolchain: stable |
| manylinux: auto |
| rustup-components: rust-std rustfmt |
| args: --release --sdist --out dist --features protoc,substrait |
| - name: Assert sdist build does not generate wheels |
| run: | |
| if [ "$(ls -A target/wheels)" ]; then |
| echo "Error: Sdist build generated wheels" |
| exit 1 |
| else |
| echo "Directory is clean" |
| fi |
| shell: bash |
| |
| merge-build-artifacts: |
| runs-on: ubuntu-latest |
| needs: |
| - build-python-mac-win |
| - build-macos-x86_64 |
| - build-manylinux-x86_64 |
| - build-manylinux-aarch64 |
| - build-sdist |
| steps: |
| - name: Merge Build Artifacts |
| uses: actions/upload-artifact/merge@v4 |
| with: |
| name: dist |
| pattern: dist-* |
| |
| # Documentation build job that runs after wheels are built |
| build-docs: |
| name: Build docs |
| runs-on: ubuntu-latest |
| needs: [build-manylinux-x86_64] # Only need the Linux wheel for docs |
| # Only run docs on main branch pushes, tags, or PRs |
| if: github.event_name == 'push' || github.event_name == 'pull_request' |
| steps: |
| - name: Set target branch |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') |
| id: target-branch |
| run: | |
| set -x |
| if test '${{ github.ref }}' = 'refs/heads/main'; then |
| echo "value=asf-staging" >> "$GITHUB_OUTPUT" |
| elif test '${{ github.ref_type }}' = 'tag'; then |
| echo "value=asf-site" >> "$GITHUB_OUTPUT" |
| else |
| echo "Unsupported input: ${{ github.ref }} / ${{ github.ref_type }}" |
| exit 1 |
| fi |
| |
| - name: Checkout docs sources |
| uses: actions/checkout@v5 |
| |
| - name: Checkout docs target branch |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') |
| uses: actions/checkout@v5 |
| with: |
| fetch-depth: 0 |
| ref: ${{ steps.target-branch.outputs.value }} |
| path: docs-target |
| |
| - name: Setup Python |
| uses: actions/setup-python@v6 |
| with: |
| python-version: "3.11" |
| |
| - name: Install dependencies |
| uses: astral-sh/setup-uv@v7 |
| with: |
| enable-cache: true |
| |
| # Download the Linux wheel built in the previous job |
| - name: Download pre-built Linux wheel |
| uses: actions/download-artifact@v5 |
| with: |
| name: dist-manylinux-x86_64 |
| path: wheels/ |
| |
| # Install from the pre-built wheel |
| - name: Install from pre-built wheel |
| run: | |
| set -x |
| uv venv |
| # Install documentation dependencies |
| uv sync --dev --no-install-package datafusion --group docs |
| # Install the pre-built wheel |
| WHEEL=$(find wheels/ -name "*.whl" | head -1) |
| if [ -n "$WHEEL" ]; then |
| echo "Installing wheel: $WHEEL" |
| uv pip install "$WHEEL" |
| else |
| echo "ERROR: No wheel found!" |
| exit 1 |
| fi |
| |
| - name: Build docs |
| run: | |
| set -x |
| cd docs |
| curl -O https://gist.githubusercontent.com/ritchie46/cac6b337ea52281aa23c049250a4ff03/raw/89a957ff3919d90e6ef2d34235e6bf22304f3366/pokemon.csv |
| curl -O https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2021-01.parquet |
| uv run --no-project make html |
| |
| - name: Copy & push the generated HTML |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') |
| run: | |
| set -x |
| cd docs-target |
| # delete anything but: 1) '.'; 2) '..'; 3) .git/ |
| find ./ | grep -vE "^./$|^../$|^./.git" | xargs rm -rf |
| cp ../.asf.yaml . |
| cp -r ../docs/build/html/* . |
| git status --porcelain |
| if [ "$(git status --porcelain)" != "" ]; then |
| git config user.name "github-actions[bot]" |
| git config user.email "github-actions[bot]@users.noreply.github.com" |
| git add --all |
| git commit -m 'Publish built docs triggered by ${{ github.sha }}' |
| git push || git push --force |
| fi |
| |
| # NOTE: PyPI publish needs to be done manually for now after release passed the vote |
| # release: |
| # name: Publish in PyPI |
| # needs: [build-manylinux, build-python-mac-win] |
| # runs-on: ubuntu-latest |
| # steps: |
| # - uses: actions/download-artifact@v5 |
| # - name: Publish to PyPI |
| # uses: pypa/gh-action-pypi-publish@master |
| # with: |
| # user: __token__ |
| # password: ${{ secrets.pypi_password }} |