Nikhil Pravin Pise
feat: implement comprehensive improvement plan (Phases 1-5)
e98cc10
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
PYTHON_VERSION: "3.11"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# ===========================================================================
# Linting - Fast feedback on code style
# ===========================================================================
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Run ruff linter
run: uv run ruff check . --output-format=github
- name: Check ruff formatting
run: uv run ruff format --check .
# ===========================================================================
# Type Checking - Static analysis with mypy
# ===========================================================================
typecheck:
name: Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Run mypy
run: uv run mypy src/ --ignore-missing-imports
# ===========================================================================
# Unit Tests - Fast, isolated tests
# ===========================================================================
test-unit:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Run unit tests
run: |
uv run pytest tests/unit/ -v \
--cov=src \
--cov-report=xml \
--cov-report=term-missing \
--tb=short
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: coverage.xml
fail_ci_if_error: false
verbose: true
# ===========================================================================
# Integration Tests - Tests with mocked external services
# ===========================================================================
test-integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: [lint, typecheck]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Run integration tests
run: |
uv run pytest tests/integration/ -v \
--tb=short \
-m "not slow"
# ===========================================================================
# E2E Tests - Full browser-based tests with Playwright
# ===========================================================================
test-e2e:
name: E2E Tests
runs-on: ubuntu-latest
needs: [test-integration]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Install Playwright browsers
run: uv run playwright install chromium --with-deps
- name: Start Gradio app in background
run: |
uv run python app.py &
sleep 15 # Wait for server to start
env:
GRADIO_SERVER_PORT: 7860
- name: Run E2E tests
run: |
uv run pytest tests/e2e/ -v \
--tb=short \
-m "not slow"
# ===========================================================================
# Security Scanning
# ===========================================================================
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync --dev
- name: Run pip-audit (vulnerability scan)
run: uv run pip-audit --strict
continue-on-error: true
- name: Run bandit (security linter)
run: uv run bandit -r src/ -c pyproject.toml
# ===========================================================================
# Docker Build Test
# ===========================================================================
docker:
name: Docker Build
runs-on: ubuntu-latest
needs: [test-unit]
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
run: |
docker build \
--tag medium-mcp:test \
--cache-from type=gha \
--cache-to type=gha,mode=max \
.
- name: Test Docker image
run: |
docker run --rm medium-mcp:test \
python -c "from src.service import ScraperService; print('Import OK')"
# ===========================================================================
# All Tests Passed Gate
# ===========================================================================
all-tests-pass:
name: All Tests Pass
runs-on: ubuntu-latest
needs: [lint, typecheck, test-unit, test-integration, security]
if: always()
steps:
- name: Check all jobs passed
run: |
if [ "${{ needs.lint.result }}" != "success" ] || \
[ "${{ needs.typecheck.result }}" != "success" ] || \
[ "${{ needs.test-unit.result }}" != "success" ] || \
[ "${{ needs.test-integration.result }}" != "success" ]; then
echo "One or more required jobs failed"
exit 1
fi
echo "All required jobs passed!"