feat: Implement response caching enhancement (Task 2) #919
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: Tests | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| checks: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Test on Python ${{ matrix.python-version }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.11", "3.12"] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pytest pytest-asyncio pytest-cov pytest-xdist | |
| continue-on-error: false | |
| - name: List test files | |
| run: | | |
| echo "Available test files:" | |
| find tests -name "test_*.py" -type f | head -20 | |
| echo "Total test files:" | |
| find tests -name "test_*.py" -type f | wc -l | |
| - name: Run tests with coverage (Codecov format) | |
| run: | | |
| pytest tests/ \ | |
| --cov=backend \ | |
| --cov-branch \ | |
| --cov-report=xml \ | |
| --cov-report=term \ | |
| --cov-report=html \ | |
| --junit-xml=junit.xml \ | |
| -v \ | |
| --tb=short \ | |
| --maxfail=10 | |
| env: | |
| ENVIRONMENT: test | |
| DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY || 'test_key' }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY || 'test_key' }} | |
| PYTHONPATH: ${{ github.workspace }} | |
| continue-on-error: true | |
| - name: Verify coverage.xml was created | |
| run: | | |
| if [ -f coverage.xml ]; then | |
| echo "✅ coverage.xml exists" | |
| ls -lh coverage.xml | |
| echo "First 20 lines of coverage.xml:" | |
| head -20 coverage.xml | |
| else | |
| echo "❌ coverage.xml not found!" | |
| echo "Listing files in current directory:" | |
| ls -la | |
| echo "Listing files in tests directory:" | |
| ls -la tests/ | head -10 | |
| exit 1 | |
| fi | |
| continue-on-error: true | |
| - name: Upload coverage to Codecov | |
| if: hashFiles('coverage.xml') != '' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| continue-on-error: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v6 | |
| if: always() | |
| with: | |
| name: test-results-${{ matrix.python-version }} | |
| path: | | |
| junit.xml | |
| htmlcov/ | |
| coverage.xml | |
| retention-days: 7 | |
| if-no-files-found: ignore | |
| - name: Publish test results | |
| uses: EnricoMi/publish-unit-test-result-action@v2 | |
| if: always() | |
| with: | |
| files: junit.xml | |
| check_name: "Test Results (Python ${{ matrix.python-version }})" | |
| comment_mode: always | |
| report_individual_runs: true | |
| continue-on-error: true | |
| docker-build: | |
| name: Docker Build (no push) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image (CHROMA_WARMUP=false) | |
| run: | | |
| docker build \ | |
| --build-arg CHROMA_WARMUP=false \ | |
| -t stillme-api:ci \ | |
| . | |
| - name: Build Docker image (CHROMA_WARMUP=true) | |
| run: | | |
| docker build \ | |
| --build-arg CHROMA_WARMUP=true \ | |
| -t stillme-api:ci-warmup \ | |
| . | |
| continue-on-error: true # Warmup may fail, but build should still work | |
| - name: Smoke test built image | |
| run: | | |
| # Start container in background | |
| docker run -d \ | |
| --name stillme-test \ | |
| -p 8000:8000 \ | |
| -e PORT=8000 \ | |
| -e ENVIRONMENT=test \ | |
| stillme-api:ci | |
| # Wait for server to start | |
| echo "Waiting for server to start..." | |
| sleep 15 | |
| # Test /health endpoint | |
| for i in {1..10}; do | |
| if curl -f http://localhost:8000/health > /dev/null 2>&1; then | |
| echo "✅ /health endpoint returned 200 OK" | |
| curl -i http://localhost:8000/health | |
| break | |
| fi | |
| echo "Waiting for /health endpoint... ($i/10)" | |
| sleep 2 | |
| done | |
| # Clean up | |
| docker stop stillme-test || true | |
| docker rm stillme-test || true | |
| continue-on-error: true # Smoke test is optional | |
| smoke-test: | |
| name: Smoke Test (Health & Ready Endpoints) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pytest httpx | |
| - name: Start server in background | |
| run: | | |
| export PORT=8000 | |
| python start_backend.py & | |
| SERVER_PID=$! | |
| echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV | |
| # Wait for server to start | |
| sleep 10 | |
| env: | |
| ENVIRONMENT: test | |
| PYTHONPATH: ${{ github.workspace }} | |
| DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY || 'test_key' }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY || 'test_key' }} | |
| - name: Test /health endpoint (liveness) | |
| run: | | |
| for i in {1..30}; do | |
| if curl -f http://localhost:8000/health > /dev/null 2>&1; then | |
| echo "✅ /health endpoint returned 200 OK" | |
| curl -i http://localhost:8000/health | |
| exit 0 | |
| fi | |
| echo "Waiting for /health endpoint... ($i/30)" | |
| sleep 2 | |
| done | |
| echo "❌ /health endpoint did not return 200 after 60 seconds" | |
| exit 1 | |
| - name: Test /ready endpoint (readiness) | |
| run: | | |
| response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/ready) | |
| echo "Response code: $response" | |
| if [ "$response" = "200" ] || [ "$response" = "503" ]; then | |
| echo "✅ /ready endpoint returned $response (expected 200 or 503)" | |
| curl -i http://localhost:8000/ready | |
| else | |
| echo "❌ /ready endpoint returned unexpected status: $response" | |
| exit 1 | |
| fi | |
| - name: Stop server | |
| if: always() | |
| run: | | |
| if [ -n "$SERVER_PID" ]; then | |
| kill $SERVER_PID || true | |
| fi | |
| pkill -f "python start_backend.py" || true | |
| coverage: | |
| name: Coverage Report | |
| runs-on: ubuntu-latest | |
| needs: test | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pytest pytest-asyncio pytest-cov | |
| - name: Generate coverage report | |
| run: | | |
| pytest tests/ \ | |
| --cov=backend \ | |
| --cov-branch \ | |
| --cov-report=term \ | |
| --cov-report=html \ | |
| -v | |
| env: | |
| ENVIRONMENT: test | |
| PYTHONPATH: ${{ github.workspace }} | |
| - name: Comment PR with coverage | |
| uses: py-cov-action/python-coverage-comment-action@v3 | |
| if: github.event_name == 'pull_request' | |
| with: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| MINIMUM_GREEN: 40 | |
| MINIMUM_ORANGE: 30 | |