Merge pull request #200 from Cybermaxi7/feat/revenue-sharing-stakehol… #131
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/CD Pipeline | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| workflow_dispatch: | |
| env: | |
| PYTHON_VERSION: "3.11" | |
| DOCKER_IMAGE_NAME: veritix-python-app | |
| REGISTRY: ghcr.io | |
| jobs: | |
| # Security scanning | |
| security-scan: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Run security checks | |
| uses: pyupio/safety@v1 | |
| with: | |
| requirements: requirements.txt | |
| - name: Run bandit security scan | |
| run: | | |
| pip install bandit | |
| bandit -r src/ -f json -o bandit-report.json || true | |
| - name: Upload bandit results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| if: always() | |
| with: | |
| sarif_file: bandit-report.json | |
| # Format enforcement (black + isort) — must pass before tests run | |
| lint-check: | |
| name: Format Check (black + isort) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| cache: "pip" | |
| cache-dependency-path: "requirements.txt" | |
| - name: Install formatters | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install black==24.4.2 isort==5.13.2 | |
| - name: Check formatting with black | |
| run: black --check src/ tests/ | |
| - name: Check import order with isort | |
| run: isort --check-only --diff src/ tests/ | |
| # Linting | |
| lint: | |
| name: Code Quality | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| cache: "pip" | |
| cache-dependency-path: "requirements.txt" | |
| - name: Install linting tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install black flake8 isort mypy==1.11.2 types-requests==2.32.0.20240907 | |
| pip install -r requirements.txt | |
| - name: Check code formatting with Black | |
| run: black --check . | |
| - name: Check import sorting with isort | |
| run: isort --check-only --diff . | |
| - name: Lint with Flake8 | |
| run: | | |
| flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics | |
| flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics | |
| - name: Type check with mypy | |
| env: | |
| QR_SIGNING_KEY: "changeme_at_least_32_chars_long!!" | |
| DATABASE_URL: "postgresql://veritix:veritix@localhost/veritix" | |
| NEST_API_BASE_URL: "http://localhost:3000" | |
| run: | | |
| mypy src/ | |
| # Testing — depends on lint-check to enforce formatting before tests | |
| test: | |
| name: Tests | |
| runs-on: ubuntu-latest | |
| needs: [lint-check] | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: veritix | |
| POSTGRES_PASSWORD: veritix | |
| POSTGRES_DB: veritix_test | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| cache: "pip" | |
| cache-dependency-path: "requirements.txt" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pytest pytest-asyncio pytest-cov | |
| - name: Run tests with coverage | |
| env: | |
| DATABASE_URL: postgresql://veritix:veritix@localhost:5432/veritix_test | |
| SKIP_MODEL_TRAINING: true | |
| run: | | |
| pytest --cov=src --cov-report=xml --cov-report=term-missing --cov-fail-under=80 | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: test-results | |
| path: | | |
| coverage.xml | |
| .coverage | |
| # Docker build and test | |
| docker: | |
| name: Docker Build | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] | |
| if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ github.repository }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Login to GitHub Container Registry | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: ${{ github.event_name != 'pull_request' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Run Docker container tests | |
| run: | | |
| docker run --rm ${{ env.DOCKER_IMAGE_NAME }}:latest python -c "import src.main; print('Application imports successfully')" | |
| - name: Export Docker image | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| docker save ${{ env.DOCKER_IMAGE_NAME }}:latest | gzip > veritix-app.tar.gz | |
| - name: Upload Docker image artifact | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: docker-image | |
| path: veritix-app.tar.gz | |
| # Deploy to staging | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| needs: [docker] | |
| if: github.ref == 'refs/heads/develop' | |
| environment: staging | |
| steps: | |
| - name: Deploy to staging environment | |
| run: | | |
| echo "Deploying to staging environment" | |
| # Deploy to production | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: [docker] | |
| if: github.ref == 'refs/heads/main' | |
| environment: production | |
| steps: | |
| - name: Deploy to production environment | |
| run: | | |
| echo "Deploying to production environment" | |
| - name: Create GitHub Release | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: v${{ github.run_number }} | |
| release_name: Release v${{ github.run_number }} | |
| draft: false | |
| prerelease: false |