Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions .github/workflows/_build_linux_aarch64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: Build Linux aarch64 Wheels

on:
workflow_call:

jobs:
build-linux-aarch64:
name: Build Linux aarch64 Wheels
# Use native ARM64 runners for much faster builds (vs QEMU emulation)
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

# Setup Go for BoringSSL build
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true

# Build wheels with cibuildwheel (handles manylinux containers)
# Vendor dependencies are built inside the manylinux container and cached across Python versions
# Note: GitHub Actions cache doesn't work here since vendor dir is inside the container
- name: Build wheels
uses: pypa/cibuildwheel@v3.3
env:
# Build for all Python versions on aarch64
CIBW_BUILD: cp38-manylinux_aarch64 cp39-manylinux_aarch64 cp310-manylinux_aarch64 cp311-manylinux_aarch64 cp312-manylinux_aarch64 cp313-manylinux_aarch64 cp314-manylinux_aarch64
# Vendor build happens inside manylinux container via before-build (from pyproject.toml)
# The script will detect cached libraries and skip rebuilding across Python versions
CIBW_ARCHS_LINUX: aarch64

# Setup Python versions for testing
- name: Setup Python versions
uses: actions/setup-python@v5
with:
python-version: |
3.8
3.9
3.10
3.11
3.12
3.13
3.14
allow-prereleases: true

# Test the built wheels on native ARM64
- name: Test wheels
run: |
# Test each wheel that was built
for wheel in ./wheelhouse/*.whl; do
echo "========================================"
echo "Testing wheel: $(basename "$wheel")"
echo "========================================"

# Extract Python version from wheel filename (e.g., cp39, cp310)
python_tag=$(basename "$wheel" | grep -oE 'cp[0-9]+' | head -1)
python_version="${python_tag:2:1}.${python_tag:3}"

echo "Setting up Python $python_version..."

# Try to find the matching Python version
python_cmd=""
for cmd in "python${python_version}" "python3.${python_version#*.}" "python3"; do
if command -v "$cmd" &> /dev/null; then
# Verify this is the right version
version_check=$($cmd --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
if [ "$version_check" = "$python_version" ]; then
python_cmd="$cmd"
break
fi
fi
done

# Fall back to python3 if we couldn't find exact match
if [ -z "$python_cmd" ]; then
echo "WARNING: Python $python_version not found, using python3"
python_cmd="python3"
fi

echo "Using Python: $($python_cmd --version)"

# Install the wheel in a fresh environment
"$python_cmd" -m pip install --force-reinstall "$wheel"

# Run the test script
echo ""
echo "Running tests..."
"$python_cmd" scripts/test_local_build.py

# Check exit code
if [ $? -eq 0 ]; then
echo ""
echo "[OK] Wheel test PASSED: $(basename "$wheel")"
else
echo ""
echo "[FAIL] Wheel test FAILED: $(basename "$wheel")"
exit 1
fi

echo ""
done

echo "========================================"
echo "All wheel tests PASSED"
echo "========================================"

# Upload wheels as artifacts
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux-aarch64
path: ./wheelhouse/*.whl
if-no-files-found: error
retention-days: 5
# Retry on transient failures
continue-on-error: false
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: Build Linux Wheels
name: Build Linux x86_64 Wheels

on:
workflow_call:

jobs:
build-linux:
name: Build Linux Wheels
build-linux-x86_64:
name: Build Linux x86_64 Wheels
runs-on: ubuntu-latest

steps:
Expand All @@ -20,34 +20,17 @@ jobs:
go-version: '1.21'
cache: true

# Cache vendor dependencies to speed up builds
- name: Restore vendor cache
id: cache-vendor
uses: actions/cache/restore@v4
with:
path: vendor
key: vendor-linux-manylinux-${{ hashFiles('scripts/linux/setup_vendors.sh') }}-v11
restore-keys: |
vendor-linux-manylinux-${{ hashFiles('scripts/linux/setup_vendors.sh') }}-v11

# Build wheels with cibuildwheel (handles manylinux containers)
# The vendor directory is mounted into the container and shared across Python versions
# The setup script will skip rebuilding if libraries already exist
# Vendor dependencies are built inside the manylinux container and cached across Python versions
# Note: GitHub Actions cache doesn't work here since vendor dir is inside the container
- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
uses: pypa/cibuildwheel@v3.3
env:
# Build for all Python versions
# Build for all Python versions on x86_64
CIBW_BUILD: cp38-manylinux_x86_64 cp39-manylinux_x86_64 cp310-manylinux_x86_64 cp311-manylinux_x86_64 cp312-manylinux_x86_64 cp313-manylinux_x86_64 cp314-manylinux_x86_64
# Vendor build happens inside manylinux container via before-build (from pyproject.toml)
# The script will detect cached libraries and skip rebuilding

# Save vendor cache after build
- name: Save vendor cache
if: steps.cache-vendor.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: vendor
key: vendor-linux-manylinux-${{ hashFiles('scripts/linux/setup_vendors.sh') }}-v11
# The script will detect cached libraries and skip rebuilding across Python versions
CIBW_ARCHS_LINUX: x86_64

# Setup Python versions for testing
- name: Setup Python versions
Expand Down Expand Up @@ -125,8 +108,12 @@ jobs:
echo "========================================"

# Upload wheels as artifacts
- uses: actions/upload-artifact@v4
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux
name: wheels-linux-x86_64
path: ./wheelhouse/*.whl
if-no-files-found: error
retention-days: 5
# Retry on transient failures
continue-on-error: false
15 changes: 10 additions & 5 deletions .github/workflows/_build_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ jobs:
cache: true

# Cache vendor dependencies to speed up builds
# Note: Cache is architecture-specific (ARM64 vs x86_64)
- name: Restore vendor cache
id: cache-vendor
uses: actions/cache/restore@v4
with:
path: vendor
key: vendor-macos-${{ hashFiles('scripts/darwin/setup_vendors.sh') }}-v10
key: vendor-macos-${{ runner.arch }}-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/darwin/**/*.sh') }}-v10
restore-keys: |
vendor-macos-${{ hashFiles('scripts/darwin/setup_vendors.sh') }}-v10
vendor-macos-${{ runner.arch }}-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/darwin/**/*.sh') }}-v10

