| # 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. |
| |
| # Publish Python wheels after the orchestrator has confirmed the wheel |
| # build completed successfully. |
| |
| name: Release Python Publish |
| |
| on: |
| workflow_call: |
| |
| concurrency: |
| group: release-python-publish-${{ github.ref }} |
| cancel-in-progress: false |
| |
| permissions: |
| actions: read |
| contents: read |
| |
| jobs: |
| publish: |
| name: Publish to PyPI |
| if: github.repository == 'apache/paimon-full-text' && startsWith(github.ref, 'refs/tags/') |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/download-artifact@v5 |
| with: |
| pattern: wheels-* |
| merge-multiple: true |
| path: dist |
| |
| - name: Verify wheel versions |
| env: |
| TAG_NAME: ${{ github.ref_name }} |
| shell: bash |
| run: | |
| set -euo pipefail |
| |
| expected_version="${TAG_NAME#v}" |
| expected_version="${expected_version/-rc/rc}" |
| shopt -s nullglob |
| wheels=(dist/*.whl) |
| |
| if [[ "${#wheels[@]}" -eq 0 ]]; then |
| echo "No wheels found in dist" >&2 |
| exit 1 |
| fi |
| |
| for wheel in "${wheels[@]}"; do |
| base="$(basename "$wheel")" |
| case "$base" in |
| paimon_ftindex-"${expected_version}"-*.whl) ;; |
| *) |
| echo "Unexpected wheel for ${TAG_NAME}: ${base}" >&2 |
| exit 1 |
| ;; |
| esac |
| done |
| |
| - name: Verify wheel native libraries |
| shell: bash |
| run: | |
| set -euo pipefail |
| |
| python - <<'PY' |
| from pathlib import Path |
| from zipfile import ZipFile |
| |
| expected_suffixes = (".so", ".dylib", ".dll") |
| wheels = sorted(Path("dist").glob("*.whl")) |
| if not wheels: |
| raise SystemExit("No wheels found in dist") |
| |
| for wheel in wheels: |
| with ZipFile(wheel) as zf: |
| names = set(zf.namelist()) |
| libs = [ |
| name |
| for name in names |
| if name.startswith("paimon_ftindex/libpaimon_ftindex_ffi") |
| or name == "paimon_ftindex/paimon_ftindex_ffi.dll" |
| ] |
| required_metadata = { |
| "paimon_ftindex/LICENSE", |
| "paimon_ftindex/NOTICE", |
| "paimon_ftindex/DEPENDENCIES.rust.tsv", |
| } |
| if not libs: |
| raise SystemExit(f"{wheel.name} does not contain the native FFI library") |
| if not any(lib.endswith(expected_suffixes) for lib in libs): |
| raise SystemExit(f"{wheel.name} has unexpected native library names: {libs}") |
| missing_metadata = sorted(required_metadata - names) |
| if missing_metadata: |
| raise SystemExit( |
| f"{wheel.name} is missing license metadata: {missing_metadata}" |
| ) |
| if any(name.startswith("tests/") for name in names): |
| raise SystemExit(f"{wheel.name} unexpectedly contains tests/") |
| PY |
| |
| - name: Publish to TestPyPI |
| if: contains(github.ref_name, '-rc') |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e |
| with: |
| repository-url: https://test.pypi.org/legacy/ |
| skip-existing: true |
| packages-dir: dist |
| password: ${{ secrets.TEST_PYPI_API_TOKEN }} |
| |
| - name: Publish to PyPI |
| if: ${{ !contains(github.ref_name, '-') }} |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e |
| with: |
| skip-existing: true |
| packages-dir: dist |
| password: ${{ secrets.PYPI_API_TOKEN }} |