| | 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: |
| | |
| | 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: |
| | 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: |
| | 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 |
| |
|
| | |
| | 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 |
| | |
| | |
| | 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 |
| | |
| | |
| | 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: |
| | 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: |
| | 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(/<coverage.*?line-rate="([^"]+)"/); |
| | if (coverageMatch) { |
| | const coveragePercent = Math.round(parseFloat(coverageMatch[1]) * 100); |
| | comment += `\nπ **Test Coverage**: ${coveragePercent}%\n`; |
| | } |
| | } catch (e) { |
| | // Coverage file not available |
| | } |
| | |
| | github.rest.issues.createComment({ |
| | issue_number: context.issue.number, |
| | owner: context.repo.owner, |
| | repo: context.repo.repo, |
| | body: comment |
| | }); |