diff --git a/.github/workflows/build-adbc-driver-flightsql.yml b/.github/workflows/build-adbc-driver-flightsql.yml new file mode 100644 index 00000000000..5a08cda23c2 --- /dev/null +++ b/.github/workflows/build-adbc-driver-flightsql.yml @@ -0,0 +1,211 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on upstream's own wheel build at this tag (the python-manylinux job of +# .github/workflows/packaging.yml, ci/scripts/python_util.sh's build_drivers and +# ci/scripts/python_wheel_unix_{build,relocate}.sh): +# https://github.com/apache/arrow-adbc/blob/apache-arrow-adbc-24/.github/workflows/packaging.yml +# Unlike adbc-driver-postgresql/adbc-driver-sqlite, this driver's shared library +# (c/driver/flightsql -> go/adbc/pkg/flightsql, via CMake's add_go_lib) is a cgo +# `go build -buildmode=c-shared`, not a plain C/C++ CMake target, so the manylinux +# image needs a Go toolchain added (the image ships none). The pinned version comes +# from upstream's own .env (the same read native-unix.yml's "Get required Go +# version" step does) and go.dev ships a linux-riscv64 tarball for it. setup.py +# still copies the resulting libadbc_driver_flightsql.so into the package and the +# relocate script's retag step is reproduced inline since it isn't vendored as a +# package file we can invoke directly. See build-adbc-driver-manager.yml for why +# the checkout uses the Go module tag. Testing mirrors native-unix.yml's own +# "Test Python Driver Flight SQL" step: build go/adbc's own +# driver/flightsql/cmd/testserver and run the wheel's tests against it locally, +# no external Flight SQL service (Dremio/GizmoSQL) needed. +name: Build adbc-driver-flightsql wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/adbc-driver-flightsql.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-adbc-driver-flightsql.yml' + - 'docs/packages/adbc-driver-flightsql.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-adbc-driver-flightsql.yml' + - 'docs/packages/adbc-driver-flightsql.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: adbc-driver-flightsql + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + name: Build adbc-driver-flightsql ${{ matrix.version }} py3-none-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + # The Go module graph (grpc-go, arrow-go's Flight SQL client, protobuf, ...) + # has to be fetched fresh every run on top of the driver/testserver builds. + timeout-minutes: 90 + + env: + ADBC_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout apache/arrow-adbc v${{ env.ADBC_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: apache/arrow-adbc + ref: go/adbc/v${{ env.ADBC_VERSION }} + persist-credentials: false + + - name: Get required Go version + run: | + (. .env && echo "GO_VERSION=${GO}") >> "$GITHUB_ENV" + + # The wheel is py3-none (no compiled CPython extension, just a ctypes-loaded + # .so), so cibuildwheel's per-interpreter model doesn't fit; drive the + # manylinux image directly instead (gotcha 15's pattern), with the build + # script written to a file rather than an inline `bash -c` one-liner. + - name: Write the build script + run: | + cat > build.sh <<'BUILD_SCRIPT' + set -euo pipefail + + curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-riscv64.tar.gz" -o /tmp/go.tar.gz + tar -C /usr/local -xzf /tmp/go.tar.gz + export PATH="/usr/local/go/bin:${PATH}" + export GOCACHE=/workspace/.gocache + export GOPATH=/workspace/.gopath + go version + + # add_go_lib()'s go build always passes -buildvcs=true; the bind-mounted + # checkout is owned by a different uid inside the container, so without + # this git refuses it as gotcha 117 describes for the same bind-mount shape. + git config --global --add safe.directory "*" + + cmake -S c -B build \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DCMAKE_INSTALL_PREFIX=/workspace/build/install \ + -DADBC_BUILD_SHARED=ON \ + -DADBC_BUILD_STATIC=OFF \ + -DADBC_DRIVER_FLIGHTSQL=ON + cmake --build build --target install -j"$(nproc)" + + (cd go/adbc && go build -o /workspace/testserver ./driver/flightsql/cmd/testserver) + # Set the executable bit while still root: the host step below runs as + # the unprivileged runner user, which can't chmod a file this container + # (running as root) wrote to the bind-mounted checkout. + chmod 755 /workspace/testserver + + PY=/opt/python/cp312-cp312/bin + "$PY"/pip install -q --upgrade pip wheel auditwheel + + cd python/adbc_driver_flightsql + ADBC_FLIGHTSQL_LIBRARY=/workspace/build/install/lib/libadbc_driver_flightsql.so \ + "$PY"/pip wheel . --no-deps -w dist + + # setup.py declares no ext_modules, so setuptools tags the wheel + # py3-none-any/purelib even though it embeds a real .so; fix that up + # the way ci/scripts/python_wheel_fix_tag.py does upstream (on every + # OS, not just macOS/Windows) before repairing. + plat=$("$PY"/python -c 'import sysconfig; print(sysconfig.get_platform().replace("-", "_").replace(".", "_"))') + cd dist + "$PY"/python -m wheel unpack ./*.whl -d unpacked + meta=$(find unpacked -name WHEEL) + sed -i \ + -e 's/^Root-Is-Purelib: true$/Root-Is-Purelib: false/' \ + -e "s/^Tag: py3-none-any\$/Tag: py3-none-${plat}/" \ + "$meta" + rm ./*.whl + "$PY"/python -m wheel pack unpacked/* --dest-dir . + rm -rf unpacked + + "$PY"/python -m auditwheel repair ./*.whl -w /workspace/wheelhouse --plat manylinux_2_39_riscv64 + BUILD_SCRIPT + + - name: Build the driver, testserver and package the wheel + run: | + docker run --rm \ + -v "$(pwd)":/workspace \ + --workdir /workspace \ + -e GO_VERSION="${{ env.GO_VERSION }}" \ + "${{ env.MANYLINUX_RISCV64_IMAGE }}" \ + bash build.sh + + - name: Install the wheel and run the test suite against a local Flight SQL server + run: | + set -euo pipefail + ./testserver -host 0.0.0.0 -port 41414 & + testserver_pid=$! + trap 'kill "$testserver_pid"' EXIT + for _ in $(seq 1 30); do + if curl -fsS --http2-prior-knowledge -o /dev/null -X POST \ + -H 'content-type: application/grpc' http://localhost:41414; then + break + fi + sleep 1 + done + + python3 -m venv .venv + . .venv/bin/activate + # The runner's stock pip predates riscv64 manylinux tag support and + # rejects the wheel as unsupported. + pip install -q --upgrade pip + # adbc-driver-manager/pandas/pyarrow riscv64 wheels only exist on our + # own registry. protobuf is upstream's own [test] extra (test_errors.py/ + # test_incremental.py import google.protobuf directly). + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ pip install -q \ + wheelhouse/*.whl adbc-driver-manager numpy pandas protobuf "pyarrow>=14.0.1" "pytest>=9" + + export ADBC_TEST_FLIGHTSQL_URI="grpc://localhost:41414" + python -c "import adbc_driver_flightsql; import adbc_driver_flightsql.dbapi" + # Mirrors upstream's own python_util.sh test_packages(): --import-mode + # append keeps the installed wheel authoritative over the checkout. + # The Dremio/GizmoSQL fixtures self-skip: they need ADBC_DREMIO_*/ + # ADBC_GIZMOSQL_* env vars for services this repo doesn't run. + python -m pytest -vv --import-mode append python/adbc_driver_flightsql/tests + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: adbc-driver-flightsql-${{ env.ADBC_VERSION }}-py3-none-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish adbc-driver-flightsql ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: adbc-driver-flightsql-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/adbc-driver-flightsql.yaml b/docs/packages/adbc-driver-flightsql.yaml new file mode 100644 index 00000000000..03b481e406d --- /dev/null +++ b/docs/packages/adbc-driver-flightsql.yaml @@ -0,0 +1,5 @@ +package-name: adbc-driver-flightsql +source-code: https://github.com/apache/arrow-adbc +license: Apache-2.0 +versions: +- version: 1.12.0