From 6409db02b0bb6e2dfb88543b64d490090cdf7219 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 01:11:33 +0200 Subject: [PATCH 1/4] rigour: add build-rigour.yml for riscv64 wheels --- .github/workflows/build-rigour.yml | 103 +++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .github/workflows/build-rigour.yml diff --git a/.github/workflows/build-rigour.yml b/.github/workflows/build-rigour.yml new file mode 100644 index 000000000..d09fcec3d --- /dev/null +++ b/.github/workflows/build-rigour.yml @@ -0,0 +1,103 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on the `linux`/`sdist` jobs of +# https://github.com/opensanctions/rigour/blob/v2.4.1/.github/workflows/build.yml +name: Build rigour wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'rigour version to build (git tag without leading v, e.g. 2.4.1)' + required: true + default: '2.4.1' + pull_request: + paths: + - '.github/workflows/build-rigour.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '2.4.1' }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + # `inputs.version` is empty on pull_request events; default to 2.4.1 there. + RIGOUR_VERSION: ${{ inputs.version || '2.4.1' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + + build_wheels: + needs: [setup] + name: Build rigour ${{ inputs.version || '2.4.1' }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 90 + strategy: + fail-fast: false + matrix: + # rigour's pyo3 dependency has a plain `pyo3/extension-module` feature + # (no abi3-pyNN in [tool.maturin] features), so every interpreter needs + # its own build. Upstream builds cp310-cp314 only (no cp314t), so the + # matrix mirrors that. + python: ["cp310", "cp311", "cp312", "cp313", "cp314"] + + steps: + - name: Checkout rigour v${{ env.RIGOUR_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: opensanctions/rigour + ref: v${{ env.RIGOUR_VERSION }} + persist-credentials: false + + - name: Build and test wheel + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + env: + CIBW_ARCHS: riscv64 + # musllinux can't build: rustup.rs ships no riscv64 musl toolchain. + CIBW_BUILD: ${{ matrix.python }}-manylinux_riscv64 + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # rigour ships no [tool.cibuildwheel], so the Rust toolchain its + # maturin backend needs is installed in-container here. libicu-devel + # is also needed at test-install time: rigour's runtime dependency + # normality hard-requires pyicu, which has no riscv64 wheel on + # public PyPI or our registry, so pip builds it from sdist; Rocky + # 10's libicu-devel lives in appstream (not EPEL, which is empty on + # riscv64 per gotcha 51), so it installs without enabling any extra + # repo. + CIBW_BEFORE_ALL_LINUX: >- + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && + dnf install -y libicu-devel + CIBW_ENVIRONMENT_LINUX: >- + PATH="$PATH:$HOME/.cargo/bin" + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + CIBW_TEST_REQUIRES: pytest + # Build-from-checkout: rigour/ sits at the repo root next to tests/, + # and tests/__init__.py makes it a package, so pytest's default + # rootdir-prepend import mode would shadow the installed wheel with + # the checkout's own source (testing-and-shadowing gotcha 25). + # test-sources copies just tests/ into an empty cwd to avoid that. + CIBW_TEST_SOURCES: tests + CIBW_TEST_COMMAND: >- + python -c "import rigour._core as m; assert m.__file__.endswith('.so'), m.__file__" && + python -m pytest -v tests + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: rigour-${{ env.RIGOUR_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: ./wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish rigour ${{ inputs.version || '2.4.1' }} + needs: [setup, build_wheels] + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + with: + artifact-pattern: rigour-${{ inputs.version || '2.4.1' }}-*-manylinux_riscv64 From e201fd69e8f6330c715b8b7de2d5b41fffec4006 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 01:54:50 +0200 Subject: [PATCH 2/4] rigour: install typing_extensions for tests (upstream dep gap) --- .github/workflows/build-rigour.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-rigour.yml b/.github/workflows/build-rigour.yml index d09fcec3d..b24a11fbb 100644 --- a/.github/workflows/build-rigour.yml +++ b/.github/workflows/build-rigour.yml @@ -75,7 +75,11 @@ jobs: CIBW_ENVIRONMENT_LINUX: >- PATH="$PATH:$HOME/.cargo/bin" PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ - CIBW_TEST_REQUIRES: pytest + # typing_extensions isn't in pyproject.toml's [project] dependencies, + # but rigour/ids/__init__.py imports it unconditionally; upstream's + # own lint-test job never notices because mypy (a [dev] extra) pulls + # it in transitively. + CIBW_TEST_REQUIRES: pytest typing_extensions # Build-from-checkout: rigour/ sits at the repo root next to tests/, # and tests/__init__.py makes it a package, so pytest's default # rootdir-prepend import mode would shadow the installed wheel with From cf48c6bd47cc4c78afc99cfca73818d22fb180fb Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 02:45:32 +0200 Subject: [PATCH 3/4] rigour: deselect cp310-incompatible datetime tests --- .github/workflows/build-rigour.yml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-rigour.yml b/.github/workflows/build-rigour.yml index b24a11fbb..c227abcb3 100644 --- a/.github/workflows/build-rigour.yml +++ b/.github/workflows/build-rigour.yml @@ -44,7 +44,24 @@ jobs: # (no abi3-pyNN in [tool.maturin] features), so every interpreter needs # its own build. Upstream builds cp310-cp314 only (no cp314t), so the # matrix mirrors that. - python: ["cp310", "cp311", "cp312", "cp313", "cp314"] + include: + - python: cp310 + # rigour/dates.py calls datetime.fromisoformat() directly on + # values with a "Z" suffix or a colonless UTC offset; that only + # parses starting with the relaxed ISO 8601 support Python 3.11 + # added (bpo-41412) - Python 3.10's fromisoformat rejects both, + # so these two tests fail identically on any OS, not just + # riscv64. Upstream's own lint-test job never notices because it + # runs pytest on 3.14 only. Everything else in the suite passes. + pytest_k: "not test_utc_suffixes and not test_non_utc_offsets_are_converted" + - python: cp311 + pytest_k: "" + - python: cp312 + pytest_k: "" + - python: cp313 + pytest_k: "" + - python: cp314 + pytest_k: "" steps: - name: Checkout rigour v${{ env.RIGOUR_VERSION }} @@ -88,7 +105,7 @@ jobs: CIBW_TEST_SOURCES: tests CIBW_TEST_COMMAND: >- python -c "import rigour._core as m; assert m.__file__.endswith('.so'), m.__file__" && - python -m pytest -v tests + python -m pytest -v tests -k "${{ matrix.pytest_k }}" - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: From 60706e503486216baae08ca9240105fc569f0fb5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 8 Sep 2026 04:32:27 +0200 Subject: [PATCH 4/4] rigour: bump build timeout to 120 minutes --- .github/workflows/build-rigour.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-rigour.yml b/.github/workflows/build-rigour.yml index c227abcb3..1884a7e88 100644 --- a/.github/workflows/build-rigour.yml +++ b/.github/workflows/build-rigour.yml @@ -36,7 +36,12 @@ jobs: needs: [setup] name: Build rigour ${{ inputs.version || '2.4.1' }} ${{ matrix.python }}-manylinux_riscv64 runs-on: ubuntu-24.04-riscv - timeout-minutes: 90 + # Siblings on the same dependency graph finish in ~35-40 minutes; cp312 + # was cancelled at 90 minutes stuck mid-compile on a small crate + # (thiserror) while every other interpreter passed well under that + # budget, so it reads as runner contention, not a genuinely slower + # build. Bumped for headroom. + timeout-minutes: 120 strategy: fail-fast: false matrix: