Repository navigation
docs: Update projects #24
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 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 |