Skip to content

Commit 3877f9b

Browse files
committed
Fix CI hanging on emulated platforms (aarch64/musllinux)
Add timeout and skip heavy tests on slow emulated platforms to prevent CI from hanging forever under QEMU emulation. Changes: - Add timeout-minutes: 90 to build_wheels job to prevent infinite hangs - Create _ci_test_runner.py that detects emulated platforms and skips heavy concurrency/memory/safety tests that can hang under QEMU - Update CIBW_TEST_COMMAND to use the new intelligent test runner - Pass platform_id via CIBW_ENVIRONMENT for platform detection This fixes the issue where 9 musllinux_aarch64 jobs were hanging for over an hour, causing CI to never complete on PR #48. Native platforms (x86_64, win_amd64, macosx_x86_64, macosx_arm64) still run the full test suite for complete coverage.
1 parent 9533ab3 commit 3877f9b

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

.github/workflows/cibuildwheel.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
build_wheels:
1616
name: Build wheels on ${{ matrix.os }}
1717
runs-on: ${{ matrix.os }}
18+
timeout-minutes: 90
1819
strategy:
1920
# Ensure that a wheel builder finishes even if another fails
2021
fail-fast: false
@@ -286,12 +287,13 @@ jobs:
286287
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux_image }}
287288
CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }}
288289
CIBW_BEFORE_BUILD: pip install pybind11
289-
CIBW_TEST_COMMAND: python {project}/tests/_ci_debug_import.py && pytest {project}/tests -vv
290-
CIBW_TEST_COMMAND_WINDOWS: python {project}\tests\_ci_debug_import.py && pytest {project}\tests -vv
290+
CIBW_TEST_COMMAND: python {project}/tests/_ci_test_runner.py
291+
CIBW_TEST_COMMAND_WINDOWS: python {project}\tests\_ci_test_runner.py
291292
CIBW_TEST_REQUIRES: pytest numpy
292293
CIBW_BUILD_VERBOSITY: 1
293294
CIBW_ARCHS: ${{ matrix.arch }}
294295
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }}
296+
CIBW_ENVIRONMENT: CIBW_PLATFORM_ID=${{ matrix.platform_id }}
295297
- uses: actions/upload-artifact@v4
296298
with:
297299
name: wheels-${{ matrix.platform_id }}-py${{ matrix.python }}

tests/_ci_test_runner.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env python
2+
"""
3+
CI test runner that adapts test execution based on platform.
4+
5+
For emulated platforms (aarch64, musllinux), skip heavy concurrency/stress tests
6+
that can hang or take excessive time under QEMU emulation.
7+
8+
For native platforms (x86_64, win_amd64, macosx), run full test suite.
9+
"""
10+
import os
11+
import sys
12+
import subprocess
13+
import platform
14+
15+
def get_platform_info():
16+
"""Determine if we're running on an emulated platform."""
17+
platform_id = os.environ.get('CIBW_PLATFORM_ID', '')
18+
19+
is_emulated = (
20+
'aarch64' in platform_id or
21+
'musllinux' in platform_id or
22+
platform.machine() == 'aarch64'
23+
)
24+
25+
return platform_id, is_emulated
26+
27+
def main():
28+
"""Run tests appropriate for the current platform."""
29+
platform_id, is_emulated = get_platform_info()
30+
31+
print(f"Platform ID: {platform_id}")
32+
print(f"Machine: {platform.machine()}")
33+
print(f"Is emulated/slow platform: {is_emulated}")
34+
35+
import_test = os.path.join(os.path.dirname(__file__), '_ci_debug_import.py')
36+
print(f"\n=== Running import test: {import_test} ===")
37+
result = subprocess.run([sys.executable, import_test])
38+
if result.returncode != 0:
39+
print("Import test failed!")
40+
return result.returncode
41+
42+
test_dir = os.path.dirname(__file__)
43+
44+
if is_emulated:
45+
print("\n=== Running lightweight test suite (emulated platform) ===")
46+
ignore_args = [
47+
'--ignore=tests/unit/test_concurrency.py',
48+
'--ignore=tests/unit/test_memory_safety.py',
49+
'--ignore=tests/unit/test_comprehensive_safety.py',
50+
'--ignore=tests/unit/test_segfault_safety.py',
51+
]
52+
cmd = [sys.executable, '-m', 'pytest', test_dir, '-vv'] + ignore_args
53+
else:
54+
print("\n=== Running full test suite (native platform) ===")
55+
cmd = [sys.executable, '-m', 'pytest', test_dir, '-vv']
56+
57+
print(f"Command: {' '.join(cmd)}")
58+
result = subprocess.run(cmd)
59+
60+
return result.returncode
61+
62+
if __name__ == '__main__':
63+
sys.exit(main())

0 commit comments

Comments
 (0)