Repository navigation
204 lines (183 loc) · 8.07 KB
/
Copy pathbuild-pyqwest.yml
File metadata and controls
204 lines (183 loc) · 8.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# 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