Merge pull request #104 from Fahmedo/main #66
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 | |
| # 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 | |
| - 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 | |
| # Testing | |
| test: | |
| name: Tests | |
| runs-on: ubuntu-latest | |
| 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" | |
| # Add your staging deployment logic here | |
| # e.g., docker-compose up -d, kubectl apply, etc. | |
| # 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" | |
| # Add your production deployment logic here | |
| # e.g., docker-compose up -d, kubectl apply, etc. | |
| - 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 |