Skip to content

Merge pull request #29 from AgentQuantum/fix/heroku-build #71

Merge pull request #29 from AgentQuantum/fix/heroku-build

Merge pull request #29 from AgentQuantum/fix/heroku-build #71

Workflow file for this run

name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
backend:
name: Backend Tests
runs-on: ubuntu-latest
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
working-directory: ./backend
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov flake8 coverage-badge black isort radon
- name: Check code formatting with Black
working-directory: ./backend
run: black --check .
- name: Check import sorting with isort
working-directory: ./backend
run: isort --check-only .
- name: Lint with flake8
working-directory: ./backend
run: |
# Use .flake8 config for all linting rules
flake8 . --count --show-source --statistics
- name: Check code complexity with Radon
working-directory: ./backend
run: |
echo "## πŸ“Š Code Complexity Analysis" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Cyclomatic Complexity" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
radon cc . --min B --show-complexity >> $GITHUB_STEP_SUMMARY 2>&1 || true
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Maintainability Index" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
radon mi . --min B >> $GITHUB_STEP_SUMMARY 2>&1 || true
echo '```' >> $GITHUB_STEP_SUMMARY
# Fail if complexity too high (C or worse)
radon cc . --min C && echo "βœ… Complexity check passed" || (echo "❌ Functions with complexity > 10 found" && exit 1)
- name: Run pytest with 95% branch coverage
working-directory: ./backend
run: |
python -m pytest -v tests \
--cov=. \
--cov-config=.coveragerc \
--cov-branch \
--cov-report=xml \
--cov-report=term-missing \
--cov-fail-under=95
- name: Extract and enforce branch coverage
working-directory: ./backend
run: |
# Extract branch coverage from coverage.xml
BRANCH_COV=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(f\"{float(root.attrib['branch-rate']) * 100:.2f}\")")
LINE_COV=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(f\"{float(root.attrib['line-rate']) * 100:.2f}\")")
echo "BRANCH_COV=$BRANCH_COV" >> $GITHUB_ENV
echo "LINE_COV=$LINE_COV" >> $GITHUB_ENV
echo "Branch Coverage: $BRANCH_COV%"
echo "Line Coverage: $LINE_COV%"
# Fail if branch coverage is below 95%
python -c "import sys; cov = float('$BRANCH_COV'); print(f'Branch coverage: {cov}%'); sys.exit(0 if cov >= 95.0 else 1)"
- name: Coverage Summary
working-directory: ./backend
run: |
BRANCH_COV=${{ env.BRANCH_COV }}
LINE_COV=${{ env.LINE_COV }}
BRANCH_STATUS=$(python -c "import sys; status = 'βœ… PASS' if float('$BRANCH_COV') >= 95.0 else '❌ FAIL'; print(status)")
echo "## πŸ“Š Backend Test Coverage" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Coverage | Status |" >> $GITHUB_STEP_SUMMARY
echo "|--------|----------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| **Branch Coverage** | **$BRANCH_COV%** | $BRANCH_STATUS |" >> $GITHUB_STEP_SUMMARY
echo "| Line Coverage | $LINE_COV% | βœ… |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Requirement:** Branch coverage must be β‰₯ 95%" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### πŸ“‹ Coverage Report" >> $GITHUB_STEP_SUMMARY
echo "View detailed coverage in the [Actions tab](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
- name: Upload coverage XML
uses: actions/upload-artifact@v4
with:
name: coverage-xml
path: backend/coverage.xml
retention-days: 30
frontend:
name: Frontend Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: ./frontend
run: npm ci
- name: Check Prettier formatting
working-directory: ./frontend
run: npm run format:check
- name: Run ESLint
working-directory: ./frontend
run: npm run lint
- name: Run Jest tests with coverage
working-directory: ./frontend
run: npm run test:ci -- --coverageReporters=text --coverageReporters=json-summary
- name: Coverage Summary
working-directory: ./frontend
run: |
echo "## πŸ“Š Frontend Test Coverage" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Debug: show coverage directory contents
ls -la coverage/ 2>/dev/null || echo "No coverage directory"
# Extract coverage from json-summary
if [ -f coverage/coverage-summary.json ]; then
STMT=$(python3 -c "import json; d=json.load(open('coverage/coverage-summary.json')); print(f\"{d['total']['statements']['pct']:.2f}\")")
BRANCH=$(python3 -c "import json; d=json.load(open('coverage/coverage-summary.json')); print(f\"{d['total']['branches']['pct']:.2f}\")")
FUNC=$(python3 -c "import json; d=json.load(open('coverage/coverage-summary.json')); print(f\"{d['total']['functions']['pct']:.2f}\")")
LINES=$(python3 -c "import json; d=json.load(open('coverage/coverage-summary.json')); print(f\"{d['total']['lines']['pct']:.2f}\")")
echo "| Metric | Coverage | Status |" >> $GITHUB_STEP_SUMMARY
echo "|--------|----------|--------|" >> $GITHUB_STEP_SUMMARY
STMT_STATUS=$(python3 -c "print('βœ…' if float('$STMT') >= 95 else '⚠️')")
BRANCH_STATUS=$(python3 -c "print('βœ…' if float('$BRANCH') >= 80 else '⚠️')")
FUNC_STATUS=$(python3 -c "print('βœ…' if float('$FUNC') >= 95 else '⚠️')")
LINES_STATUS=$(python3 -c "print('βœ…' if float('$LINES') >= 95 else '⚠️')")
echo "| **Statements** | **$STMT%** | $STMT_STATUS |" >> $GITHUB_STEP_SUMMARY
echo "| **Branches** | **$BRANCH%** | $BRANCH_STATUS |" >> $GITHUB_STEP_SUMMARY
echo "| Functions | $FUNC% | $FUNC_STATUS |" >> $GITHUB_STEP_SUMMARY
echo "| Lines | $LINES% | $LINES_STATUS |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Thresholds:** Statements β‰₯95%, Branches β‰₯80%, Functions β‰₯95%, Lines β‰₯95%" >> $GITHUB_STEP_SUMMARY
else
echo "⚠️ Coverage summary not found. Running with Jest thresholds only." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Thresholds enforced:** Statements β‰₯95%, Branches β‰₯80%, Functions β‰₯95%, Lines β‰₯95%" >> $GITHUB_STEP_SUMMARY
fi