Skip to content

Commit 0399ca1

Browse files
committed
pydantic-monty-runtime: add build-pydantic-monty-runtime.yml for riscv64 wheels
1 parent 8ec9abe commit 0399ca1

1 file changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# SPDX-FileCopyrightText: 2026 The RISE Project
2+
# SPDX-License-Identifier: MIT
3+
---
4+
# This workflow is based on the `build` job of
5+
# https://github.com/pydantic/monty/blob/v0.0.21/.github/workflows/ci.yml
6+
name: Build pydantic-monty-runtime wheels (riscv64)
7+
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
version:
12+
description: 'pydantic-monty-runtime version to build (git tag, e.g. v0.0.21)'
13+
required: true
14+
default: 'v0.0.21'
15+
pull_request:
16+
paths:
17+
- '.github/workflows/build-pydantic-monty-runtime.yml'
18+
19+
concurrency:
20+
group: ${{ github.workflow }}-${{ inputs.version || 'v0.0.21' }}-${{ github.head_ref || github.run_id }}
21+
cancel-in-progress: true
22+
23+
permissions:
24+
contents: read # to fetch code (actions/checkout)
25+
26+
env:
27+
# `inputs.version` is empty on pull_request events; default to v0.0.21 there.
28+
MONTY_VERSION: ${{ inputs.version || 'v0.0.21' }}
29+
30+
jobs:
31+
setup:
32+
uses: $/.github/workflows/_setup.yml
33+
34+
build_wheel:
35+
needs: [setup]
36+
name: Build pydantic-monty-runtime ${{ inputs.version || 'v0.0.21' }} manylinux_riscv64
37+
runs-on: ubuntu-24.04-riscv
38+
timeout-minutes: 360
39+
40+
steps:
41+
- name: Checkout monty ${{ env.MONTY_VERSION }}
42+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
43+
with:
44+
repository: pydantic/monty
45+
ref: ${{ env.MONTY_VERSION }}
46+
persist-credentials: false
47+
48+
# `crates/monty-runtime`'s pyproject.toml has no `license-files`, so
49+
# maturin's default LICEN[CS]E* glob only looks next to it -- the repo's
50+
# actual LICENSE lives at the workspace root (gotcha 146). Upstream's own
51+
# published wheel has the same gap (no LICENSE in its dist-info); copy it
52+
# in so ours doesn't.
53+
- name: Copy LICENSE next to the crate's pyproject.toml
54+
run: cp LICENSE crates/monty-runtime/LICENSE
55+
56+
# `[tool.maturin] bindings = "bin"`: the wheel is one compiled executable
57+
# with no ABI tag (monty-runtime never links pyo3 -- monty-proto's pyo3
58+
# dependency is gated behind a "python" feature this crate doesn't
59+
# enable), so a single native build covers every interpreter.
60+
- name: Build wheel
61+
uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
62+
with:
63+
command: build
64+
target: riscv64gc-unknown-linux-gnu
65+
args: --release --locked --out dist
66+
manylinux: '2_39'
67+
working-directory: crates/monty-runtime
68+
before-script-linux: git config --global --add safe.directory "*"
69+
70+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
71+
with:
72+
name: pydantic-monty-runtime-${{ env.MONTY_VERSION }}-manylinux_riscv64
73+
path: crates/monty-runtime/dist/*.whl
74+
if-no-files-found: error
75+
76+
test_wheel:
77+
name: Test pydantic-monty-runtime ${{ inputs.version || 'v0.0.21' }} on Python ${{ matrix.python-version }}
78+
needs: [setup, build_wheel]
79+
runs-on: ubuntu-24.04-riscv
80+
timeout-minutes: 30
81+
env:
82+
# Without this uv would reuse the runner image's system CPython for 3.12
83+
# and download a standalone build for the others.
84+
UV_PYTHON_PREFERENCE: only-managed
85+
strategy:
86+
fail-fast: false
87+
matrix:
88+
# This repo's default interpreter matrix (gotcha in workflow-anatomy.md);
89+
# the wheel is interpreter-agnostic (bindings = "bin"), so every
90+
# interpreter -- including free-threaded -- exercises the same binary.
91+
python-version: ['3.12', '3.13', '3.14', '3.14t']
92+
93+
steps:
94+
- name: Download wheel
95+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
96+
with:
97+
name: pydantic-monty-runtime-${{ env.MONTY_VERSION }}-manylinux_riscv64
98+
99+
- name: Install Python
100+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
101+
with:
102+
python-version: ${{ matrix.python-version }}
103+
activate-environment: true
104+
enable-cache: false
105+
106+
- name: Install wheel
107+
run: uv pip install --reinstall --no-index --find-links . pydantic-monty-runtime
108+
109+
# No wheel-level test suite ships in the sdist (gotcha 187): the CLI's
110+
# own tests (crates/monty-runtime/tests/*.rs) are Rust integration tests
111+
# run by upstream's own `cargo test`, never packaged. Drive the real
112+
# sandboxed interpreter instead of settling for a bare --version check,
113+
# mirroring upstream's own tests/mounts.rs cases (a mounted-path read, an
114+
# unmounted-path PermissionError, and a write-limit OSError) rather than
115+
# inventing an unmounted-write round trip upstream itself never asserts.
116+
- name: Test wheel
117+
run: |
118+
set -euo pipefail
119+
monty --version
120+
monty --help >/dev/null
121+
122+
[ "$(monty -c "print('hello world')")" = "hello world" ]
123+
124+
work=$(mktemp -d)
125+
cat > "$work/script.py" <<'PY'
126+
print(1 + 2)
127+
PY
128+
[ "$(monty "$work/script.py")" = "3" ]
129+
130+
host=$(mktemp -d)
131+
echo 'hello from the host' > "$host/in.txt"
132+
cat > "$work/mount.py" <<'PY'
133+
from pathlib import Path
134+
135+
print(Path('/mnt/in.txt').read_text().strip())
136+
PY
137+
[ "$(monty -m "$host::/mnt" "$work/mount.py")" = "hello from the host" ]
138+
139+
cat > "$work/unmounted.py" <<'PY'
140+
from pathlib import Path
141+
142+
Path('/outside.txt').read_text()
143+
PY
144+
set +e
145+
err=$(monty -m "$host::/mnt" "$work/unmounted.py" 2>&1)
146+
rc=$?
147+
set -e
148+
[ "$rc" -ne 0 ]
149+
echo "$err" | grep -q "PermissionError: Permission denied: '/outside.txt'"
150+
151+
cat > "$work/write_limit.py" <<'PY'
152+
from pathlib import Path
153+
154+
Path('/mnt/out.txt').write_text('hello from the sandbox')
155+
PY
156+
set +e
157+
err=$(monty -m "$host::/mnt::rw::4" "$work/write_limit.py" 2>&1)
158+
rc=$?
159+
set -e
160+
[ "$rc" -ne 0 ]
161+
echo "$err" | grep -q "OSError: disk write limit of 4 bytes exceeded"
162+
163+
publish:
164+
name: Publish pydantic-monty-runtime ${{ inputs.version || 'v0.0.21' }}
165+
needs: [setup, build_wheel, test_wheel]
166+
permissions:
167+
contents: write
168+
pull-requests: write
169+
uses: $/.github/workflows/_publish-wheel.yml
170+
with:
171+
artifact-pattern: pydantic-monty-runtime-${{ inputs.version || 'v0.0.21' }}-manylinux_riscv64

0 commit comments

Comments
 (0)