geo/.github/workflows/ci.yml

228 lines
6.4 KiB
YAML

name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
backend-lint-test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: geo_test
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7
ports: ['6379:6379']
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
cd backend
pip install -r requirements.txt
pip install ruff pytest-cov
- name: Lint (ruff)
run: cd backend && ruff check app/
- name: Type check (optional)
run: cd backend && ruff check app/ --select=E,W
continue-on-error: true
- name: Run tests
env:
DATABASE_URL: postgresql+asyncpg://test:test@localhost:5432/geo_test
REDIS_URL: redis://localhost:6379/0
JWT_SECRET: test-secret-key-minimum-32-characters-long
ENVIRONMENT: test
run: |
cd backend
pytest tests/ -v --tb=short
- name: Security scan (bandit)
run: |
pip install bandit
cd backend
bandit -r app/ -f json -o bandit-report.json || true
bandit -r app/ -f txt || true
continue-on-error: true
- name: Upload bandit report
if: always()
uses: actions/upload-artifact@v4
with:
name: bandit-report
path: backend/bandit-report.json
retention-days: 7
- name: Performance baseline
env:
DATABASE_URL: postgresql+asyncpg://test:test@localhost:5432/geo_test
REDIS_URL: redis://localhost:6379/0
JWT_SECRET: test-secret-key-minimum-32-characters-long
ENVIRONMENT: test
run: |
cd backend
START_TIME=$(date +%s)
pytest tests/ -v --tb=short -q 2>&1 | tee test-output.txt
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
echo "Backend test duration: ${DURATION}s" >> $GITHUB_STEP_SUMMARY
echo "## Performance Baseline" >> $GITHUB_STEP_SUMMARY
echo "- Backend test suite duration: **${DURATION}s**" >> $GITHUB_STEP_SUMMARY
continue-on-error: true
frontend-lint-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: cd frontend && npm ci
- name: Lint (ESLint)
run: cd frontend && npm run lint
- name: Type check
run: cd frontend && npx tsc --noEmit
- name: Unit tests
run: cd frontend && npm run test:ci
- name: Security audit (npm audit)
run: cd frontend && npm audit --audit-level=moderate || true
continue-on-error: true
docker-build:
runs-on: ubuntu-latest
needs: [backend-lint-test, frontend-lint-test]
steps:
- uses: actions/checkout@v4
- name: Build backend image
run: docker build -t geo-backend:test ./backend
- name: Build frontend image
run: docker build -t geo-frontend:test ./frontend
e2e-test:
runs-on: ubuntu-latest
needs: [backend-lint-test, frontend-lint-test]
steps:
- uses: actions/checkout@v4
- name: Create .env for Docker Compose
run: |
cat > .env << 'EOF'
POSTGRES_PASSWORD=geo_e2e_test_2026
REDIS_PASSWORD=geo_redis_e2e_2026
JWT_SECRET=e2e-test-secret-key-minimum-32-characters-long
ENVIRONMENT=test
DEEPSEEK_API_KEY=${{ secrets.DEEPSEEK_API_KEY || '' }}
EOF
- name: Start Docker Compose services
run: |
docker compose up -d db redis
echo "Waiting for database..."
until docker compose exec -T db pg_isready -U postgres -d geo_platform; do
sleep 2
done
echo "Database is ready"
- name: Run database migrations
run: |
docker compose up -d backend
echo "Waiting for backend to start..."
for i in $(seq 1 30); do
if curl -sf http://localhost:8000/health > /dev/null 2>&1; then
echo "Backend is healthy"
break
fi
echo "Waiting for backend... ($i/30)"
sleep 5
done
- name: Start frontend service
run: |
docker compose up -d frontend
echo "Waiting for frontend to start..."
for i in $(seq 1 30); do
if curl -sf http://localhost:3000 > /dev/null 2>&1; then
echo "Frontend is healthy"
break
fi
echo "Waiting for frontend... ($i/30)"
sleep 5
done
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install Playwright browsers
run: |
cd frontend
npm ci
npx playwright install --with-deps chromium
- name: Seed test data
run: |
curl -sf -X POST http://localhost:8000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"admin@123","name":"E2E Test Admin"}' || true
- name: Run E2E tests
run: |
cd frontend
E2E_TEST_EMAIL=admin@example.com \
E2E_TEST_PASSWORD=admin@123 \
npx playwright test --project=chromium --reporter=html
env:
PLAYWRIGHT_BASE_URL: http://localhost:3000
- name: Upload E2E test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-test-results
path: |
frontend/playwright-report/
frontend/test-results/
retention-days: 7
- name: Stop Docker Compose
if: always()
run: docker compose down -v