This repository was archived by the owner on Feb 1, 2026. It is now read-only.
feat: Migrate semantic search from sentence-transformers to Ollama #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| jobs: | |
| install-check: | |
| name: Install Check (Frozen) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libsqlite3-dev | |
| - name: Verify frozen install | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt --no-deps --require-hashes 2>/dev/null || pip install -r requirements.txt | |
| pip install pytest pytest-asyncio | |
| - name: Quick import test | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| run: | | |
| python -c "from query.query import QuerySystem; print('Imports OK')" | |
| python-tests: | |
| name: Python Tests (${{ matrix.os }}, Py ${{ matrix.python-version }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest] | |
| python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] | |
| include: | |
| # macOS and Windows - latest Python only for speed | |
| - os: macos-latest | |
| python-version: "3.11" | |
| - os: windows-latest | |
| python-version: "3.11" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: "pip" | |
| - name: Install system dependencies (Ubuntu) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libsqlite3-dev | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip setuptools wheel | |
| pip install -r requirements.txt | |
| pip install pytest pytest-cov pytest-asyncio | |
| - name: Run tests with coverage | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| run: | | |
| pytest tests/ -v --cov=src --cov-report=xml --cov-report=term -k "not stress and not destructive" | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: ./coverage.xml | |
| flags: python | |
| name: python-${{ matrix.python-version }}-${{ matrix.os }} | |
| fail_ci_if_error: false | |
| # Platform-specific path and permission tests | |
| platform-edge-cases: | |
| name: Platform Edge Cases (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: "pip" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pytest | |
| - name: Test path handling | |
| shell: python | |
| run: | | |
| import os | |
| import tempfile | |
| from pathlib import Path | |
| # Test path operations work on all platforms | |
| test_dir = Path(tempfile.gettempdir()) / 'elf_test' | |
| test_dir.mkdir(exist_ok=True) | |
| test_file = test_dir / 'nested' / 'deep' / 'file.txt' | |
| test_file.parent.mkdir(parents=True, exist_ok=True) | |
| test_file.write_text('test') | |
| assert test_file.exists(), 'Path creation failed' | |
| assert test_file.read_text() == 'test', 'Path read failed' | |
| print('Path handling OK') | |
| # Test home directory detection | |
| home = Path.home() | |
| assert home.exists(), 'Home directory detection failed' | |
| print(f'Home directory: {home}') | |
| print('All path tests passed') | |
| - name: Test SQLite behavior | |
| shell: python | |
| run: | | |
| import sqlite3 | |
| import tempfile | |
| import os | |
| from pathlib import Path | |
| db_path = Path(tempfile.gettempdir()) / 'elf_sqlite_test.db' | |
| # Test basic operations | |
| conn = sqlite3.connect(str(db_path)) | |
| conn.execute('CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT)') | |
| conn.execute("INSERT INTO test VALUES (1, 'test')") | |
| conn.commit() | |
| conn.close() | |
| # Test WAL mode (platform-specific behavior) | |
| conn = sqlite3.connect(str(db_path)) | |
| conn.execute('PRAGMA journal_mode=WAL') | |
| journal_mode = conn.execute('PRAGMA journal_mode').fetchone()[0] | |
| print(f'Journal mode: {journal_mode}') | |
| # Verify WAL file created on most platforms | |
| conn.close() | |
| # Cleanup | |
| db_path.unlink(missing_ok=True) | |
| wal_path = db_path.parent / (db_path.name + '-wal') | |
| shm_path = db_path.parent / (db_path.name + '-shm') | |
| wal_path.unlink(missing_ok=True) | |
| shm_path.unlink(missing_ok=True) | |
| print('SQLite tests passed') | |
| - name: Test file permissions (Unix only) | |
| if: runner.os != 'Windows' | |
| shell: python | |
| run: | | |
| import os | |
| import tempfile | |
| import stat | |
| from pathlib import Path | |
| test_file = Path(tempfile.gettempdir()) / 'elf_perm_test.txt' | |
| test_file.write_text('secret') | |
| # Test permission setting | |
| os.chmod(test_file, 0o600) | |
| mode = stat.S_IMODE(test_file.stat().st_mode) | |
| assert mode == 0o600, f'Permission mismatch: {oct(mode)}' | |
| test_file.unlink() | |
| print('Permission tests passed') | |
| code-quality: | |
| name: Code Quality | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install ruff mypy | |
| - name: Run Ruff format check | |
| run: | | |
| ruff format --check src/ tests/ scripts/ || true | |
| - name: Run Ruff lint | |
| run: | | |
| ruff check src/ tests/ scripts/ || true | |
| - name: Run MyPy type checking | |
| run: | | |
| mypy src/ --ignore-missing-imports --pretty || true | |
| secrets-scan: | |
| name: Secrets Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install detect-secrets | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install detect-secrets==1.5.0 | |
| - name: Create baseline if missing | |
| run: | | |
| if [ ! -f .secrets.baseline ]; then | |
| echo '{"version": "1.5.0", "plugins_used": [], "filters_used": [], "results": {}, "generated_at": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}' > .secrets.baseline | |
| fi | |
| - name: Scan for secrets | |
| run: | | |
| detect-secrets scan --baseline .secrets.baseline --all-files || true | |
| - name: Check for new secrets | |
| run: | | |
| if ! detect-secrets scan --baseline .secrets.baseline --all-files 2>/dev/null; then | |
| echo "::warning::Potential secrets detected. Review the output above." | |
| # Don't fail the build, just warn | |
| fi | |
| shellcheck: | |
| name: Shell Script Linting | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Run ShellCheck | |
| uses: ludeeus/action-shellcheck@master | |
| with: | |
| scandir: "./scripts" | |
| severity: error | |
| ci-summary: | |
| name: CI Summary | |
| runs-on: ubuntu-latest | |
| needs: [install-check, python-tests, platform-edge-cases, code-quality, secrets-scan, shellcheck] | |
| if: always() | |
| steps: | |
| - name: Summary | |
| run: | | |
| echo "## CI Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Job | Result |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Install Check | ${{ needs.install-check.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Python Tests | ${{ needs.python-tests.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Platform Edge Cases | ${{ needs.platform-edge-cases.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Code Quality | ${{ needs.code-quality.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Secrets Scan | ${{ needs.secrets-scan.result }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| ShellCheck | ${{ needs.shellcheck.result }} |" >> $GITHUB_STEP_SUMMARY | |
| if [[ "${{ needs.install-check.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.python-tests.result }}" == "failure" ]] || \ | |
| [[ "${{ needs.platform-edge-cases.result }}" == "failure" ]]; then | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "❌ **CI Failed**" >> $GITHUB_STEP_SUMMARY | |
| exit 1 | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ **All Required Checks Passed**" >> $GITHUB_STEP_SUMMARY |