# Build vendor dependencies (always build to ensure clean state)
- name: Build vendor dependencies
Expand All @@ -46,7 +47,7 @@ jobs:
uses: actions/cache/save@v4
with:
path: vendor
key: vendor-macos-${{ hashFiles('scripts/darwin/setup_vendors.sh') }}-v10
key: vendor-macos-${{ runner.arch }}-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/darwin/**/*.sh') }}-v10

# Verify vendor build
- name: Verify vendor build
Expand Down Expand Up @@ -74,7 +75,7 @@ jobs:

# Build wheels for all Python versions
- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
uses: pypa/cibuildwheel@v3.3
env:
# Skip before-build since we already built vendors
CIBW_BEFORE_BUILD: ""
Expand Down Expand Up @@ -152,8 +153,12 @@ jobs:
echo "========================================"

# Upload wheels as artifacts
- uses: actions/upload-artifact@v4
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-macos
path: ./wheelhouse/*.whl
if-no-files-found: error
retention-days: 5
# Retry on transient failures
continue-on-error: false
17 changes: 11 additions & 6 deletions .github/workflows/_build_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ jobs:
uses: actions/cache/restore@v4
with:
path: vendor
key: vendor-windows-${{ hashFiles('scripts/windows/setup_vendors.sh') }}-v10
key: vendor-windows-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/windows/**/*.sh') }}-v10
restore-keys: |
vendor-windows-${{ hashFiles('scripts/windows/setup_vendors.sh') }}-v10
vendor-windows-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/windows/**/*.sh') }}-v10

# Build vendor dependencies (always build to ensure clean state)
- name: Build vendor dependencies
Expand All @@ -48,7 +48,7 @@ jobs:
uses: actions/cache/save@v4
with:
path: vendor
key: vendor-windows-${{ hashFiles('scripts/windows/setup_vendors.sh') }}-v10
key: vendor-windows-${{ hashFiles('scripts/setup_vendors.sh', 'scripts/windows/**/*.sh') }}-v10

# Verify vendor build
- name: Verify vendor build
Expand Down Expand Up @@ -84,11 +84,12 @@ jobs:

# Build wheels for all Python versions
- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
uses: pypa/cibuildwheel@v3.3
env:
# Skip before-build since we already built vendors
CIBW_BEFORE_BUILD: ""
# Build for all Python versions
# Build for all Python versions on AMD64 only
# Note: ARM64 support requires vendor libraries to be built for ARM64, which needs separate build infrastructure
CIBW_BUILD: cp38-win_amd64 cp39-win_amd64 cp310-win_amd64 cp311-win_amd64 cp312-win_amd64 cp313-win_amd64 cp314-win_amd64

