Cập nhật README: thay [Tên của bạn] -> lộc võ, cập nhật email và liên… #2
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: Smart Quiz App - CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main ] | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # Code Quality and Security Checks | |
| code-quality: | |
| name: Code Quality & Security | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install flake8 black bandit safety | |
| pip install -r server/requirements.txt | |
| - name: Run Black code formatter check | |
| run: black --check server/ | |
| - name: Run Flake8 linter | |
| run: flake8 server/ --max-line-length=100 --exclude=migrations/ | |
| - name: Run Bandit security linter | |
| run: bandit -r server/ -f json -o bandit-report.json || true | |
| - name: Check for security vulnerabilities | |
| run: safety check --json --output safety-report.json || true | |
| - name: Upload security reports | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: security-reports | |
| path: | | |
| bandit-report.json | |
| safety-report.json | |
| # Backend Testing | |
| backend-tests: | |
| name: Backend Tests | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15 | |
| env: | |
| POSTGRES_PASSWORD: test_password | |
| POSTGRES_DB: test_db | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r server/requirements.txt | |
| - name: Run backend tests | |
| env: | |
| DATABASE_URL: postgresql://postgres:test_password@localhost:5432/test_db | |
| REDIS_HOST: localhost | |
| FLASK_ENV: testing | |
| SECRET_KEY: test-secret-key | |
| JWT_SECRET_KEY: test-jwt-secret | |
| run: | | |
| cd server | |
| python -m pytest tests/ -v --cov=. --cov-report=xml --cov-report=html | |
| - name: Upload coverage reports | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| file: ./server/coverage.xml | |
| flags: backend | |
| name: backend-coverage | |
| # Android Build and Test | |
| android-build: | |
| name: Android Build & Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v3 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v2 | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Grant execute permission for gradlew | |
| run: chmod +x gradlew | |
| - name: Run Android lint | |
| run: ./gradlew lintDebug | |
| - name: Run unit tests | |
| run: ./gradlew testDebugUnitTest | |
| - name: Run instrumented tests | |
| uses: reactivecircus/android-emulator-runner@v2 | |
| with: | |
| api-level: 29 | |
| script: ./gradlew connectedDebugAndroidTest | |
| - name: Build debug APK | |
| run: ./gradlew assembleDebug | |
| - name: Upload APK | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: debug-apk | |
| path: app/build/outputs/apk/debug/app-debug.apk | |
| - name: Upload test reports | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: android-test-reports | |
| path: | | |
| app/build/reports/ | |
| app/build/test-results/ | |
| # Security Scanning | |
| security-scan: | |
| name: Security Scanning | |
| runs-on: ubuntu-latest | |
| needs: [code-quality] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy scan results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| # Build and Push Docker Images | |
| build-and-push: | |
| name: Build & Push Docker Images | |
| runs-on: ubuntu-latest | |
| needs: [backend-tests, android-build, security-scan] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Deploy to Staging | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| needs: [build-and-push] | |
| if: github.ref == 'refs/heads/develop' | |
| environment: staging | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Deploy to staging server | |
| uses: appleboy/[email protected] | |
| with: | |
| host: ${{ secrets.STAGING_HOST }} | |
| username: ${{ secrets.STAGING_USER }} | |
| key: ${{ secrets.STAGING_SSH_KEY }} | |
| script: | | |
| cd /opt/smartquiz-staging | |
| docker-compose pull | |
| docker-compose up -d | |
| docker system prune -f | |
| - name: Run health check | |
| run: | | |
| sleep 30 | |
| curl -f ${{ secrets.STAGING_URL }}/api/v1/health || exit 1 | |
| # Deploy to Production | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: [build-and-push] | |
| if: github.ref == 'refs/heads/main' | |
| environment: production | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Deploy to production server | |
| uses: appleboy/[email protected] | |
| with: | |
| host: ${{ secrets.PRODUCTION_HOST }} | |
| username: ${{ secrets.PRODUCTION_USER }} | |
| key: ${{ secrets.PRODUCTION_SSH_KEY }} | |
| script: | | |
| cd /opt/smartquiz-production | |
| docker-compose pull | |
| docker-compose up -d --no-deps backend | |
| docker system prune -f | |
| - name: Run production health check | |
| run: | | |
| sleep 60 | |
| curl -f ${{ secrets.PRODUCTION_URL }}/api/v1/health || exit 1 | |
| - name: Notify deployment success | |
| uses: 8398a7/action-slack@v3 | |
| with: | |
| status: success | |
| text: 'Smart Quiz App deployed successfully to production! 🚀' | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| # Performance Testing | |
| performance-test: | |
| name: Performance Testing | |
| runs-on: ubuntu-latest | |
| needs: [deploy-staging] | |
| if: github.ref == 'refs/heads/develop' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run K6 performance tests | |
| uses: grafana/[email protected] | |
| with: | |
| filename: tests/performance/load-test.js | |
| env: | |
| K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} | |
| BASE_URL: ${{ secrets.STAGING_URL }} | |
| - name: Upload performance results | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: performance-results | |
| path: results.json |