From e888b6a4394281a32cf784531385989a032d99a4 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Mon, 21 Sep 2026 14:51:10 +0000 Subject: [PATCH] pyvrl: add build-pyvrl.yml for riscv64 wheels * **Package**: `pyvrl` * **Version**: `0.0.2` * **Source**: https://github.com/crowdalert/pyvrl * **Docs**: https://github.com/crowdalert/pyvrl Compiles a pyo3/maturin extension wrapping Vector's `vrl` crate - the Vector Remap Language compiler and stdlib - into a per-interpreter wheel. Upstream publishes no riscv64 wheel. Mirrors [upstream's `ci.yaml`](https://github.com/crowdalert/pyvrl/blob/v0.0.2/.github/workflows/ci.yaml) `linux` job. **Differs from upstream** - musllinux dropped - rustup.rs ships no riscv64 musl toolchain. **Matrix**: `cp312` only - pyo3 0.20 supports nothing newer, and its `PYO3_USE_ABI3_FORWARD_COMPATIBILITY` escape hatch turns on `Py_LIMITED_API`, which cfg-removes the chrono conversions pyvrl needs for VRL timestamp values. Upstream's own wheels stop at cp312 for the same reason. **Testing** - Upstream's CI has no test step; exercises the documented `Transform`/`remap` API instead - the README example plus JSON, timestamp, unicode and error paths. **License**: OK --- .github/workflows/build-pyvrl.yml | 151 ++++++++++++++++++++++++++++++ docs/packages/pyvrl.yaml | 5 + 2 files changed, 156 insertions(+) create mode 100644 .github/workflows/build-pyvrl.yml create mode 100644 docs/packages/pyvrl.yaml diff --git a/.github/workflows/build-pyvrl.yml b/.github/workflows/build-pyvrl.yml new file mode 100644 index 0000000000..5cbcb40472 --- /dev/null +++ b/.github/workflows/build-pyvrl.yml @@ -0,0 +1,151 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on: https://github.com/crowdalert/pyvrl/blob/v0.0.2/.github/workflows/ci.yaml +name: Build pyvrl wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/pyvrl.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-pyvrl.yml' + - 'docs/packages/pyvrl.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-pyvrl.yml' + - 'docs/packages/pyvrl.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: pyvrl + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build pyvrl ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 1440 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # cp312 is pyo3 0.20's ceiling, which is also where upstream's own + # wheels stop. PYO3_USE_ABI3_FORWARD_COMPATIBILITY would lift it, but + # it turns on Py_LIMITED_API, and pyo3 0.20 cfg-removes the chrono + # conversions this crate needs under it. + python: ["cp312"] + + env: + PYVRL_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout pyvrl ${{ env.PYVRL_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: crowdalert/pyvrl + ref: v${{ env.PYVRL_VERSION }} + persist-credentials: false + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + # musllinux is dropped: rustup.rs ships no riscv64 musl toolchain. + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # pyvrl ships no [tool.cibuildwheel], so the Rust toolchain its + # maturin backend needs is installed in-container here. + CIBW_BEFORE_ALL_LINUX: >- + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + CIBW_ENVIRONMENT_LINUX: >- + PATH="$PATH:$HOME/.cargo/bin" + CIBW_TEST_COMMAND: | + python3 - <<'PYEOF' + import datetime + from pyvrl import Transform + program = ''' + .y = "bar" + .x = upcase!(.x) + .n = to_int!(.n) + 1 + .list = push!(.list, "z") + . + ''' + transform = Transform(program) + assert transform.source == program + out = transform.remap({"x": "foo", "n": 41, "list": ["a"]}) + assert out == {"x": "FOO", "y": "bar", "n": 42, "list": ["a", "z"]}, out + unicode = Transform('.s = upcase!(.s)\n.') + assert unicode.remap({"s": "caf\N{LATIN SMALL LETTER E WITH ACUTE} \N{EARTH GLOBE AMERICAS}"}) == {"s": "CAF\N{LATIN CAPITAL LETTER E WITH ACUTE} \N{EARTH GLOBE AMERICAS}"} + parsed = Transform('. = parse_json!(.raw)').remap({"raw": '{"a": [1, 2.5, true, null]}'}) + assert parsed == {"a": [1, 2.5, True, None]}, parsed + stamp = Transform('. = {"t": parse_timestamp!("2024-05-06T07:08:09Z", "%+")}').remap({}) + assert stamp == {"t": datetime.datetime(2024, 5, 6, 7, 8, 9, tzinfo=datetime.timezone.utc)}, stamp + try: + Transform(".x = no_such_function!(.x)") + except ValueError: + pass + else: + raise AssertionError("expected a compile error") + try: + Transform("abort").remap({}) + except ValueError: + pass + else: + raise AssertionError("expected a runtime error") + print("pyvrl OK") + PYEOF + + - name: Check the extension made it into the wheel + run: | + python3 - wheelhouse/*.whl <<'EOF' + import sys, zipfile + for whl in sys.argv[1:]: + names = zipfile.ZipFile(whl).namelist() + assert any(n.startswith("pyvrl/pyvrl.") and n.endswith(".so") for n in names), names + assert any("licen" in n and n.endswith("LICENSE") for n in names), names + print(whl, "ok") + EOF + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: pyvrl-${{ env.PYVRL_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish pyvrl ${{ 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: pyvrl-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/pyvrl.yaml b/docs/packages/pyvrl.yaml new file mode 100644 index 0000000000..50f87de5d0 --- /dev/null +++ b/docs/packages/pyvrl.yaml @@ -0,0 +1,5 @@ +package-name: pyVRL +source-code: https://github.com/crowdalert/pyvrl +license: MIT +versions: +- version: 0.0.2