From 7da8f1c7f1b89dc10b73dbc4f667089230a10255 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 20 Aug 2026 17:47:06 +0200 Subject: [PATCH] workflows: add build-fastuuid.yml for riscv64 manywheel builds Add build-fastuuid.yml to build fastuuid 0.14.0 wheels for riscv64 and publish them to pypi.riseproject.dev. fastuuid is a PyO3/Rust extension built with maturin, with no C native dependencies (pure-Rust: pyo3, uuid, rand). We build our own sdist from an upstream checkout on ubuntu-latest, then build the riscv64 bdist from that sdist with cibuildwheel on the manylinux_2_39_riscv64 image. fastuuid gitignores Cargo.lock, so a fresh dependency resolve floats the `uuid` crate to the newest 1.x. uuid >=1.21 deprecated the `uuid::Context` alias (renamed to `ContextV1`), and the crate compiles under `#![deny(warnings)]`, so that deprecation is a hard compile error. We pin uuid to 1.18.1 (the version upstream released 0.14.0 against) before maturin captures Cargo.lock into the sdist, which restores a clean build. The sdist also carries the `.cargo/config.toml` that sets `--cfg uuid_unstable` (required by the uuid crate's v1/v7 features). The Rust toolchain is installed in-container with rustup (CIBW_BEFORE_ALL_LINUX) and put on PATH (CIBW_ENVIRONMENT_LINUX), since fastuuid ships no [tool.cibuildwheel] config of its own. Each wheel is tested the way upstream does, running its pytest suite (tests/test_uuid.py + test_benchmarks.py) inside the container against the matching interpreter. All test deps (pytest, hypothesis, pytest-benchmark, uuid7) are pure-Python wheels on public PyPI. Matrix cp312/cp313/cp314/cp314t: fastuuid is not abi3 (upstream ships per-interpreter wheels), so every Python version needs its own build. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/build-fastuuid.yml | 177 +++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 .github/workflows/build-fastuuid.yml diff --git a/.github/workflows/build-fastuuid.yml b/.github/workflows/build-fastuuid.yml new file mode 100644 index 0000000..26438aa --- /dev/null +++ b/.github/workflows/build-fastuuid.yml @@ -0,0 +1,177 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on: https://github.com/fastuuid/fastuuid/blob/0.14.0/.github/workflows/ci-cd.yml +name: Build fastuuid wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'fastuuid version to build (git tag without leading v, e.g. 0.14.0)' + required: true + default: '0.14.0' + pull_request: + paths: + - '.github/workflows/build-fastuuid.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '0.14.0' }}-${{ 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 0.14.0 there. + FASTUUID_VERSION: ${{ inputs.version || '0.14.0' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + # fastuuid gitignores Cargo.lock, so a fresh resolve floats the `uuid` crate to + # the newest 1.x. uuid >=1.21 deprecated the `uuid::Context` alias (renamed to + # `ContextV1`), and the crate builds under `#![deny(warnings)]`, so that + # deprecation becomes a hard compile error. Pin uuid to the version upstream + # released 0.14.0 against (what their release sdist's Cargo.lock ships), which + # reproduces a clean build. Bump this in lockstep with FASTUUID_VERSION. + UUID_CRATE_VERSION: '1.18.1' + +jobs: + # Build the sdist ourselves from an upstream checkout (never consume the + # prebuilt PyPI sdist). maturin bundles the pinned Cargo.lock + the `.cargo/ + # config.toml` (which sets `--cfg uuid_unstable`, required by the uuid crate's + # v1/v7 features) + the tests/ suite into the sdist, so the riscv64 bdist + # builds reproducibly from it. The sdist is arch-independent, so build it once + # on ubuntu-latest (see gotcha 4). + python_sdist: + runs-on: ubuntu-latest + outputs: + sdist_artifact_name: ${{ steps.build_sdist.outputs.sdist_artifact_name }} + package_version: ${{ steps.build_sdist.outputs.package_version }} + steps: + - name: Checkout fastuuid ${{ env.FASTUUID_VERSION }} + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: fastuuid/fastuuid + ref: ${{ env.FASTUUID_VERSION }} + persist-credentials: false + + - name: Install Python + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + python-version: '3.12' + activate-environment: true + enable-cache: false + + - name: Pin uuid crate and build sdist + id: build_sdist + run: | + set -euo pipefail + rm -rf dist + + # Lock uuid to the release version before maturin captures Cargo.lock + # into the sdist (see UUID_CRATE_VERSION rationale above). + cargo generate-lockfile + cargo update -p uuid --precise "${UUID_CRATE_VERSION}" + + uv pip install 'maturin>=1.0,<2.0' build + python -m build --sdist --outdir dist + + sdist_name="$(ls dist)" + { + echo "sdist_artifact_name=${sdist_name}" + echo "package_version=$(echo "${sdist_name}" | sed -En 's/fastuuid-(.+)\.tar\.gz/\1/p')" + } >> "$GITHUB_OUTPUT" + + - name: Upload sdist artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: ${{ steps.build_sdist.outputs.sdist_artifact_name }} + path: dist/${{ steps.build_sdist.outputs.sdist_artifact_name }} + if-no-files-found: error + + build_wheels: + needs: [python_sdist] + name: Build fastuuid ${{ inputs.version || '0.14.0' }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + # fastuuid is a PyO3 extension built per-interpreter (not abi3 - upstream + # ships cp3x-cp3x wheels), so every Python version needs its own build. + # Repo-standard riscv64 target set. Upstream doesn't build for 3.14t yet, + # so skip it for now. + python: ["cp312", "cp313", "cp314"] + + steps: + - name: Fetch sdist artifact + id: fetch_sdist + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ needs.python_sdist.outputs.sdist_artifact_name }} + + - name: Install uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + python-version: '3.12' + activate-environment: true + enable-cache: false + + - name: Build and test wheel + env: + CIBW_ARCHS: riscv64 + # Only manylinux: rustup.rs ships no riscv64 musl host toolchain, so + # musllinux can't build (same reason build-tiktoken.yml skips it). + CIBW_BUILD: ${{ matrix.python }}-manylinux_riscv64 + CIBW_BUILD_VERBOSITY: '1' + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # fastuuid ships no [tool.cibuildwheel], so the Rust toolchain its + # maturin backend needs is installed in-container here and put on PATH + # for the build (build-tiktoken.yml carries the equivalent in its own + # pyproject before-all/environment). + 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"' + # Test each wheel the way upstream does - run its pytest suite (tox's + # black/isort steps are dev-only lint, not wheel tests, so skipped). + # All test deps are pure-Python wheels on public PyPI, so no registry + # plumbing is needed; uuid7 provides the `uuid_extensions` module the + # benchmarks import. HYPOTHESIS_PROFILE=dev caps property-test examples + # (the "ci" default is 2000) and --benchmark-disable runs each benchmark + # once for coverage (incl. the GIL-releasing bulk/threaded paths) + # without spending CI time on perf timing. Tests live inside the sdist + # dir we pass to cibuildwheel, so reference them via {package} (= + # /project/fastuuid), NOT {project} (= the invocation dir /project) - + # see gotcha 5. + CIBW_TEST_REQUIRES: pytest hypothesis pytest-benchmark uuid7 + CIBW_TEST_COMMAND: HYPOTHESIS_PROFILE=dev pytest -q {package}/tests --benchmark-disable + run: | + set -euo pipefail + mkdir fastuuid + tar zxf "${{ steps.fetch_sdist.outputs.download-path }}/${{ needs.python_sdist.outputs.sdist_artifact_name }}" \ + --strip-components=1 -C fastuuid + uv pip install --upgrade cibuildwheel + python -m cibuildwheel --output-dir wheelhouse ./fastuuid + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: fastuuid-${{ env.FASTUUID_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: ./wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish fastuuid ${{ inputs.version || '0.14.0' }} to GitLab + needs: [build_wheels] + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Publish wheels and open docs PR + uses: riseproject-dev/python-wheels/actions/publish-wheels@main + with: + artifact-pattern: fastuuid-${{ env.FASTUUID_VERSION }}-*-manylinux_riscv64 + gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }} + gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }} + gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }} + gh-token: ${{ secrets.GITHUB_TOKEN }}