refactor: Extract duplicate Kscien fetching logic into shared utility module (fixes #11) #113
Workflow file for this run
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/CD Pipeline | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main ] | |
| release: | |
| types: [ published ] | |
| workflow_dispatch: | |
| jobs: | |
| lint-and-type-check: | |
| name: Linting and Type Checking | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e .[dev] | |
| - name: Run ruff linting | |
| run: | | |
| ruff check src/ tests/ | |
| ruff format --check src/ tests/ | |
| - name: Run mypy type checking | |
| run: | | |
| mypy src/ --strict | |
| - name: Check SPDX license identifiers | |
| run: | | |
| python scripts/check-spdx.py | |
| - name: Check logging consistency | |
| run: | | |
| python scripts/check-logging.py | |
| - name: Check example execution | |
| run: | | |
| python scripts/check-examples.py | |
| test: | |
| name: Tests | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e .[dev] | |
| - name: Run tests with coverage | |
| run: | | |
| pytest --cov=src --cov-report=xml --cov-report=html --cov-report=term-missing tests/ | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| - name: Archive coverage reports | |
| uses: actions/upload-artifact@v4 | |
| if: matrix.python-version == '3.11' | |
| with: | |
| name: coverage-report | |
| path: htmlcov/ | |
| security-scan: | |
| name: Security Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e .[dev] | |
| - name: Run bandit security scan | |
| run: | | |
| bandit -r src/ -ll | |
| - name: Run safety check | |
| run: | | |
| safety check | |
| build: | |
| name: Build Package | |
| runs-on: ubuntu-latest | |
| needs: [lint-and-type-check, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install --upgrade build twine | |
| echo "Verifying installations:" | |
| python -m pip show build | |
| python -m pip show twine | |
| python -c "import build; print(f'build version: {build.__version__}')" | |
| - name: Build package | |
| run: | | |
| python -m build | |
| - name: Check package | |
| run: | | |
| twine check dist/* | |
| - name: Archive build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist-packages | |
| path: dist/ | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: [lint-and-type-check, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e .[dev] | |
| - name: Run integration tests | |
| run: | | |
| pytest tests/integration/ -v --tb=short | |
| - name: Test CLI functionality | |
| run: | | |
| # Test basic CLI commands | |
| aletheia-probe --help | |
| aletheia-probe config || true # May fail without config, that's OK | |
| aletheia-probe status || true # May fail without backends, that's OK | |
| cross-platform-integration: | |
| name: Cross-Platform Integration Tests | |
| runs-on: ${{ matrix.os }} | |
| needs: [lint-and-type-check, test] | |
| if: | | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| github.event_name == 'pull_request' | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| python-version: ["3.11"] | |
| fail-fast: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/pip | |
| ~/Library/Caches/pip | |
| ~\AppData\Local\pip\Cache | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Cache assessment data | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.config/aletheia-probe | |
| ~/.aletheia-probe | |
| ~\AppData\Local\aletheia-probe | |
| ~\AppData\Roaming\aletheia-probe | |
| key: ${{ runner.os }}-assessment-data-${{ github.run_number }} | |
| restore-keys: | | |
| ${{ runner.os }}-assessment-data- | |
| # Platform-specific system dependencies | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y unrar git curl | |
| - name: Install system dependencies (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| # Install unar (macOS equivalent of unrar) | |
| brew install unar || echo "RAR tools installation failed" | |
| # git and curl are pre-installed on macOS | |
| - name: Install system dependencies (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| # Install via chocolatey (available on GitHub Actions Windows runners) | |
| choco install unrar -y || echo "unrar installation failed, trying 7zip" | |
| choco install 7zip -y || echo "7zip installation failed" | |
| # git is pre-installed on GitHub Actions Windows runners | |
| - name: Setup Unicode encoding for Windows | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| # Set UTF-8 encoding for Python and console output | |
| echo "PYTHONIOENCODING=utf-8" >> $GITHUB_ENV | |
| echo "PYTHONUTF8=1" >> $GITHUB_ENV | |
| # Set console code page to UTF-8 (Windows only) | |
| chcp 65001 || echo "Could not set UTF-8 code page" | |
| shell: bash | |
| - name: Install Python package | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e . | |
| - name: Validate installation and check status | |
| run: | | |
| aletheia-probe --help | |
| aletheia-probe status || echo "Status check completed with warnings" | |
| - name: Limited data sync for testing | |
| run: | | |
| echo "Starting limited data sync for CI/CD testing..." | |
| # Sync specific backends to keep CI/CD time reasonable (5-7 minutes max) | |
| # Use platform-appropriate timeout command | |
| if command -v timeout >/dev/null 2>&1; then | |
| timeout 300 aletheia-probe sync doaj bealls retraction_watch || echo "Sync completed with timeout/warnings" | |
| elif command -v gtimeout >/dev/null 2>&1; then | |
| gtimeout 300 aletheia-probe sync doaj bealls retraction_watch || echo "Sync completed with timeout/warnings" | |
| else | |
| # No timeout available, rely on GitHub Actions timeout-minutes | |
| aletheia-probe sync doaj bealls retraction_watch || echo "Sync completed with warnings" | |
| fi | |
| shell: bash | |
| timeout-minutes: 8 | |
| - name: Test basic assessment functionality | |
| run: | | |
| echo "Testing basic assessment functionality..." | |
| # Test with well-known legitimate journal | |
| echo "Testing legitimate journal assessment..." | |
| aletheia-probe journal "Nature" --format json || echo "Nature assessment completed with warnings" | |
| # Test with a pattern that might indicate predatory behavior | |
| echo "Testing predatory pattern assessment..." | |
| aletheia-probe journal "International Journal of Advanced Research" --format json || echo "Predatory pattern assessment completed with warnings" | |
| # Test journal status without full assessment | |
| echo "Testing status command..." | |
| aletheia-probe status || echo "Status command completed with warnings" | |
| - name: Test with sample BibTeX data | |
| run: | | |
| echo "Testing BibTeX assessment functionality..." | |
| # Create a sample BibTeX file using echo commands (cross-platform) | |
| echo "@article{nature_test_2024," > sample_test.bib | |
| echo " title={Sample Nature Article}," >> sample_test.bib | |
| echo " author={Test Author}," >> sample_test.bib | |
| echo " journal={Nature}," >> sample_test.bib | |
| echo " year={2024}," >> sample_test.bib | |
| echo " volume={123}," >> sample_test.bib | |
| echo " pages={1-10}" >> sample_test.bib | |
| echo "}" >> sample_test.bib | |
| echo "" >> sample_test.bib | |
| echo "@article{arxiv_test_2024," >> sample_test.bib | |
| echo " title={Sample ArXiv Preprint}," >> sample_test.bib | |
| echo " author={Another Author}," >> sample_test.bib | |
| echo " journal={arXiv preprint}," >> sample_test.bib | |
| echo " year={2024}" >> sample_test.bib | |
| echo "}" >> sample_test.bib | |
| echo "" >> sample_test.bib | |
| echo "@article{ieee_test_2024," >> sample_test.bib | |
| echo " title={Sample IEEE Article}," >> sample_test.bib | |
| echo " author={IEEE Author}," >> sample_test.bib | |
| echo " journal={IEEE Computer}," >> sample_test.bib | |
| echo " year={2024}," >> sample_test.bib | |
| echo " volume={57}," >> sample_test.bib | |
| echo " pages={20-30}" >> sample_test.bib | |
| echo "}" >> sample_test.bib | |
| echo "Created sample_test.bib" | |
| # Test BibTeX assessment | |
| aletheia-probe bibtex sample_test.bib --format json || echo "BibTeX assessment completed with warnings" | |
| # Test that exit codes work properly | |
| aletheia-probe bibtex sample_test.bib || echo "BibTeX exit code test completed" | |
| - name: Test configuration and cache | |
| run: | | |
| echo "Testing configuration and cache functionality..." | |
| # Test config display | |
| aletheia-probe config || echo "Config show completed with warnings" | |
| # Test status (shows cache and backend status) | |
| aletheia-probe status || echo "Status check completed with warnings" | |
| - name: Platform-specific validation | |
| run: | | |
| echo "Running platform-specific validation for ${{ matrix.os }}..." | |
| # Check that all required commands are available | |
| python -c " | |
| import subprocess | |
| import sys | |
| def check_command(cmd): | |
| try: | |
| result = subprocess.run([cmd, '--help' if cmd != 'git' else '--version'], | |
| capture_output=True, timeout=10) | |
| print(f'[OK] {cmd}: Available (exit code {result.returncode})') | |
| return True | |
| except Exception as e: | |
| print(f'[ERROR] {cmd}: Not available - {e}') | |
| return False | |
| commands = ['python', 'git'] | |
| # Check for RAR tools on non-Windows platforms | |
| if '${{ matrix.os }}' == 'macos-latest': | |
| # Try both unar and unrar on macOS | |
| for cmd in ['unar', 'unrar']: | |
| try: | |
| subprocess.run([cmd, '--help'], capture_output=True, timeout=10) | |
| commands.append(cmd) | |
| print(f'[INFO] Using {cmd} for RAR support on macOS') | |
| break | |
| except: | |
| continue | |
| elif '${{ matrix.os }}' == 'ubuntu-latest': | |
| commands.append('unrar') | |
| all_good = all(check_command(cmd) for cmd in commands) | |
| status = 'PASSED' if all_good else 'PARTIAL' | |
| print(f'Platform validation: {status}') | |
| " | |
| - name: Archive test artifacts | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: integration-artifacts-${{ matrix.os }}-py${{ matrix.python-version }} | |
| path: | | |
| sample_test.bib | |
| ~/.config/aletheia-probe/logs/ | |
| ~/.aletheia-probe/logs/ | |
| ~\AppData\Local\aletheia-probe\logs\ | |
| ~\AppData\Roaming\aletheia-probe\logs\ | |
| performance-tests: | |
| name: Performance Tests | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e .[dev] pytest-benchmark | |
| - name: Run performance benchmarks | |
| run: | | |
| pytest tests/ -k "benchmark" --benchmark-only --benchmark-json=benchmark.json || true | |
| - name: Archive benchmark results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: benchmark-results | |
| path: benchmark.json | |
| notify: | |
| name: Notify | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: [lint-and-type-check, test, security-scan, build, integration-tests, cross-platform-integration] | |
| steps: | |
| - name: Notify on success | |
| if: ${{ needs.lint-and-type-check.result == 'success' && needs.test.result == 'success' && needs.security-scan.result == 'success' && needs.build.result == 'success' && needs.cross-platform-integration.result == 'success' }} | |
| run: | | |
| echo "✅ All checks passed!" | |
| - name: Notify on failure | |
| if: ${{ needs.lint-and-type-check.result == 'failure' || needs.test.result == 'failure' || needs.security-scan.result == 'failure' || needs.build.result == 'failure' || needs.cross-platform-integration.result == 'failure' }} | |
| run: | | |
| echo "❌ Some checks failed!" | |
| exit 1 |