fix: build Linux Python wheels with vendored OpenSSL (manylinux + musllinux) (#327)

Fixes the Linux Python wheel build that broke the `0.9.3` release (and would
have broken `0.9.4`), and adds a CI guard so it cannot regress silently.

### Root cause
The `live-binance` data layer links `native-tls` -> `openssl-sys`, which needs
OpenSSL at build time. Neither wheel container provides it:
- **manylinux** ships no OpenSSL headers, and
- **musllinux** cross-compiles against a musl sysroot that has no OpenSSL at all,
  so installing a host package (`yum`/`apk`) cannot reach the cross target.

The 3-OS Python CI jobs build natively on the runner, which already has system
OpenSSL, so CI stayed green while the release container build failed.

### Fix
- New opt-in **`vendored-tls`** feature on `wickra-data` and the Python binding:
  enables `native-tls/vendored`, compiling OpenSSL from source and linking it
  statically. No system OpenSSL needed on either libc. No-op on macOS/Windows
  (Security.framework / SChannel — `openssl-sys` is never in the graph there).
- `release.yml` builds the Linux wheels with `--features vendored-tls` (replaces
  the manylinux-only `before-script-linux` header install, which could not fix
  the musllinux cross build).
- CI gains a **`manylinux` + `musllinux` container build-smoke** matrix job, so
  both container builds run on every PR. This PR's own CI is the proof the fix
  works before any release re-attempt.

### Notes
- No version bump: `0.9.4` published nowhere (the release run was cancelled
  before any publish job ran), so this lands on `0.9.4` and the tag is re-pointed
  at the fixed commit.
- Adds checks to `ci.yml` (the smoke job is now a 2-entry matrix).
This commit is contained in:
kingchenc
2026-06-17 22:26:21 +02:00
committed by GitHub
parent e595ea8bfe
commit 41d5a7dd25
6 changed files with 100 additions and 17 deletions
+41
View File
@@ -1031,6 +1031,47 @@ jobs:
mvn -B -q -f examples/java exec:exec -Dexec.mainClass="org.wickra.examples.$cls"
done
# Build a Python wheel inside both the manylinux and the musllinux container,
# mirroring the Linux wheel build in release.yml. The 3-OS Python jobs build
# natively on the runner, which already ships system OpenSSL, so they cannot
# catch a build-time gap that only exists inside the slim release containers —
# exactly what broke the 0.9.3 Linux wheels (the live-binance data layer links
# native-tls -> openssl-sys, and the containers provide no OpenSSL: manylinux
# lacks the headers, musllinux cross-compiles against a musl sysroot without
# OpenSSL at all). The wheels are built with the `vendored-tls` feature, which
# statically compiles OpenSSL from source. This job exercises both container
# builds on every PR, so the same class of breakage now fails CI, not release.
python-wheel-container-smoke:
name: Python wheel (${{ matrix.manylinux }} smoke)
runs-on: ubuntu-latest
timeout-minutes: 30 # backstop: vendored OpenSSL adds a from-source compile
strategy:
fail-fast: false
matrix:
manylinux: [auto, musllinux_1_2]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Sync root README into bindings/python so the build matches release
run: cp README.md bindings/python/README.md
- uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
with:
working-directory: bindings/python
target: x86_64
# Keep in sync with release.yml: vendored OpenSSL for the Linux wheels.
args: --release --out dist --features vendored-tls
manylinux: ${{ matrix.manylinux }}
# Building OpenSSL from source needs Perl modules (IPC::Cmd,
# Time::Piece, ...) the minimal manylinux (CentOS 7) image lacks.
# perl-core pulls the full distribution; the explicit names document
# the ones OpenSSL's Configure has required. The musllinux cross image
# ships a complete Perl and has no yum, so this is a no-op there.
before-script-linux: |
if command -v yum >/dev/null 2>&1; then yum install -y perl-core perl-IPC-Cmd perl-Data-Dumper perl-Time-Piece; fi
# The cross-library benchmark has moved to a dedicated scheduled workflow
# (.github/workflows/bench.yml) — see audit finding R10. It runs nightly
# at 03:00 UTC and on-demand via `workflow_dispatch`, and is no longer on
+14 -8
View File
@@ -184,16 +184,22 @@ jobs:
with:
working-directory: bindings/python
target: ${{ matrix.target }}
args: --release --strip --out dist
manylinux: ${{ matrix.manylinux }}
# The live-binance data layer links native-tls -> openssl-sys, which
# needs the system OpenSSL headers at build time. The manylinux and
# musllinux build containers do not ship them, so install them inside
# the container before maturin compiles the wheel (no-op on the native
# macOS/Windows runners, where this hook does not run).
# needs OpenSSL at build time. The manylinux containers lack the headers
# and the musllinux build cross-compiles against a musl sysroot with no
# OpenSSL at all, so build the Linux wheels with vendored OpenSSL
# (compiled from source, linked statically). No-op on the native
# macOS/Windows runners, where native-tls never pulls openssl-sys. The
# CI `python-wheel-container-smoke` job exercises both containers on PRs.
args: --release --strip --out dist --features vendored-tls
manylinux: ${{ matrix.manylinux }}
# Building OpenSSL from source needs Perl modules (IPC::Cmd,
# Time::Piece, ...) the minimal manylinux (CentOS 7) image lacks.
# perl-core pulls the full distribution; the explicit names document
# the ones OpenSSL's Configure has required. The musllinux cross image
# ships a complete Perl and has no yum, so this is a no-op there.
before-script-linux: |
if command -v yum >/dev/null 2>&1; then yum install -y openssl-devel; fi
if command -v apk >/dev/null 2>&1; then apk add --no-cache openssl-dev pkgconfig; fi
if command -v yum >/dev/null 2>&1; then yum install -y perl-core perl-IPC-Cmd perl-Data-Dumper perl-Time-Piece; fi
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
# Include manylinux in the name so the glibc and musl x86_64/aarch64