Merge pull request #369 from chopratejas/fix-wheel-perl-ipc-cmd-debian

fix(ci): wheel before-script must work on Debian aarch64-cross container
This commit is contained in:
Tejas Chopra 2026-05-03 20:06:15 -07:00 committed by GitHub
commit 1323830f70
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 74 additions and 15 deletions

View file

@ -230,23 +230,44 @@ jobs:
# `openssl = { features = ["vendored"] }` dep — that compiles
# OpenSSL from source as part of the cargo build, so we no
# longer need to install system OpenSSL in the manylinux
# container or via Homebrew on macOS. We DO still install
# `perl-IPC-Cmd` because OpenSSL's vendored Configure script
# uses it (without it the build fails with "Can't locate
# IPC/Cmd.pm"). The `if`/`elif` covers RHEL-family manylinux
# images; we don't run on Debian-family musllinux today, but
# the apt branch makes it forward-compatible.
# container or via Homebrew on macOS. We DO need `IPC::Cmd`
# at build time because OpenSSL's vendored Configure script
# imports it (without it the build fails with "Can't locate
# IPC/Cmd.pm").
#
# `IPC::Cmd` has been a Perl core module since 5.10, so any
# working `perl` install provides it. The aarch64-cross
# container the maturin-action uses is Debian/Ubuntu-based
# (apt), the x86_64 native container is AlmaLinux 8 (yum/dnf).
# Probe the IPC::Cmd module directly first; only install when
# missing, using whichever package manager exists. The legacy
# `libipc-cmd-perl` alias on Debian is no longer in default
# sources — installing plain `perl` pulls IPC::Cmd via
# perl-modules-* on every Debian/Ubuntu version we'll see.
before-script-linux: |
set -euo pipefail
if command -v yum >/dev/null 2>&1; then
if perl -MIPC::Cmd -e 1 >/dev/null 2>&1; then
echo "IPC::Cmd already available"
exit 0
fi
if command -v dnf >/dev/null 2>&1; then
dnf install -y perl-IPC-Cmd
elif command -v yum >/dev/null 2>&1; then
yum install -y perl-IPC-Cmd
elif command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y --no-install-recommends libipc-cmd-perl
apt-get update -qq
# `perl` is the meta-package that pulls perl-modules-* containing IPC::Cmd.
apt-get install -y --no-install-recommends perl
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache perl-utils
else
echo "::error::No supported package manager (yum/apt-get) found in manylinux container" >&2
echo "::error::No supported package manager (dnf/yum/apt-get/apk) in container" >&2
exit 1
fi
# Final assertion — fail the build now (not 5 minutes later
# in the openssl-src compile step) if IPC::Cmd is still not
# importable. No silent fallback per project guideline.
perl -MIPC::Cmd -e 'print "IPC::Cmd loaded OK\n"'
env:
# PyO3 0.22 supports up to Python 3.13; allow forward-compat
# builds for 3.14+ until we bump PyO3 (tracked separately).

View file

@ -89,15 +89,53 @@ def test_headroom_proxy_vendors_openssl() -> None:
def test_build_wheels_installs_perl_ipc_cmd_for_vendored_openssl() -> None:
"""OpenSSL's vendored `Configure` script needs `IPC::Cmd`. Without
it the build fails with `Can't locate IPC/Cmd.pm`. The before-script
must install it on whichever distro the manylinux container runs
(RHEL family today; defensive apt branch for future Debian-family
musllinux builds).
must (a) probe the module first to skip a no-op install when the
container already has it, (b) cover RHEL family (dnf/yum) AND
Debian/Ubuntu (apt-get) AND musllinux (apk) since the maturin-action
uses different containers per target, and (c) fail loud with an
explicit `perl -MIPC::Cmd -e 1` assertion if the install path
didn't actually resolve the module — no silent fallback into a
later confusing openssl-src build error.
The previous shape used `libipc-cmd-perl` on the apt branch, which
is a deprecated alias and is not in the default sources of the
aarch64-cross container; that broke the aarch64 wheel build.
"""
content = (ROOT / ".github" / "workflows" / "release.yml").read_text(encoding="utf-8")
assert "before-script-linux:" in content
assert "perl-IPC-Cmd" in content # yum (RHEL family)
assert "libipc-cmd-perl" in content # apt (Debian family fallback)
# Pre-probe so we no-op when IPC::Cmd is already importable.
assert "perl -MIPC::Cmd -e 1" in content
# All three RHEL-family + Debian-family + Alpine package managers covered.
assert "dnf install -y perl-IPC-Cmd" in content
assert "yum install -y perl-IPC-Cmd" in content
# The plain `perl` meta-package pulls perl-modules-* on Debian/Ubuntu,
# which contains IPC::Cmd. The legacy `libipc-cmd-perl` alias must NOT
# be referenced as an installable target — it is no longer in default
# Debian/Ubuntu sources. We allow the string in YAML/shell comments
# (operator hints) by checking only non-comment lines.
assert "apt-get install -y --no-install-recommends perl" in content
assert "apk add --no-cache perl-utils" in content
non_comment_lines: list[str] = []
for raw in content.splitlines():
stripped = raw.lstrip()
# Drop YAML and shell `#` comments. Mid-line `#` comments would
# require a real YAML/shell tokenizer; the file's actual install
# commands are never on the same physical line as a comment.
if stripped.startswith("#"):
continue
non_comment_lines.append(raw)
code_only = "\n".join(non_comment_lines)
assert "libipc-cmd-perl" not in code_only, (
"libipc-cmd-perl must not appear as an apt-get target — it is a "
"deprecated alias not in default Debian/Ubuntu sources."
)
# Final fail-loud assertion (no silent fallback).
assert "perl -MIPC::Cmd -e 'print \"IPC::Cmd loaded OK" in content
def test_build_wheels_does_not_set_openssl_dir() -> None: