name: Pull Request Checks on: pull_request: branches: [ main, develop ] push: branches: [ develop ] env: AWS_REGION: us-west-2 S3_BUCKET: fredmlv1 LAMBDA_FUNCTION: fred-ml-processor PYTHON_VERSION: '3.9' jobs: # Code Quality Checks quality: name: ๐Ÿ” Code Quality runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Cache pip dependencies uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install black flake8 mypy isort - name: Check code formatting run: | echo "๐ŸŽจ Checking code formatting..." black --check --diff . - name: Run linting run: | echo "๐Ÿ” Running linting..." flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics - name: Check import sorting run: | echo "๐Ÿ“ฆ Checking import sorting..." isort --check-only --diff . - name: Run type checking run: | echo "๐Ÿ” Running type checking..." mypy lambda/ frontend/ src/ --ignore-missing-imports # Unit Tests unit-tests: name: ๐Ÿงช Unit Tests runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov - name: Run unit tests run: | echo "๐Ÿงช Running unit tests..." pytest tests/unit/ -v --cov=lambda --cov=frontend --cov-report=xml --cov-report=term-missing - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: file: ./coverage.xml flags: unittests name: codecov-umbrella fail_ci_if_error: false # Security Scan security: name: ๐Ÿ”’ Security Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Bandit security scan run: | echo "๐Ÿ”’ Running security scan..." pip install bandit bandit -r lambda/ frontend/ src/ -f json -o bandit-report.json || true - name: Upload security report uses: actions/upload-artifact@v3 if: always() with: name: security-report path: bandit-report.json # Dependency Check dependencies: name: ๐Ÿ“ฆ Dependency Check runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Check for outdated dependencies run: | echo "๐Ÿ“ฆ Checking for outdated dependencies..." pip install pip-check-updates pcu --version || echo "pip-check-updates not available" - name: Check for security vulnerabilities run: | echo "๐Ÿ”’ Checking for security vulnerabilities..." pip install safety safety check || true # Documentation Check docs: name: ๐Ÿ“š Documentation Check runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Check README run: | echo "๐Ÿ“š Checking documentation..." if [ ! -f "README.md" ]; then echo "โŒ README.md is missing" exit 1 fi # Check for required sections required_sections=("## ๐Ÿ—๏ธ Architecture" "## ๐Ÿš€ Features" "## ๐Ÿ› ๏ธ Setup") for section in "${required_sections[@]}"; do if ! grep -q "$section" README.md; then echo "โŒ Missing required section: $section" exit 1 fi done echo "โœ… Documentation check passed" - name: Check deployment docs run: | if [ ! -f "docs/deployment/streamlit-cloud.md" ]; then echo "โŒ Streamlit Cloud deployment guide is missing" exit 1 fi echo "โœ… Deployment documentation exists" # Build Test build-test: name: ๐Ÿ—๏ธ Build Test runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Test Lambda package creation run: | echo "๐Ÿ“ฆ Testing Lambda package creation..." cd lambda pip install -r requirements.txt -t . zip -r ../lambda-test-package.zip . cd .. if [ -f "lambda-test-package.zip" ]; then echo "โœ… Lambda package created successfully" ls -la lambda-test-package.zip else echo "โŒ Lambda package creation failed" exit 1 fi - name: Test Streamlit app import run: | echo "๐ŸŽจ Testing Streamlit app imports..." python -c "import sys; sys.path.append('frontend'); from app import load_config, init_aws_clients; print('โœ… Streamlit app imports successfully')" # Comment Results comment: name: ๐Ÿ’ฌ Comment Results runs-on: ubuntu-latest needs: [quality, unit-tests, security, dependencies, docs, build-test] if: github.event_name == 'pull_request' steps: - name: Checkout code uses: actions/checkout@v4 - name: Download test results uses: actions/download-artifact@v3 with: name: test-results - name: Create PR comment uses: actions/github-script@v7 with: script: | const fs = require('fs'); let comment = '## ๐Ÿงช Pull Request Test Results\n\n'; // Check job results const jobs = ['quality', 'unit-tests', 'security', 'dependencies', 'docs', 'build-test']; let passed = 0; let total = jobs.length; for (const job of jobs) { const result = context.payload.workflow_run?.conclusion || 'unknown'; const status = result === 'success' ? 'โœ…' : 'โŒ'; comment += `${status} **${job}**: ${result}\n`; if (result === 'success') passed++; } comment += `\n**Summary**: ${passed}/${total} checks passed\n\n`; if (passed === total) { comment += '๐ŸŽ‰ All checks passed! This PR is ready for review.\n'; } else { comment += 'โš ๏ธ Some checks failed. Please review and fix the issues.\n'; } // Add test coverage if available try { const coverage = fs.readFileSync('coverage.xml', 'utf8'); const coverageMatch = coverage.match(/