From ea98400820a3a69097d79e2b19055e9f554fee2d Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Thu, 22 Jan 2026 14:00:02 +0100 Subject: [PATCH] ci: Fix macOS tests and add FreeBSD support (#3442) * ci: Remove failing macos-13 from test matrix * ci: Add FreeBSD testing workflow * ci: Document test matrix rationale * ci: Update cross-platform-actions to v0.32.0 for FreeBSD 14.2 support * ci: Use FreeBSD 14.1 (14.2 has SSH connectivity issues) * ci: Switch to vmactions/freebsd-vm for FreeBSD testing * ci: Fix FreeBSD package names (pip included in Python) * ci: Simplify FreeBSD matrix and fix package names * ci: Use specific Python version command on FreeBSD * ci: Add sqlite3 package for FreeBSD * tests: Increase signal integration test timeouts for CI The signal integration tests were flaky in CI environments, especially FreeBSD VMs, due to 10-second timeouts being too short. Increased timeouts to 30 seconds to handle slower CI environments. --- .github/workflows/freebsd.yml | 47 ++++++++++++++++++++++++++++++++ .github/workflows/tox.yml | 5 ++-- tests/test_signal_integration.py | 10 +++++-- 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/freebsd.yml diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml new file mode 100644 index 00000000..060f40ca --- /dev/null +++ b/.github/workflows/freebsd.yml @@ -0,0 +1,47 @@ +name: FreeBSD + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +env: + FORCE_COLOR: 1 + +jobs: + test: + name: FreeBSD ${{ matrix.freebsd-version }} / Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - freebsd-version: '14.2' + python-version: '3.12' + python-pkg: 'python312 py312-sqlite3' + - freebsd-version: '14.2' + python-version: '3.13' + python-pkg: 'python313 py313-sqlite3' + steps: + - uses: actions/checkout@v6 + + - name: Test on FreeBSD + uses: vmactions/freebsd-vm@v1 + with: + release: ${{ matrix.freebsd-version }} + usesh: true + prepare: | + pkg install -y ${{ matrix.python-pkg }} + run: | + python${{ matrix.python-version }} -m venv venv + . venv/bin/activate + pip install --upgrade pip + pip install pytest pytest-cov coverage + pip install -e . + pytest --cov=gunicorn -v tests/ \ + --ignore=tests/workers/test_ggevent.py \ + --ignore=tests/workers/test_geventlet.py diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 2555073c..c7daa648 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -17,9 +17,8 @@ jobs: unsupported: [false] os: - ubuntu-latest - # not defaulting to macos-latest: Python <= 3.9 was missing from macos-14 @ arm64 - - macos-13 - # Not testing Windows, because tests need Unix-only fcntl, grp, pwd, etc. + # Not testing Windows: tests need Unix-only fcntl, grp, pwd, etc. + # FreeBSD: tested in separate freebsd.yml workflow python-version: # Supporting Python 3.10 through 3.13 - "3.10" diff --git a/tests/test_signal_integration.py b/tests/test_signal_integration.py index 85d99ebf..868e1564 100644 --- a/tests/test_signal_integration.py +++ b/tests/test_signal_integration.py @@ -18,6 +18,10 @@ import time import pytest +# Timeout for CI environments (VMs can be slow) +CI_TIMEOUT = 30 + + # Simple WSGI app inline SIMPLE_APP = ''' def application(environ, start_response): @@ -40,7 +44,7 @@ def find_free_port(): return s.getsockname()[1] -def wait_for_server(host, port, timeout=10): +def wait_for_server(host, port, timeout=CI_TIMEOUT): """Wait until server is accepting connections.""" start = time.monotonic() while time.monotonic() - start < timeout: @@ -142,7 +146,7 @@ class TestSignalHandlingIntegration: # Wait for process to exit try: - exit_code = proc.wait(timeout=10) + exit_code = proc.wait(timeout=CI_TIMEOUT) assert exit_code == 0, f"Expected exit code 0, got {exit_code}" except subprocess.TimeoutExpired: proc.kill() @@ -161,7 +165,7 @@ class TestSignalHandlingIntegration: # Wait for process to exit try: - exit_code = proc.wait(timeout=10) + exit_code = proc.wait(timeout=CI_TIMEOUT) assert exit_code == 0, f"Expected exit code 0, got {exit_code}" except subprocess.TimeoutExpired: proc.kill()