Skip to content

Feat/selene plugins #544

Feat/selene plugins

Feat/selene plugins #544

Workflow file for this run

name: Python test / linting
env:
TRIGGER_ON_PR_PUSH: true # Set to true to enable triggers on PR pushes
RUSTFLAGS: -C debuginfo=0
RUST_BACKTRACE: 1
PYTHONUTF8: 1
on:
push:
branches: [ "master", "development", "dev" ]
pull_request:
branches: [ "master", "development", "dev" ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
python-test:
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Free Disk Space (Ubuntu)
if: runner.os == 'Linux'
uses: jlumbroso/free-disk-space@main
with:
# Remove Android tools (saves ~14GB)
android: true
# Remove .NET runtime (saves ~2.7GB)
dotnet: true
# Remove Haskell runtime
haskell: true
# Don't remove large packages - may include libffi and other build deps
large-packages: false
# Remove Docker images (saves space)
docker-images: true
# Keep tool-cache as we may need some tools
tool-cache: false
# Remove swap storage (saves ~4GB)
swap-storage: true
- name: Free Disk Space (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
Write-Host "Disk space before cleanup:"
Get-PSDrive C | Select-Object Used,Free
# Remove Android SDK (saves ~9GB)
Write-Host "Removing Android SDK..."
Remove-Item -Path "C:\Android" -Recurse -Force -ErrorAction SilentlyContinue
# Remove .NET runtime and libraries (saves ~2GB)
Write-Host "Removing .NET..."
Remove-Item -Path "C:\Program Files\dotnet" -Recurse -Force -ErrorAction SilentlyContinue
# Remove CodeQL (saves ~5GB)
Write-Host "Removing CodeQL..."
Remove-Item -Path "C:\hostedtoolcache\CodeQL" -Recurse -Force -ErrorAction SilentlyContinue
# Remove large packages
Write-Host "Removing large packages..."
Remove-Item -Path "C:\ProgramData\chocolatey" -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "Disk space after cleanup:"
Get-PSDrive C | Select-Object Used,Free
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Set up Visual Studio environment on Windows
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- name: Set up Rust
run: rustup show
- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
workspaces: python/pecos-rslib
- name: Install LLVM 14.0.6 using pecos-llvm (Unix)
if: runner.os != 'Windows'
run: |
echo "Installing LLVM using pecos-llvm-utils..."
cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- install
echo "Setting LLVM environment variables..."
export PECOS_LLVM=$(cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- find 2>/dev/null)
export LLVM_SYS_140_PREFIX="$PECOS_LLVM"
echo "PECOS_LLVM=$PECOS_LLVM" >> $GITHUB_ENV
echo "LLVM_SYS_140_PREFIX=$LLVM_SYS_140_PREFIX" >> $GITHUB_ENV
echo "Verifying LLVM installation..."
cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- check
- name: Install LLVM 14.0.6 using pecos-llvm (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
Write-Host "Installing LLVM using pecos-llvm-utils..."
cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- install
Write-Host "Setting LLVM environment variables..."
$env:PECOS_LLVM = (cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- find 2>$null)
$env:LLVM_SYS_140_PREFIX = $env:PECOS_LLVM
"PECOS_LLVM=$env:PECOS_LLVM" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"LLVM_SYS_140_PREFIX=$env:LLVM_SYS_140_PREFIX" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Write-Host "Verifying LLVM installation..."
cargo run -p pecos-llvm-utils --bin pecos-llvm --release -- check
- name: Build and test PECOS (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
# Ensure LLVM environment variable is available
# If LLVM_SYS_140_PREFIX is not set but LLVM_PATH is, use LLVM_PATH
if (-not $env:LLVM_SYS_140_PREFIX -and $env:LLVM_PATH) {
Write-Host "Setting LLVM_SYS_140_PREFIX from LLVM_PATH"
$env:LLVM_SYS_140_PREFIX = $env:LLVM_PATH
}
# Double check it's really set
if (-not $env:LLVM_SYS_140_PREFIX) {
Write-Error "LLVM_SYS_140_PREFIX is still not set!"
exit 1
}
# Export to GitHub env for make/maturin to use (in case it wasn't already)
"LLVM_SYS_140_PREFIX=$env:LLVM_SYS_140_PREFIX" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Also ensure LLVM bin is in PATH
$llvmBinDir = Join-Path -Path $env:LLVM_SYS_140_PREFIX -ChildPath "bin"
if (Test-Path $llvmBinDir) {
# Update PATH for current session (so pytest can find llvm-as)
$env:PATH = "$llvmBinDir;$env:PATH"
# Update PATH for future steps
"$llvmBinDir" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
}
# Find MSVC link.exe and create cargo config
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vsPath = & $vsWhere -latest -property installationPath
$linkPath = Get-ChildItem -Path "$vsPath\VC\Tools\MSVC" -Recurse -Filter "link.exe" |
Where-Object { $_.FullName -like "*\bin\Hostx64\x64\*" } |
Select-Object -First 1 -ExpandProperty FullName
if ($linkPath) {
# Create .cargo directory and config in multiple locations
# Create in root
New-Item -ItemType Directory -Force -Path .cargo | Out-Null
# Create config with escaped path and LLVM environment variable
$escapedPath = $linkPath.Replace('\', '/')
$escapedLLVMPath = $env:LLVM_SYS_140_PREFIX.Replace('\', '/')
$configContent = "[target.x86_64-pc-windows-msvc]`nlinker = `"$escapedPath`"`n`n[env]`nLLVM_SYS_140_PREFIX = `"$escapedLLVMPath`""
$configContent | Out-File -FilePath ".cargo\config.toml" -Encoding UTF8
# Also create in pecos-rslib directory
New-Item -ItemType Directory -Force -Path "python\pecos-rslib\.cargo" | Out-Null
$configContent | Out-File -FilePath "python\pecos-rslib\.cargo\config.toml" -Encoding UTF8
# And in the rust subdirectory
New-Item -ItemType Directory -Force -Path "python\pecos-rslib\rust\.cargo" | Out-Null
$configContent | Out-File -FilePath "python\pecos-rslib\rust\.cargo\config.toml" -Encoding UTF8
# Also create in user's cargo home directory as a fallback
$cargoHome = if ($env:CARGO_HOME) { $env:CARGO_HOME } else { "$env:USERPROFILE\.cargo" }
New-Item -ItemType Directory -Force -Path $cargoHome | Out-Null
# For user cargo config, we need to be careful not to overwrite existing content
if (Test-Path "$cargoHome\config.toml") {
# Add our content to existing file
"`n$configContent" | Out-File -FilePath "$cargoHome\config.toml" -Encoding UTF8 -Append
} else {
# Create new file
$configContent | Out-File -FilePath "$cargoHome\config.toml" -Encoding UTF8
}
} else {
Write-Error "Could not find MSVC link.exe"
exit 1
}
# Ensure LLVM environment variable is exported for subprocess
[System.Environment]::SetEnvironmentVariable("LLVM_SYS_140_PREFIX", $env:LLVM_SYS_140_PREFIX, "User")
[System.Environment]::SetEnvironmentVariable("LLVM_SYS_140_PREFIX", $env:LLVM_SYS_140_PREFIX, "Process")
# Also set it as a regular environment variable one more time
$env:LLVM_SYS_140_PREFIX = $env:LLVM_SYS_140_PREFIX
# Build and test
make build-debug
make pytest-all
- name: Build and test PECOS (non-Windows)
if: runner.os != 'Windows'
run: |
# On macOS, set up minimal environment for matplotlib compatibility
if [[ "${{ runner.os }}" == "macOS" ]]; then
# Set matplotlib backend to avoid GUI issues
export MPLBACKEND=Agg
export MATPLOTLIB_INTERACTIVE=false
# Try to fix matplotlib segfault by limiting threading
export OPENBLAS_NUM_THREADS=1
export MKL_NUM_THREADS=1
export NUMEXPR_NUM_THREADS=1
export OMP_NUM_THREADS=1
# Force matplotlib to use bundled libraries instead of system ones
export MPLCONFIGDIR=$PWD/.matplotlib
mkdir -p $MPLCONFIGDIR
# CRITICAL: Prevent Homebrew library paths from being used during linking
# This fixes the "@rpath/libunwind.1.dylib" runtime error on macOS
# Reference: https://github.com/rust-lang/rust/issues/135372
#
# The issue: When LIBRARY_PATH or similar environment variables include
# Homebrew paths (like /usr/local/lib or /opt/homebrew/lib), the linker
# finds Homebrew's libunwind and creates @rpath references that fail at runtime.
#
# The solution: Clear these variables so the linker ONLY uses system libraries
# from /usr/lib (which are in the dyld shared cache).
unset LIBRARY_PATH
unset LD_LIBRARY_PATH
unset DYLD_LIBRARY_PATH
unset DYLD_FALLBACK_LIBRARY_PATH
# Also prevent pkg-config from finding Homebrew packages
unset PKG_CONFIG_PATH
# Set explicit library path to ONLY include system directories
export LIBRARY_PATH=/usr/lib
echo "macOS environment configured for build (LIBRARY_PATH=/usr/lib)"
fi
# Build the project
make build-debug
# After build, verify the extension module on macOS
if [[ "${{ runner.os }}" == "macOS" ]]; then
EXT_MODULE=$(find .venv/lib -name "pecos_rslib*.so" 2>/dev/null | head -1)
if [ -n "$EXT_MODULE" ]; then
if otool -L "$EXT_MODULE" | grep -q "@rpath/libunwind"; then
echo "ERROR: Extension has @rpath/libunwind reference"
otool -L "$EXT_MODULE"
exit 1
fi
echo "macOS extension module built successfully"
fi
fi
make pytest-all
- name: Run linting
run: |
# Run all linting checks
make lint # Rust checks + Python pre-commit