# Setup Python versions for testing
Expand Down Expand Up @@ -163,8 +164,12 @@ jobs:
shell: bash

# Upload wheels as artifacts
- uses: actions/upload-artifact@v4
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-windows
path: ./wheelhouse/*.whl
if-no-files-found: error
retention-days: 5
# Retry on transient failures
continue-on-error: false
4 changes: 2 additions & 2 deletions .github/workflows/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ jobs:
# Operating Systems to test
# Comment out any OS you want to skip during development
OS_MATRIX='[
"windows-latest", "ubuntu-latest", "macos-latest"
"ubuntu-latest", "ubuntu-24.04-arm", "macos-latest", "macos-15-intel", "windows-latest"
]'
# OS options: "windows-latest", "ubuntu-latest", "macos-latest"
# OS options: "windows-latest", "ubuntu-latest", "ubuntu-24.04-arm", "macos-latest", "macos-15-intel"

# Python versions to test
PYTHON_MATRIX='[
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ jobs:
uses: actions/cache/restore@v4
with:
path: vendor
key: vendor-${{ runner.os }}-${{ hashFiles('scripts/setup_vendors.sh') }}-v10
key: vendor-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/**/*.sh') }}-v10
restore-keys: |
vendor-${{ runner.os }}-${{ hashFiles('scripts/setup_vendors.sh') }}-v10
vendor-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/**/*.sh') }}-v10

- name: Setup vendor dependencies (always rebuild to ensure clean state)
run: |
Expand Down Expand Up @@ -261,7 +261,7 @@ jobs:
uses: actions/cache/save@v4
with:
path: vendor
key: vendor-${{ runner.os }}-${{ hashFiles('scripts/setup_vendors.sh') }}-v10
key: vendor-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/**/*.sh') }}-v10

- name: Save Python build cache
if: always()
Expand Down
37 changes: 27 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ jobs:
# Load Configuration
# ============================================================
load-config:
name: Load Configuration
uses: ./.github/workflows/_config.yml

# ============================================================
# Test Job
# ============================================================
test:
name: Test
needs: load-config
if: needs.load-config.outputs.enable-tests == 'true'
uses: ./.github/workflows/_test.yml
Expand All @@ -34,10 +36,15 @@ jobs:
# ============================================================
# Build Test Jobs
# ============================================================
build-test-linux:
name: Build Test (Linux)
build-test-linux-x86_64:
name: Build Test (Linux x86_64)
needs: load-config
uses: ./.github/workflows/_build_linux.yml
uses: ./.github/workflows/_build_linux_x86_64.yml

build-test-linux-aarch64:
name: Build Test (Linux aarch64)
needs: load-config
uses: ./.github/workflows/_build_linux_aarch64.yml

build-test-macos:
name: Build Test (macOS)
Expand All @@ -54,7 +61,7 @@ jobs:
# ============================================================
summary:
name: CI Summary
needs: [load-config, test, build-test-linux, build-test-macos, build-test-windows]
needs: [load-config, test, build-test-linux-x86_64, build-test-linux-aarch64, build-test-macos, build-test-windows]
if: always()
runs-on: ubuntu-latest

Expand Down Expand Up @@ -82,13 +89,23 @@ jobs:
echo ""
echo "Build Tests:"

# Linux
if [ "${{ needs.build-test-linux.result }}" == "success" ]; then
echo " ✅ Linux: PASSED"
elif [ "${{ needs.build-test-linux.result }}" == "skipped" ]; then
echo " ⊘ Linux: SKIPPED"
# Linux x86_64
if [ "${{ needs.build-test-linux-x86_64.result }}" == "success" ]; then
echo " ✅ Linux x86_64: PASSED"
elif [ "${{ needs.build-test-linux-x86_64.result }}" == "skipped" ]; then
echo " ⊘ Linux x86_64: SKIPPED"
else
echo " ❌ Linux x86_64: FAILED"
EXIT_CODE=1
fi

# Linux aarch64
if [ "${{ needs.build-test-linux-aarch64.result }}" == "success" ]; then
echo " ✅ Linux aarch64: PASSED"
elif [ "${{ needs.build-test-linux-aarch64.result }}" == "skipped" ]; then
echo " ⊘ Linux aarch64: SKIPPED"
else
echo " ❌ Linux: FAILED"
echo " ❌ Linux aarch64: FAILED"
EXIT_CODE=1
fi

Expand Down
Loading
Loading