CI Pipeline #31
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
| name: CI Pipeline | |
| on: | |
| pull_request: | |
| branches: ["main", "master", "develop"] | |
| push: | |
| branches: ["main", "master", "develop"] | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 3 * * *" | |
| env: | |
| PYTHON_VERSION: "3.11" | |
| NODE_VERSION: "18" | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| lint-and-quality: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| name: Code Quality & Linting | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install flake8 black pylint mypy pytest | |
| - name: Run Black formatter check | |
| run: black --check . || true | |
| continue-on-error: true | |
| - name: Run Flake8 linter | |
| run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics || true | |
| continue-on-error: true | |
| - name: Run Pylint | |
| run: pylint src/ ml-model-api/ --fail-under=7.0 || true | |
| continue-on-error: true | |
| - name: Frontend linting | |
| working-directory: frontend | |
| run: | | |
| npm ci | |
| npm run lint || true | |
| continue-on-error: true | |
| tests: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| needs: [lint-and-quality] | |
| services: | |
| postgres: | |
| image: postgres:15-alpine | |
| env: | |
| POSTGRES_USER: test | |
| POSTGRES_PASSWORD: test | |
| POSTGRES_DB: testdb | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| redis: | |
| image: redis:7-alpine | |
| ports: | |
| - 6379:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| 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 | |
| python -m pip install -r requirements-dev.txt | |
| - name: Run unit tests with coverage | |
| run: | | |
| export DATABASE_URL=postgresql://test:test@localhost:5432/testdb | |
| export REDIS_URL=redis://localhost:6379/0 | |
| python scripts/coverage_report.py | |
| env: | |
| DATABASE_URL: postgresql://test:test@localhost:5432/testdb | |
| REDIS_URL: redis://localhost:6379/0 | |
| - name: Performance smoke benchmarks | |
| if: github.event_name != 'schedule' | |
| run: python scripts/run_tests.py --performance-smoke | |
| - name: Performance full benchmarks | |
| if: github.event_name == 'schedule' | |
| run: python scripts/run_tests.py --performance-full | |
| - name: Upload coverage artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage | |
| path: | | |
| coverage.xml | |
| htmlcov | |
| if-no-files-found: warn | |
| build-frontend: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| name: Build Frontend | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Cache node modules | |
| uses: actions/cache@v4 | |
| with: | |
| path: frontend/node_modules | |
| key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node- | |
| - name: Install dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Build | |
| working-directory: frontend | |
| run: npm run build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend-build | |
| path: frontend/.next | |
| retention-days: 7 | |
| build-docker: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| name: Build Docker Images | |
| needs: [tests, build-frontend] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata for Docker | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=sha,prefix= | |
| type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |