Add comprehensive test suite and CI/CD pipeline for PR checks #4
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
| # CI/CD Pipeline for Weather API | |
| # This workflow runs automated tests and checks on all pull requests | |
| # to ensure code quality before merging. | |
| name: CI Tests | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| types: [opened, synchronize, reopened] | |
| # Cancel in-progress runs for the same PR/branch | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Run Tests | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| matrix: | |
| python-version: ['3.10', '3.11', '3.12'] | |
| fail-fast: false | |
| steps: | |
| - name: Checkout code | |
| 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 dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Run tests with coverage | |
| run: | | |
| python -m pytest tests/ -v --cov=. --cov-report=xml --cov-report=term-missing --tb=short | |
| env: | |
| PYTHONPATH: ${{ github.workspace }} | |
| - name: Upload coverage reports | |
| uses: codecov/codecov-action@v4 | |
| if: matrix.python-version == '3.12' | |
| with: | |
| file: ./coverage.xml | |
| fail_ci_if_error: false | |
| continue-on-error: true | |
| lint: | |
| name: Code Quality Checks | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: 'pip' | |
| - name: Install linting tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install ruff | |
| - name: Run Ruff linter | |
| run: | | |
| ruff check . --output-format=github || true | |
| continue-on-error: true | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: 'pip' | |
| - name: Install dependencies and security scanner | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install bandit safety | |
| - name: Run Bandit security scanner | |
| run: | | |
| bandit -r . -ll -x tests/ || true | |
| continue-on-error: true | |
| - name: Check dependencies for vulnerabilities | |
| run: | | |
| pip freeze | safety check --stdin || true | |
| continue-on-error: true | |
| api-test: | |
| name: API Integration Tests | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| needs: test | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Start server in background | |
| run: | | |
| python -m uvicorn app:app --host 0.0.0.0 --port 8000 & | |
| sleep 5 | |
| - name: Test API health endpoint | |
| run: | | |
| curl -f http://localhost:8000/api-test || exit 1 | |
| - name: Test API docs endpoint | |
| run: | | |
| curl -f http://localhost:8000/docs || exit 1 | |
| # Summary job that depends on all other jobs | |
| check-status: | |
| name: PR Check Summary | |
| runs-on: ubuntu-latest | |
| permissions: {} | |
| needs: [test, lint, security, api-test] | |
| if: always() | |
| steps: | |
| - name: Check job results | |
| run: | | |
| echo "Test job: ${{ needs.test.result }}" | |
| echo "Lint job: ${{ needs.lint.result }}" | |
| echo "Security job: ${{ needs.security.result }}" | |
| echo "API test job: ${{ needs.api-test.result }}" | |
| if [ "${{ needs.test.result }}" != "success" ]; then | |
| echo "❌ Tests failed! PR should not be merged." | |
| exit 1 | |
| fi | |
| echo "✅ All critical checks passed!" |