-
Notifications
You must be signed in to change notification settings - Fork 2
92 lines (88 loc) · 4.41 KB
/
Copy pathpython.yml
File metadata and controls
92 lines (88 loc) · 4.41 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
name: Python binding
# Path filter = the actual inputs to this job, which is why it is wider than
# the crate directory: `aph-py` links `aph-core`, and it embeds two files from
# `examples/` at compile time, so a change to either changes what this job
# compiles. The two workspace files are inputs for the same reason and are the
# easiest ones to forget — the manifest carries `[workspace.dependencies]`
# (which `aph-py` inherits) and the `members` list itself, and the lockfile is
# where the exact pyo3 this job compiles gets pinned. That pin only exists once
# a resolve has SEEN this member, so the `Cargo.lock` regenerated by the first
# cargo run over `aph-py` belongs in the same commit as the crate: landing the
# member without it leaves this whole dependency tree outside the lock, and CI
# would then resolve pyo3 afresh on every run. Omitting these paths lets a pyo3
# bump, or an edit dropping `aph-py` from `members`, reach main without ever
# scheduling this job: main stays green while `cargo test -p aph-py` is broken.
# With them, nothing else in the repository can affect it.
on:
push:
branches: [main]
paths:
- "interpreters/rust/aph-py/**"
- "interpreters/rust/aph-core/**"
- "interpreters/rust/Cargo.toml"
- "interpreters/rust/Cargo.lock"
- "examples/**"
- ".github/workflows/python.yml"
pull_request:
branches: [main]
paths:
- "interpreters/rust/aph-py/**"
- "interpreters/rust/aph-core/**"
- "interpreters/rust/Cargo.toml"
- "interpreters/rust/Cargo.lock"
- "examples/**"
- ".github/workflows/python.yml"
# Least privilege: this workflow only reads the tree.
permissions:
contents: read
jobs:
test:
name: cargo test -p aph-py
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install stable Rust
uses: dtolnay/rust-toolchain@stable
# ONE Python version on purpose. The crate builds against CPython's
# stable ABI (`abi3-py39`), so the version present at build time does not
# decide which versions a wheel can load — testing a matrix would repeat
# the same assertions against the same ABI.
#
# pyo3's `auto-initialize` requires a SHARED libpython, which this action's
# distributions provide; a static-only interpreter fails the build with
# that explanation rather than a link error.
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
workspaces: interpreters/rust
# Split from the test run so a libpython link failure is legible as one:
# this step proves the cdylib links, the next proves the behaviour.
- name: Build the extension
working-directory: interpreters/rust
run: cargo build -p aph-py
# aph-py is outside default-members, so the bare `cargo test` in the
# Rust workflow never reaches it — name it or it is not tested.
- name: Run tests
working-directory: interpreters/rust
run: cargo test -p aph-py
# Determinism: two cold builds with canonicalized paths must produce
# the same bytes, or this artifact's contents depend on WHERE it was
# built — the property the committed-wasm byte-diff enforces for the
# go binding, checked here in double-build form because no pyo3
# artifact is committed for a reference diff. Same remap roots as
# go.yml, same reasoning: rustc embeds source paths (panic locations,
# registry paths), and unmapped they make every builder's bytes
# unique.
- name: Reproducible build check (double build, canonical paths)
working-directory: interpreters/rust
run: |
FLAGS="--remap-path-prefix=$HOME/.cargo=/cargo --remap-path-prefix=$HOME/.rustup=/rustup --remap-path-prefix=$(pwd)=/build"
RUSTFLAGS="$FLAGS" cargo build --release -p aph-py --target-dir /tmp/det-a
RUSTFLAGS="$FLAGS" cargo build --release -p aph-py --target-dir /tmp/det-b
cmp /tmp/det-a/release/libaph.so /tmp/det-b/release/libaph.so \
&& echo "aph-py cdylib is byte-reproducible on this runner" \
|| { echo "::error::two identical-input builds of aph-py produced different bytes — the build embeds nondeterminism (a path the remap flags miss, a timestamp, an env leak)"; exit 1; }