runai-model-streamer: Add version 0.16.1 #7
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-FileCopyrightText: 2026 The RISE Project | |
| # SPDX-License-Identifier: MIT | |
| # | |
| # This workflow is based on: https://github.com/run-ai/runai-model-streamer/blob/master/Makefile | |
| --- | |
| name: Build runai-model-streamer wheels (riscv64) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version glob to (re)build; empty builds every version of docs/packages/runai-model-streamer.yaml not released yet' | |
| required: false | |
| default: '' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-runai-model-streamer.yml' | |
| - 'docs/packages/runai-model-streamer.yaml' | |
| - 'patches/runai-model-streamer/**' | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/build-runai-model-streamer.yml' | |
| - 'docs/packages/runai-model-streamer.yaml' | |
| - 'patches/runai-model-streamer/**' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 | |
| # Upstream's own .bazelversion; bazelisk publishes no riscv64 binary, so it is | |
| # bootstrapped from the dist archive instead. | |
| BAZEL_VERSION: '7.6.1' | |
| # Versions bazel 7.6.1's own MODULE.bazel pins; both need a riscv64 fix below. | |
| RULES_PYTHON_VERSION: '0.33.2' | |
| RULES_JAVA_VERSION: '7.6.5' | |
| jobs: | |
| setup: | |
| uses: $/.github/workflows/_setup.yml | |
| with: | |
| package: runai-model-streamer | |
| version: ${{ inputs.version }} | |
| bazel: | |
| needs: [setup] | |
| if: needs.setup.outputs.versions != '[]' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| version: ${{ fromJSON(needs.setup.outputs.versions) }} | |
| name: Bootstrap bazel (riscv64) | |
| runs-on: ubuntu-24.04-riscv | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Restore bazel binary | |
| id: cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: bazel-bin | |
| key: bazel-${{ env.BAZEL_VERSION }}-manylinux_riscv64 | |
| - name: Bootstrap bazel ${{ env.BAZEL_VERSION }} | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| mkdir -p bazel-bin | |
| docker run --rm -i --network=host \ | |
| -v "${GITHUB_WORKSPACE}:/work" \ | |
| -w /work \ | |
| -e BAZEL_VERSION="${BAZEL_VERSION}" \ | |
| -e RULES_PYTHON_VERSION="${RULES_PYTHON_VERSION}" \ | |
| -e RULES_JAVA_VERSION="${RULES_JAVA_VERSION}" \ | |
| "${MANYLINUX_RISCV64_IMAGE}" \ | |
| bash <<'SCRIPT' | |
| set -eux | |
| dnf install -y --setopt=install_weak_deps=False java-21-openjdk-devel zip unzip | |
| JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")" | |
| export JAVA_HOME | |
| # rules_python 0.33.2's PLATFORMS has no riscv64 entry, aborting the bootstrap | |
| # (bazelbuild/bazel#23018). Any linux entry is a safe stand-in: the toolchain it names | |
| # is never selected on a riscv64 host. Fixed in bazel 8.2.0; the 7.x backport is open. | |
| mkdir -p /tmp/rules_python | |
| curl -fsSLo /tmp/rules_python.tar.gz "https://github.com/bazel-contrib/rules_python/releases/download/${RULES_PYTHON_VERSION}/rules_python-${RULES_PYTHON_VERSION}.tar.gz" | |
| tar -xzf /tmp/rules_python.tar.gz -C /tmp/rules_python --strip-components=1 | |
| sed -i 's|fail("No platform declared for host OS {} on arch {}".format(os_name, arch))|return "x86_64-unknown-linux-gnu"|' \ | |
| /tmp/rules_python/python/private/toolchains_repo.bzl | |
| # rules_java 7.x maps riscv64 to a stray-colon include path, so libcpu_profiler.so | |
| # can't find jni_md.h. Fixed in rules_java 8.x, never backported. | |
| mkdir -p /tmp/rules_java | |
| curl -fsSLo /tmp/rules_java.tar.gz "https://github.com/bazelbuild/rules_java/releases/download/${RULES_JAVA_VERSION}/rules_java-${RULES_JAVA_VERSION}.tar.gz" | |
| tar -xzf /tmp/rules_java.tar.gz -C /tmp/rules_java | |
| sed -i 's|\[":include/linux"\]|["include/linux"]|g' /tmp/rules_java/toolchains/BUILD | |
| mkdir -p /tmp/bazel-src | |
| cd /tmp/bazel-src | |
| curl -fsSLo dist.zip "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-dist.zip" | |
| unzip -q dist.zip | |
| EXTRA_BAZEL_ARGS="--tool_java_runtime_version=local_jdk \ | |
| --override_module=rules_python=/tmp/rules_python \ | |
| --override_module=rules_java=/tmp/rules_java" \ | |
| bash ./compile.sh | |
| install -m 0755 output/bazel /work/bazel-bin/bazel | |
| SCRIPT | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: bazel-${{ env.BAZEL_VERSION }}-riscv64 | |
| path: bazel-bin/bazel | |
| if-no-files-found: error | |
| build_wheel: | |
| name: Build runai-model-streamer ${{ matrix.version }} py3-none-manylinux_riscv64 | |
| needs: [setup, bazel] | |
| if: needs.setup.outputs.versions != '[]' | |
| runs-on: ubuntu-24.04-riscv | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| version: ${{ fromJSON(needs.setup.outputs.versions) }} | |
| env: | |
| RUNAI_MODEL_STREAMER_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Checkout runai-model-streamer ${{ env.RUNAI_MODEL_STREAMER_VERSION }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: run-ai/runai-model-streamer | |
| ref: ${{ env.RUNAI_MODEL_STREAMER_VERSION }} | |
| path: runai-model-streamer | |
| persist-credentials: false | |
| - name: Checkout python-wheels | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: python-wheels | |
| persist-credentials: false | |
| - name: Patch runai-model-streamer source | |
| working-directory: runai-model-streamer | |
| run: git apply -v ../python-wheels/patches/runai-model-streamer/${{ env.RUNAI_MODEL_STREAMER_VERSION }}/*.patch | |
| - name: Download bazel | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: bazel-${{ env.BAZEL_VERSION }}-riscv64 | |
| path: bazel-bin | |
| - name: Build the C++ streamer library and package the wheel | |
| run: | | |
| mkdir -p dist | |
| docker run --rm -i --network=host \ | |
| -v "${GITHUB_WORKSPACE}:/work" \ | |
| -w /work/runai-model-streamer \ | |
| -e PACKAGE_VERSION="${RUNAI_MODEL_STREAMER_VERSION}" \ | |
| "${MANYLINUX_RISCV64_IMAGE}" \ | |
| bash <<'SCRIPT' | |
| set -eux | |
| # cpp/toolchain/template/toolchain.bzl links -static-libstdc++ -l:libstdc++.a | |
| # for every arch; this image's gcc devel package (libstdc++-devel) ships only | |
| # the shared libstdc++.so, so the static archive needs its own CRB package. | |
| dnf install -y --setopt=install_weak_deps=False java-21-openjdk-devel libstdc++-static | |
| JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")" | |
| export JAVA_HOME | |
| install -m 0755 /work/bazel-bin/bazel /usr/local/bin/bazel | |
| git config --global --add safe.directory '*' | |
| # cpp/toolchain/rules.bzl resolves every tool as /usr/bin/<arch>-linux-gnu-<tool>, | |
| # the Debian cross-toolchain naming upstream's own devcontainer ships (real | |
| # x86_64-linux-gnu-gcc/aarch64-linux-gnu-gcc binaries there). This image is a | |
| # native (not cross-compiling) riscv64 build of manylinux, so its compiler is | |
| # the unprefixed system gcc/g++ - symlink the triplet-prefixed names the | |
| # toolchain rule expects onto it. | |
| for tool in gcc g++ ar ld cpp gcov nm objdump strip; do | |
| native="$(command -v "$tool" || true)" | |
| [ -n "$native" ] && ln -sf "$native" "/usr/bin/riscv64-linux-gnu-$tool" | |
| done | |
| cd cpp | |
| bazel build streamer:libstreamer.so --config=riscv64 | |
| cd ../py/runai_model_streamer | |
| # cp312's venv has no setuptools preinstalled (newer CPython/pip dropped the | |
| # implicit bootstrap); setup.py's own `from setuptools import setup` needs it. | |
| /opt/python/cp312-cp312/bin/pip install -q setuptools wheel | |
| /opt/python/cp312-cp312/bin/python setup.py bdist_wheel --plat-name manylinux_2_39_riscv64 | |
| cp dist/*.whl /work/dist/ | |
| SCRIPT | |
| - name: Verify the wheel ships a riscv64 shared object | |
| run: | | |
| python3 - dist/*.whl <<'EOF' | |
| import sys, zipfile | |
| with zipfile.ZipFile(sys.argv[1]) as zf: | |
| names = zf.namelist() | |
| so = next(n for n in names if n.endswith("libstreamer/lib/libstreamer.so")) | |
| header = zf.read(so)[:20] | |
| assert header[:4] == b"\x7fELF", header | |
| assert header[18] == 0xF3, header # EM_RISCV | |
| EOF | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: runai-model-streamer-${{ matrix.version }}-py3-none-manylinux_riscv64 | |
| path: dist/*.whl | |
| if-no-files-found: error | |
| test_wheel: | |
| name: Test runai-model-streamer ${{ matrix.version }} on Python ${{ matrix.python-version }} | |
| needs: [setup, build_wheel] | |
| if: needs.setup.outputs.versions != '[]' | |
| runs-on: ubuntu-24.04-riscv | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| version: ${{ fromJSON(needs.setup.outputs.versions) }} | |
| python-version: ['3.12', '3.13', '3.14'] | |
| env: | |
| RUNAI_MODEL_STREAMER_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Checkout runai-model-streamer ${{ env.RUNAI_MODEL_STREAMER_VERSION }} | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: run-ai/runai-model-streamer | |
| ref: ${{ env.RUNAI_MODEL_STREAMER_VERSION }} | |
| path: runai-model-streamer | |
| persist-credentials: false | |
| - name: Download wheel | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: runai-model-streamer-${{ env.RUNAI_MODEL_STREAMER_VERSION }}-py3-none-manylinux_riscv64 | |
| path: wheelhouse | |
| - name: Install Python | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| activate-environment: true | |
| enable-cache: false | |
| - name: Install the wheel and upstream's test dependencies | |
| env: | |
| UV_EXTRA_INDEX_URL: https://pypi.riseproject.dev/simple/ | |
| UV_INDEX_STRATEGY: unsafe-best-match | |
| # requirements.dev pins numpy==1.24.4, which ships no riscv64 wheel and | |
| # fails to build from source under Python >=3.12 (its legacy setup.py | |
| # needs the stdlib `distutils` module, removed in 3.12). Override it to | |
| # the newer numpy our registry does have a riscv64 wheel for; nothing | |
| # in this test suite depends on numpy 1.24.4 specifically. | |
| run: | | |
| echo "numpy>=1.26,<3" > /tmp/numpy-override.txt | |
| uv pip install --override /tmp/numpy-override.txt -r runai-model-streamer/py/runai_model_streamer/requirements.dev wheelhouse/*.whl | |
| # setup.py's package_data ships libstreamer.so alone; upstream's own dev | |
| # fixtures for the mocked object-storage tests are never part of the | |
| # wheel, so they are copied in from the checkout before running them. | |
| - name: Stage upstream's test fixtures into the installed package | |
| run: | | |
| site="$(python -c 'import runai_model_streamer, os; print(os.path.dirname(runai_model_streamer.__file__))')" | |
| cp -r runai-model-streamer/py/runai_model_streamer/runai_model_streamer/safetensors_streamer/tests/test_files \ | |
| "$site/safetensors_streamer/tests/" | |
| # Run from the installed package's own parent directory so this exercises the | |
| # wheel's copy, not the checkout's, matching upstream's `make -C py test-unit-real` | |
| # (minus test-dist, which needs a multi-node torchrun harness). | |
| - name: Run upstream's tests against the installed wheel | |
| run: | | |
| site="$(python -c 'import runai_model_streamer, os; print(os.path.dirname(os.path.dirname(runai_model_streamer.__file__)))')" | |
| cd "$site" | |
| python -m unittest discover -b runai_model_streamer | |
| gpl_sources: | |
| needs: [setup] | |
| if: needs.setup.outputs.versions != '[]' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| version: ${{ fromJSON(needs.setup.outputs.versions) }} | |
| name: Collect GPL sources for runai-model-streamer ${{ matrix.version }} | |
| runs-on: ubuntu-24.04-riscv | |
| env: | |
| RUNAI_MODEL_STREAMER_VERSION: ${{ matrix.version }} | |
| steps: | |
| - name: Checkout python-wheels | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: ./actions/collect-gpl-sources | |
| with: | |
| image: ${{ env.MANYLINUX_RISCV64_IMAGE }} | |
| packages: gcc | |
| output: gpl-sources.tar | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: runai-model-streamer-${{ env.RUNAI_MODEL_STREAMER_VERSION }}-gpl-sources | |
| path: gpl-sources.tar | |
| if-no-files-found: error | |
| publish: | |
| name: Publish runai-model-streamer ${{ matrix.version }} | |
| needs: [setup, build_wheel, test_wheel, gpl_sources] | |
| 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: runai-model-streamer-${{ matrix.version }}-py3-none-manylinux_riscv64 | |
| gpl-sources-artifact: runai-model-streamer-${{ matrix.version }}-gpl-sources | |
| gpl-sources-description: gcc |