Skip to content

docs: Update projects #24

docs: Update projects

docs: Update projects #24

Workflow file for this run

# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on the `linux` job of
# https://github.com/curioswitch/pyqwest/blob/v0.10.0/.github/workflows/release.yaml
name: Build pyqwest wheels (riscv64)
on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/pyqwest.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-pyqwest.yml'
- 'docs/packages/pyqwest.yaml'
push:
branches: [main]
paths:
- '.github/workflows/build-pyqwest.yml'
- 'docs/packages/pyqwest.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: pyqwest
version: ${{ inputs.version }}
build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
name: Build pyqwest ${{ matrix.version }} ${{ matrix.tag }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
tag: [cp310-abi3, cp314t]
include:
# pyo3/abi3-py310 is an opt-in feature upstream's own release job adds
# only on top of a `pyo3/extension-module`-only build (its second
# "Build abi3 wheels" step, `-i 3.10 --features pyo3/abi3-py310`);
# nothing in Cargo.toml turns it on by default. Built on cp310 --
# the oldest interpreter the abi3 tag claims -- and re-tested on the
# newer ones via find_compatible_wheel. pyo3 disables abi3 under
# Py_GIL_DISABLED, so the free-threaded build is its own wheel.
- tag: cp310-abi3
build: >-
cp310-manylinux_riscv64 cp311-manylinux_riscv64
cp312-manylinux_riscv64 cp313-manylinux_riscv64
cp314-manylinux_riscv64
features: --features pyo3/extension-module --features pyo3/abi3-py310
- tag: cp314t
build: cp314t-manylinux_riscv64
features: --features pyo3/extension-module
env:
PYQWEST_VERSION: ${{ matrix.version }}
steps:
- name: Checkout pyqwest v${{ env.PYQWEST_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: curioswitch/pyqwest
ref: v${{ env.PYQWEST_VERSION }}
persist-credentials: false
- name: Replace tests/conftest.py to drop the pyvoy-based local server
# The real conftest.py imports pyvoy unconditionally to run a local
# Envoy-based test server; pyvoy bundles Envoy and ships no riscv64
# wheel anywhere. This keeps only the anyio backend fixtures, the
# asyncio_only deselection hook and the client_type fixture (copied
# verbatim) needed by the self-contained subset of tests below --
# none of them need the live server.
run: |
cat > tests/conftest.py <<'EOF'
from __future__ import annotations
import pytest
import sniffio
@pytest.fixture(scope="session", params=["asyncio", "trio"])
def anyio_backend(request: pytest.FixtureRequest) -> str:
return request.param
@pytest.fixture(autouse=True)
def no_stale_runner(request: pytest.FixtureRequest) -> None:
callspec = getattr(request.node, "callspec", None)
expected = callspec.params.get("anyio_backend") if callspec is not None else None
if expected is None:
return
try:
running = sniffio.current_async_library()
except sniffio.AsyncLibraryNotFoundError:
return
if running != expected:
pytest.fail(f"a {running} runner is still alive for this {expected} test")
def pytest_collection_modifyitems(
config: pytest.Config, items: list[pytest.Item]
) -> None:
kept: list[pytest.Item] = []
dropped: list[pytest.Item] = []
for item in items:
callspec = getattr(item, "callspec", None)
backend = callspec.params.get("anyio_backend") if callspec is not None else None
if backend not in (None, "asyncio") and item.get_closest_marker("asyncio_only"):
dropped.append(item)
else:
kept.append(item)
if dropped:
config.hook.pytest_deselected(items=dropped)
items[:] = kept
@pytest.fixture(
params=[
"async",
"sync",
pytest.param("async_asgi", marks=pytest.mark.asyncio_only),
pytest.param("sync_wsgi", marks=pytest.mark.asyncio_only),
]
)
def client_type(request: pytest.FixtureRequest) -> str:
return request.param
EOF
- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
env:
# musllinux is dropped: rustup.rs ships no riscv64 musl toolchain.
CIBW_BUILD: ${{ matrix.build }}
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
# pyqwest ships no [tool.cibuildwheel], so the Rust toolchain its
# maturin backend needs is installed in-container here. aws-lc-sys
# (pulled in by reqwest's rustls/http3 stack) ships prebuilt
# riscv64gc bindings, and cmake is already in the manylinux image.
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"
MATURIN_PEP517_ARGS="${{ matrix.features }}"
CIBW_TEST_REQUIRES: pytest pytest-benchmark anyio trio outcome sniffio
CIBW_TEST_SOURCES: >-
tests/__init__.py tests/_util.py tests/conftest.py
tests/test_common.py tests/test_multipart_encode.py
tests/test_protocol_errors.py tests/test_request.py
tests/test_response.py tests/test_timeout.py
tests/test_validation.py pyproject.toml
# The other test files need the pyvoy local server dropped above;
# this subset is the pyvoy-independent slice of upstream's own
# suite -- request/response/multipart construction, protocol-error
# framing over a raw socket (tests/_util.py's raw_server), TLS
# option validation and the sync timeout context manager.
CIBW_TEST_COMMAND: >-
python -c "import pyqwest._pyqwest as m; assert m.__file__.endswith('.so'), m.__file__"
&& python -m pytest -v
tests/test_common.py tests/test_multipart_encode.py
tests/test_protocol_errors.py tests/test_request.py
tests/test_response.py tests/test_timeout.py
tests/test_validation.py
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pyqwest-${{ env.PYQWEST_VERSION }}-${{ matrix.tag }}-manylinux_riscv64
path: wheelhouse/*.whl
if-no-files-found: error
publish:
name: Publish pyqwest ${{ 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: pyqwest-${{ matrix.version }}-*-manylinux_riscv64