# SONARIS Test Suite # Runs on every push to any branch and every PR targeting main. name: SONARIS Test Suite on: push: branches: ["**"] # Catch all branches, not just main pull_request: branches: [main] jobs: test: name: Run pytest runs-on: ubuntu-latest steps: # Step 1: Pull the full repository into the runner - name: Checkout repository uses: actions/checkout@v4 # Step 2: Set up Python 3.11. # Local development uses 3.14 on Windows, but 3.11 has stable wheel # support on Ubuntu CI runners. All SONARIS dependencies install cleanly # on 3.11 without C++ compiler errors. - name: Set up Python 3.11 uses: actions/setup-python@v5 with: python-version: "3.11" # Step 3: Cache pip's download cache so repeated runs don't re-download # packages. Cache key includes the OS and the hash of requirements.txt # so the cache invalidates automatically when dependencies change. - name: Cache pip dependencies uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- # Step 4: Install all project dependencies from requirements.txt. # Upgrade pip first to avoid resolver warnings on older bundled versions. - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov # Step 5: Run pytest. # --tb=short keeps failure output readable without being verbose. # --cov generates a coverage report for the modules/ package. # The || true at the end ensures the step exits 0 even when no test # files are found, so the CI badge stays green during early development. - name: Run tests run: | pytest tests/ -v --tb=short --cov=modules --cov-report=xml \ || ([ $? -eq 5 ] && echo "No tests collected, exiting cleanly." && exit 0) # Step 6: Upload the XML coverage report as a workflow artifact so it # can be retrieved and fed into a coverage service (e.g. Codecov) later. - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage.xml if-no-files-found: ignore # Don't fail if no coverage file was generated