# .github/workflows/ci-cd.yml

```yaml
# =============================================================================
# CI/CD Pipeline cho Node.js Web Application với Docker
# =============================================================================
# Workflow này tự động hóa toàn bộ quy trình từ kiểm thử đến triển khai
# Được kích hoạt khi có push lên nhánh main hoặc tạo Pull Request
# =============================================================================

name: 🚀 CI/CD Pipeline - Node.js Docker Deployment

# -----------------------------------------------------------------------------
# Định nghĩa các sự kiện kích hoạt workflow
# -----------------------------------------------------------------------------
on:
  push:
    branches:
      - main        # Kích hoạt khi push lên nhánh main (production)
      - develop     # Kích hoạt khi push lên nhánh develop (staging)
    paths-ignore:
      - '**.md'           # Bỏ qua các file markdown (docs)
      - '.gitignore'      # Bỏ qua file gitignore
      - 'docs/**'         # Bỏ qua thư mục docs
  
  pull_request:
    branches:
      - main        # Kiểm thử trước khi merge vào main
      - develop     # Kiểm thử trước khi merge vào develop
    types:
      - opened      # PR mới được tạo
      - synchronize # PR được cập nhật với commit mới
      - reopened    # PR được mở lại

  # Cho phép chạy workflow thủ công từ GitHub UI
  workflow_dispatch:
    inputs:
      environment:
        description: 'Môi trường triển khai (production/staging)'
        required: true
        default: 'staging'
        type: choice
        options:
          - production
          - staging
      skip_tests:
        description: 'Bỏ qua bước kiểm thử (không khuyến nghị)'
        required: false
        default: false
        type: boolean

# -----------------------------------------------------------------------------
# Biến môi trường toàn cục - Dùng chung cho tất cả các jobs
# -----------------------------------------------------------------------------
env:
  # Thông tin Docker Registry (Docker Hub)
  DOCKER_REGISTRY: docker.io
  DOCKER_IMAGE_NAME: ${{ secrets.DOCKER_USERNAME }}/nodejs-webapp
  
  # Cấu hình Node.js
  NODE_VERSION: '20'
  
  # Thư mục làm việc trong container (dùng cho SSH deploy)
  APP_DIR: /opt/apps/nodejs-webapp
  
  # Tên file docker-compose trên server
  COMPOSE_FILE: docker-compose.prod.yml

# -----------------------------------------------------------------------------
# Cấu hình quyền mặc định (nguyên tắc ít đặc quyền nhất)
# -----------------------------------------------------------------------------
permissions:
  contents: read      # Chỉ đọc code
  packages: write     # Ghi vào GitHub Packages nếu cần
  security-events: write  # Ghi kết quả security scan

# =============================================================================
# JOBS - Các công việc trong pipeline
# =============================================================================
jobs:

  # ===========================================================================
  # JOB 1: KIỂM THỬ - Chạy tests và kiểm tra code quality
  # ===========================================================================
  test:
    name: 🧪 Kiểm Thử & Phân Tích Code
    runs-on: ubuntu-latest  # Sử dụng Ubuntu runner mới nhất
    
    # Định nghĩa strategy để test trên nhiều phiên bản Node (tùy chọn)
    strategy:
      matrix:
        node-version: ['20']  # Có thể thêm '18', '21' để test cross-version
      fail-fast: true  # Dừng tất cả nếu một matrix job thất bại

    # Cấu hình timeout để tránh job chạy vô thời hạn
    timeout-minutes: 15

    steps:
      # -----------------------------------------------------------------------
      # Bước 1: Lấy source code về runner
      # -----------------------------------------------------------------------
      - name: 📥 Checkout Source Code
        uses: actions/checkout@v4
        with:
          # Lấy toàn bộ lịch sử commit (cần cho một số tools phân tích)
          fetch-depth: 0

      # -----------------------------------------------------------------------
      # Bước 2: Thiết lập môi trường Node.js
      # -----------------------------------------------------------------------
      - name: ⚙️ Thiết Lập Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          # Cache npm dependencies để tăng tốc các lần chạy tiếp theo
          cache: 'npm'
          # Đường dẫn đến file package-lock.json để tạo cache key
          cache-dependency-path: package-lock.json

      # -----------------------------------------------------------------------
      # Bước 3: Kiểm tra phiên bản Node.js và npm (debugging)
      # -----------------------------------------------------------------------
      - name: 🔍 Kiểm Tra Phiên Bản Môi Trường
        run: |
          echo "===== Thông tin môi trường ====="
          echo "Node.js version: $(node --version)"
          echo "npm version: $(npm --version)"
          echo "OS: $(uname -a)"
          echo "Working directory: $(pwd)"
          echo "================================"

      # -----------------------------------------------------------------------
      # Bước 4: Cài đặt dependencies với npm ci (sạch và nhanh hơn npm install)
      # npm ci: Cài đặt chính xác theo package-lock.json, không thay đổi lock file
      # -----------------------------------------------------------------------
      - name: 📦 Cài Đặt Dependencies (npm ci)
        run: |
          echo "Đang cài đặt dependencies..."
          npm ci --prefer-offline --no-audit
          echo "✅ Cài đặt dependencies thành công!"
        # Biến môi trường cho bước này
        env:
          NODE_ENV: test  # Cài đặt cả devDependencies

      # -----------------------------------------------------------------------
      # Bước 5: Kiểm tra bảo mật dependencies
      # Phát hiện các package có lỗ hổng bảo mật đã biết
      # -----------------------------------------------------------------------
      - name: 🔒 Kiểm Tra Bảo Mật Dependencies (npm audit)
        run: |
          echo "Đang kiểm tra bảo mật..."
          # --audit-level=high: Chỉ fail khi có lỗ hổng mức HIGH trở lên
          npm audit --audit-level=high || {
            echo "⚠️ Phát hiện lỗ hổng bảo mật! Xem chi tiết ở trên."
            exit 1
          }
          echo "✅ Không phát hiện lỗ hổng nghiêm trọng!"
        # Tiếp tục ngay cả khi có warning (không fail build)
        continue-on-error: false

      # -----------------------------------------------------------------------
      # Bước 6: Chạy ESLint để kiểm tra code style và lỗi cú pháp
      # -----------------------------------------------------------------------
      - name: 🔎 Phân Tích Code với ESLint
        run: |
          echo "Đang chạy ESLint..."
          # Chạy ESLint với format output dễ đọc
          # --max-warnings=0: Không cho phép bất kỳ warning nào
          npx eslint . \
            --ext .js,.jsx,.ts,.tsx \
            --format=stylish \
            --max-warnings=0 \
            --ignore-pattern="node_modules/" \
            --ignore-pattern="coverage/" \
            --ignore-pattern="dist/"
          echo "✅ ESLint pass! Code style đạt chuẩn."
        env:
          NODE_ENV: test

      # -----------------------------------------------------------------------
      # Bước 7: Chạy Unit Tests và Integration Tests
      # -----------------------------------------------------------------------
      - name: 🧪 Chạy Automated Tests
        run: |
          echo "Đang chạy test suites..."
          npm test -- \
            --coverage \
            --coverageDirectory=./coverage \
            --coverageReporters=lcov \
            --coverageReporters=text-summary \
            --forceExit \
            --detectOpenHandles
          echo "✅ Tất cả tests đã pass!"
        env:
          NODE_ENV: test
          # Sử dụng database test riêng để không ảnh hưởng production
          DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
          JWT_SECRET: test-secret-key-not-for-production
          PORT: 3001

      # -----------------------------------------------------------------------
      # Bước 8: Upload coverage report lên Codecov (theo dõi độ phủ test)
      # -----------------------------------------------------------------------
      - name: 📊 Upload Coverage Report lên Codecov
        uses: codecov/codecov-action@v4
        if: always()  # Luôn upload dù test pass hay fail
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ./coverage/lcov.info
          flags: unittests
          name: nodejs-webapp-coverage
          fail_ci_if_error: false  # Không fail CI nếu Codecov lỗi

      # -----------------------------------------------------------------------
      # Bước 9: Lưu coverage report như artifact để xem sau
      # -----------------------------------------------------------------------
      - name: 💾 Lưu Coverage Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: coverage-report-node${{ matrix.node-version }}
          path: coverage/
          retention-days: 7  # Giữ artifact trong 7 ngày

      # -----------------------------------------------------------------------
      # Bước 10: Kiểm tra build thành công (đảm bảo code compile được)
      # -----------------------------------------------------------------------
      - name: 🏗️ Kiểm Tra Build
        run: |
          echo "Đang kiểm tra build..."
          npm run build --if-present
          echo "✅ Build thành công!"
        env:
          NODE_ENV: production


  # ===========================================================================
  # JOB 2: SECURITY SCAN - Quét bảo mật chuyên sâu
  # ===========================================================================
  security-scan:
    name: 🛡️ Quét Bảo Mật
    runs-on: ubuntu-latest
    needs: []  # Chạy song song với job test
    timeout-minutes: 10

    steps:
      - name: 📥 Checkout Source Code
        uses: actions/checkout@v4

      # -----------------------------------------------------------------------
      # Quét bảo mật với Trivy - Phát hiện lỗ hổng trong code và dependencies
      # -----------------------------------------------------------------------
      - name: 🔍 Quét Bảo Mật với Trivy
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'           # Quét filesystem
          scan-ref: '.'             # Quét thư mục hiện tại
          severity: 'CRITICAL,HIGH' # Chỉ báo cáo lỗ hổng CRITICAL và HIGH
          format: 'sarif'           # Format output SARIF cho GitHub Security
          output: 'trivy-results.sarif'
          exit-code: '0'            # Không fail build, chỉ báo cáo

      # Upload kết quả bảo mật lên GitHub Security tab
      - name: 📤 Upload Kết Quả Bảo Mật
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'


  # ===========================================================================
  # JOB 3: BUILD AND DEPLOY - Build Docker image và triển khai lên server
  # Chỉ chạy sau khi job test pass thành công
  # ===========================================================================
  build-and-deploy:
    name: 🐳 Build Docker & 🚀 Triển Khai
    runs-on: ubuntu-latest
    
    # Phụ thuộc vào job test - chỉ chạy khi test pass
    needs: [test, security-scan]
    
    # Chỉ chạy khi push lên main hoặc develop (không chạy với PR)
    if: |
      github.event_name == 'push' || 
      github.event_name == 'workflow_dispatch'
    
    # Định nghĩa môi trường triển khai (có thể cần approval)
    environment:
      name: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
      url: ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_URL || secrets.STAGING_URL }}
    
    timeout-minutes: 30

    # Biến môi trường cục bộ cho job này
    env:
      # Tạo Docker image tag từ Git SHA ngắn (7 ký tự đầu)
      IMAGE_TAG: ${{ github.sha }}
      IMAGE_TAG_SHORT: ${{ github.sha }}

    steps:
      # -----------------------------------------------------------------------
      # Bước 1: Checkout code (cần cho Docker build context)
      # -----------------------------------------------------------------------
      - name: 📥 Checkout Source Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 1  # Chỉ cần commit mới nhất cho Docker build

      # -----------------------------------------------------------------------
      # Bước 2: Thiết lập QEMU cho multi-platform builds (ARM, AMD64)
      # Cần thiết nếu deploy lên ARM-based servers (AWS Graviton, Raspberry Pi)
      # -----------------------------------------------------------------------
      - name: 🖥️ Thiết Lập QEMU (Multi-platform Support)
        uses: docker/setup-qemu-action@v3
        with:
          platforms: linux/amd64,linux/arm64

      # -----------------------------------------------------------------------
      # Bước 3: Thiết lập Docker Buildx (builder nâng cao với cache support)
      # -----------------------------------------------------------------------
      - name: 🔧 Thiết Lập Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          # Sử dụng docker-container driver cho cache tốt hơn
          driver: docker-container
          buildkitd-flags: --debug

      # -----------------------------------------------------------------------
      # Bước 4: Đăng nhập vào Docker Hub Registry
      # Sử dụng secrets để bảo mật credentials
      # -----------------------------------------------------------------------
      - name: 🔐 Đăng Nhập Docker Hub
        uses: docker/login-action@v3
        with:
          registry: ${{ env.DOCKER_REGISTRY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
          # Đăng xuất sau khi job hoàn thành
          logout: true

      # -----------------------------------------------------------------------
      # Bước 5: Tạo metadata (tags và labels) cho Docker image
      # Tự động tạo tags phù hợp theo best practices
      # -----------------------------------------------------------------------
      - name: 🏷️ Tạo Docker Image Metadata
        id: docker-meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKER_IMAGE_NAME }}
          tags: |
            # Tag với Git SHA đầy đủ (unique identifier)
            type=sha,prefix=sha-,format=long
            # Tag với Git SHA ngắn (dễ đọc)
            type=sha,prefix=sha-,format=short
            # Tag latest cho nhánh main
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
            # Tag staging cho nhánh develop  
            type=raw,value=staging,enable=${{ github.ref == 'refs/heads/develop' }}
            # Tag với số semver từ Git tag (nếu có)
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            # Tag với tên nhánh (thay / bằng -)
            type=ref,event=branch
          labels: |
            org.opencontainers.image.title=Node.js Web Application
            org.opencontainers.image.description=Production-ready Node.js web app
            org.opencontainers.image.vendor=${{ github.repository_owner }}
            org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
            org.opencontainers.image.revision=${{ github.sha }}
            maintainer=${{ github.actor }}

      # -----------------------------------------------------------------------
      # Bước 6: Build và Push Docker image lên Registry
      # Sử dụng cache để tăng tốc build lần sau
      # -----------------------------------------------------------------------
      - name: 🐳 Build và Push Docker Image
        id: docker-build
        uses: docker/build-push-action@v5
        with:
          # Context là thư mục hiện tại (chứa Dockerfile)
          context: .
          
          # Đường dẫn đến Dockerfile
          file: ./Dockerfile
          
          # Build cho multiple platforms
          platforms: linux/amd64,linux/arm64
          
          # Push lên registry (chỉ khi không phải PR)
          push: true
          
          # Sử dụng tags đã tạo ở bước trước
          tags: ${{ steps.docker-meta.outputs.tags }}
          
          # Sử dụng labels đã tạo ở bước trước
          labels: ${{ steps.docker-meta.outputs.labels }}
          
          # Cấu hình cache - Sử dụng GitHub Actions cache
          cache-from: |
            type=gha,scope=${{ github.workflow }}
            type=registry,ref=${{ env.DOCKER_IMAGE_NAME }}:buildcache
          cache-to: |
            type=gha,mode=max,scope=${{ github.workflow }}
            type=registry,ref=${{ env.DOCKER_IMAGE_NAME }}:buildcache,mode=max
          
          # Build arguments (truyền vào Dockerfile)
          build-args: |
            NODE_VERSION=${{ env.NODE_VERSION }}
            BUILD_DATE=${{ github.event.repository.updated_at }}
            BUILD_REVISION=${{ github.sha }}
            BUILD_VERSION=${{ github.ref_name }}
          
          # Provenance và SBOM cho supply chain security
          provenance: true
          sbom: true

      # -----------------------------------------------------------------------
      # Bước 7: Quét bảo mật Docker image vừa build
      # Phát hiện CVE trong OS packages và dependencies bên trong image
      # -----------------------------------------------------------------------
      - name: 🔍 Quét Bảo Mật Docker Image
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: '${{ env.DOCKER_IMAGE_NAME }}:sha-${{ github.sha }}'
          format: 'table'
          exit-code: '1'           # Fail nếu có lỗ hổng nghiêm trọng
          severity: 'CRITICAL'     # Chỉ fail với lỗ hổng CRITICAL
          vuln-type: 'os,library'  # Quét cả OS và library vulnerabilities

      # -----------------------------------------------------------------------
      # Bước 8: Lưu thông tin build để sử dụng sau
      # -----------------------------------------------------------------------
      - name: 📝 Lưu Thông Tin Build
        run: |
          echo "===== Thông tin Docker Build ====="
          echo "Image: ${{ env.DOCKER_IMAGE_NAME }}"
          echo "Tags: ${{ steps.docker-meta.outputs.tags }}"
          echo "Digest: ${{ steps.docker-build.outputs.digest }}"
          echo "Git SHA: ${{ github.sha }}"
          echo "Branch: ${{ github.ref_name }}"
          echo "Deployed by: ${{ github.actor }}"
          echo "=================================="
          
          # Lưu image digest vào file để có thể reference sau
          echo "${{ steps.docker-build.outputs.digest }}" > image-digest.txt

      # -----------------------------------------------------------------------
      # Bước 9: Triển khai lên Production Server qua SSH
      # Sử dụng appleboy/ssh-action để kết nối SSH an toàn
      # Chỉ chạy khi push lên nhánh main
      # -----------------------------------------------------------------------
      - name: 🚀 Triển Khai lên Production Server
        if: github.ref == 'refs/heads/main'
        uses: appleboy/ssh-action@v1.0.3
        with:
          # Thông tin kết nối SSH (lưu trong GitHub Secrets)
          host: ${{ secrets.PROD_SERVER_HOST }}
          username: ${{ secrets.PROD_SERVER_USER }}
          # Sử dụng SSH private key thay vì password (bảo mật hơn)
          key: ${{ secrets.PROD_SERVER_SSH_KEY }}
          port: ${{ secrets.PROD_SERVER_PORT || 22 }}
          
          # Fingerprint của server để xác thực (tránh MITM attacks)
          fingerprint: ${{ secrets.PROD_SERVER_FINGERPRINT }}
          
          # Timeout kết nối SSH
          connect_timeout: 30s
          
          # Timeout cho toàn bộ script
          command_timeout: 20m
          
          # Script chạy trên server sau khi kết nối SSH
          script: |
            # ================================================================
            # Script triển khai trên Production Server
            # ================================================================
            set -e  # Dừng ngay nếu có lỗi (exit on error)
            set -u  # Báo lỗi nếu dùng biến chưa định nghĩa
            
            echo "=========================================="
            echo "🚀 Bắt đầu triển khai Production"
            echo "📅 Thời gian: $(date '+%Y-%m-%d %H:%M:%S')"
            echo "🔖 Version: ${{ github.sha }}"
            echo "👤 Deployed by: ${{ github.actor }}"
            echo "=========================================="
            
            # ----------------------------------------------------------------
            # Đăng nhập vào Docker Hub trên server
            # ----------------------------------------------------------------
            echo "🔐 Đăng nhập Docker Hub..."
            echo "${{ secrets.DOCKER_PASSWORD }}" | \
              docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
            echo "✅ Đăng nhập thành công!"
            
            # ----------------------------------------------------------------
            # Di chuyển đến thư mục ứng dụng
            # ----------------------------------------------------------------
            echo "📁 Di chuyển đến thư mục ứng dụng..."
            cd ${{ env.APP_DIR }} || {
              echo "❌ Thư mục ${{ env.APP_DIR }} không tồn tại!"
              echo "Đang tạo thư mục..."
              mkdir -p ${{ env.APP_DIR }}
              cd ${{ env.APP_DIR }}
            }
            
            # ----------------------------------------------------------------
            # Pull Docker image mới nhất từ registry
            # ----------------------------------------------------------------
            echo "⬇️ Pulling Docker image mới..."
            docker pull ${{ env.DOCKER_IMAGE_NAME }}:latest
            echo "✅ Pull image thành công!"
            
            # ----------------------------------------------------------------
            # Backup container hiện tại (để rollback nếu cần)
            # ----------------------------------------------------------------
            echo "💾 Tạo backup container hiện tại..."
            CURRENT_IMAGE=$(docker inspect \
              --format='{{.Config.Image}}' nodejs-webapp 2>/dev/null || echo "none")
            echo "Current image: $CURRENT_IMAGE"
            
            # ----------------------------------------------------------------
            # Cập nhật environment variables
            # ----------------------------------------------------------------
            echo "⚙️ Cập nhật cấu hình môi trường..."
            cat > .env.production << EOF
            NODE_ENV=production
            PORT=3000
            DATABASE_URL=${{ secrets.PROD_DATABASE_URL }}
            REDIS_URL=${{ secrets.PROD_REDIS_URL }}
            JWT_SECRET=${{ secrets.PROD_JWT_SECRET }}
            APP_VERSION=${{ github.sha }}
            DEPLOY_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
            EOF
            echo "✅ Cập nhật cấu hình thành công!"
            
            # ----------------------------------------------------------------
            # Rolling update với Docker Compose (zero-downtime deployment)
            # ----------------------------------------------------------------
            echo "🔄 Thực hiện Rolling Update..."
            
            # Cập nhật image tag trong docker-compose
            export DOCKER_IMAGE="${{ env.DOCKER_IMAGE_NAME }}:latest"
            export BUILD_VERSION="${{ github.sha }}"
            
            # Pull images mới nhất được định nghĩa trong compose file
            docker compose -f ${{ env.COMPOSE_FILE }} pull
            
            # Rolling update - Không có downtime
            docker compose -f ${{ env.COMPOSE_FILE }} up \
              --detach \
              --no-build \
              --remove-orphans \
              --wait \
              --wait-timeout 120
            
            echo "✅ Rolling update thành công!"
            
            # ----------------------------------------------------------------
            # Kiểm tra health của containers sau deploy
            # ----------------------------------------------------------------
            echo "🏥 Kiểm tra sức khỏe ứng dụng..."
            
            # Đợi 15 giây cho app khởi động
            sleep 15
            
            # Kiểm tra health endpoint
            HEALTH_CHECK_URL="http://localhost:3000/health"
            MAX_RETRIES=5
            RETRY_COUNT=0
            
            until curl -sf "$HEALTH_CHECK_URL" > /dev/null 2>&1; do
              RETRY_COUNT=$((RETRY_COUNT + 1))
              if [ $RETRY_COUNT -ge $MAX_RETRIES ]; then
                echo "❌ Health check thất bại sau $MAX_RETRIES lần thử!"
                echo "Đang rollback về phiên bản trước..."
                docker compose -f ${{ env.COMPOSE_FILE }} rollback 2>/dev/null || true
                exit 1
              fi
              echo "⏳ Đang đợi app khởi động... (lần $RETRY_COUNT/$MAX_RETRIES)"
              sleep 10
            done
            
            echo "✅ Health check pass! Ứng dụng đang chạy bình thường."
            
            # ----------------------------------------------------------------
            # Dọn dẹp Docker images cũ để tiết kiệm dung lượng
            # ----------------------------------------------------------------
            echo "🧹 Dọn dẹp Docker images cũ..."
            docker image prune -f --filter "until=24h"
            echo "✅ Dọn dẹp thành công!"
            
            # ----------------------------------------------------------------
            # Đăng xuất khỏi Docker Hub (bảo mật)
            # ----------------------------------------------------------------
            docker logout
            
            # ----------------------------------------------------------------
            # Hiển thị trạng thái cuối cùng
            # ----------------------------------------------------------------
            echo ""
            echo "=========================================="
            echo "✅ TRIỂN KHAI THÀNH CÔNG!"
            echo "📅 Hoàn thành: $(date '+%Y-%m-%d %H:%M:%S')"
            echo "🔖 Version: ${{ github.sha }}"
            echo ""
            echo "📊 Trạng thái containers:"
            docker compose -f ${{ env.COMPOSE_FILE }} ps
            echo "=========================================="

      # -----------------------------------------------------------------------
      # Bước 10: Triển khai lên Staging Server
      # Chỉ chạy khi push lên nhánh develop
      # -----------------------------------------------------------------------
      - name: 🧪 Triển Khai lên Staging Server
        if: github.ref == 'refs/heads/develop'
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.STAGING_SERVER_HOST }}
          username: ${{ secrets.STAGING_SERVER_USER }}
          key: ${{ secrets.STAGING_SERVER_SSH_KEY }}
          port: ${{ secrets.STAGING_SERVER_PORT || 22 }}
          connect_timeout: 30s
          command_timeout: 15m
          script: |
            set -e
            
            echo "=========================================="
            echo "🧪 Bắt đầu triển khai Staging"
            echo "📅 Thời gian: $(date '+%Y-%m-%d %H:%M:%S')"
            echo "🔖 Version: ${{ github.sha }}"
            echo "=========================================="
            
            # Đăng nhập Docker
            echo "${{ secrets.DOCKER_PASSWORD }}" | \
              docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
            
            cd ${{ env.APP_DIR }}
            
            # Cập nhật .env cho staging
            cat > .env.staging << EOF
            NODE_ENV=staging
            PORT=3000
            DATABASE_URL=${{ secrets.STAGING_DATABASE_URL }}
            REDIS_URL=${{ secrets.STAGING_REDIS_URL }}
            JWT_SECRET=${{ secrets.STAGING_JWT_SECRET }}
            APP_VERSION=${{ github.sha }}
            EOF
            
            # Deploy staging
            export DOCKER_IMAGE="${{ env.DOCKER_IMAGE_NAME }}:staging"
            docker compose -f docker-compose.staging.yml pull
            docker compose -f docker-compose.staging.yml up \
              --detach \
              --remove-orphans \
              --wait \
              --wait-timeout 60
            
            docker logout
            
            echo "✅ Staging deployment thành công!"
            docker compose -f docker-compose.staging.yml ps


  # ===========================================================================
  # JOB 4: NOTIFY - Gửi thông báo kết quả deployment
  # ===========================================================================
  notify:
    name: 📢 Gửi Thông Báo
    runs-on: ubuntu-latest
    
    # Chạy sau khi build-and-deploy hoàn thành (dù thành công hay thất bại)
    needs: [build-and-deploy]
    if: always()  # Luôn chạy
    
    steps:
      # -----------------------------------------------------------------------
      # Xác định trạng thái deployment
      # -----------------------------------------------------------------------
      - name: 📊 Xác Định Trạng Thái
        id: status
        run: |
          if [ "${{ needs.build-and-deploy.result }}" == "success" ]; then
            echo "status=✅ THÀNH CÔNG" >> $GITHUB_OUTPUT
            echo "color=good" >> $GITHUB_OUTPUT
            echo "emoji=🚀" >> $GITHUB_OUTPUT
          else
            echo "status=❌ THẤT BẠI" >> $GITHUB_OUTPUT
            echo "color=danger" >> $GITHUB_OUTPUT
            echo "emoji=🔥" >> $GITHUB_OUTPUT
          fi

      # -----------------------------------------------------------------------
      # Gửi thông báo qua Slack
      # -----------------------------------------------------------------------
      - name: 📱 Gửi Thông Báo Slack
        uses: slackapi/slack-github-action@v1.26.0
        if: always()
        with:
          payload: |
            {
              "text": "${{ steps.status.outputs.emoji }} *Deployment ${{ steps.status.outputs.status }}*",
              "attachments": [
                {
                  "color": "${{ steps.status.outputs.color }}",
                  "fields": [
                    {
                      "title": "Repository",
                      "value": "${{ github.repository }}",
                      "short": true
                    },
                    {
                      "title": "Branch",
                      "value": "${{ github.ref_name }}",
                      "short": true
                    },
                    {
                      "title": "Commit",
                      "value": "<${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>",
                      "short": true
                    },
                    {
                      "title": "Deployed by",
                      "value": "${{ github.actor }}",
                      "short": true
                    },
                    {
                      "title": "Workflow Run",
                      "value": "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Xem chi tiết>",
                      "short": false
                    }
                  ],
                  "footer": "GitHub Actions CI/CD | ${{ github.workflow }}",
                  "ts": "${{ github.event.repository.updated_at }}"
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

      # -----------------------------------------------------------------------
      # Tạo GitHub Deployment Status
      # -----------------------------------------------------------------------
      - name: 🏁 Cập Nhật GitHub Deployment Status
        uses: chrnorm/deployment-status@v2
        if: always()
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          state: ${{ needs.build-and-deploy.result == 'success' && 'success' || 'failure' }}
          deployment-id: ${{ github.run_id }}
          environment-url: |
            ${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_URL || secrets.STAGING_URL }}
          description: |
            Deployed version ${{ github.sha }} by ${{ github.actor }}
```

---

# Hướng Dẫn Cấu Hình GitHub Secrets

## 📋 Danh Sách Secrets Cần Thiết

```bash
# ============================================================
# DOCKER HUB CREDENTIALS
# ============================================================
DOCKER_USERNAME          # Username Docker Hub của bạn
DOCKER_PASSWORD          # Password hoặc Access Token Docker Hub
                         # ⚠️ Nên dùng Access Token thay vì password

# ============================================================
# PRODUCTION SERVER (SSH)
# ============================================================
PROD_SERVER_HOST         # IP hoặc hostname server production
PROD_SERVER_USER         # SSH username (vd: ubuntu, deploy)
PROD_SERVER_SSH_KEY      # Nội dung SSH private key (-----BEGIN...)
PROD_SERVER_PORT         # SSH port (mặc định: 22)
PROD_SERVER_FINGERPRINT  # SSH fingerprint của server

# ============================================================
# STAGING SERVER (SSH)
# ============================================================
STAGING_SERVER_HOST      # IP hoặc hostname server staging
STAGING_SERVER_USER      # SSH username staging
STAGING_SERVER_SSH_KEY   # SSH private key cho staging
STAGING_SERVER_PORT      # SSH port staging

# ============================================================
# DATABASE CONNECTIONS
# ============================================================
PROD_DATABASE_URL        # PostgreSQL/MongoDB URL production
STAGING_DATABASE_URL     # Database URL staging
TEST_DATABASE_URL         # Database URL cho CI tests

# ============================================================
# APPLICATION SECRETS
# ============================================================
PROD_JWT_SECRET          # JWT secret key production (min 64 chars)
STAGING_JWT_SECRET       # JWT secret key staging
PROD_REDIS_URL           # Redis URL production

# ============================================================
# EXTERNAL SERVICES
# ============================================================
CODECOV_TOKEN            # Token từ codecov.io
SLACK_WEBHOOK_URL        # Webhook URL từ Slack App

# ============================================================
# URLs
# ============================================================
PRODUCTION_URL           # URL production (vd: https://myapp.com)
STAGING_URL              # URL staging (vd: https://staging.myapp.com)
```

## 🔑 Tạo SSH Key Pair cho Deployment

```bash
# Tạo SSH key pair (chạy trên máy local)
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/deploy_key -N ""

# Xem public key (thêm vào server's authorized_keys)
cat ~/.ssh/deploy_key.pub

# Xem private key (thêm vào GitHub Secret: PROD_SERVER_SSH_KEY)
cat ~/.ssh/deploy_key

# Lấy SSH fingerprint của server
ssh-keyscan -H YOUR_SERVER_IP 2>/dev/null | ssh-keygen -lf -

# Thêm public key vào server
ssh-copy-id -i ~/.ssh/deploy_key.pub user@your-server-ip
```

## 🐳 Cấu Trúc Dockerfile Khuyến Nghị

```dockerfile
# Dockerfile
# Multi-stage build để giảm kích thước image

# ==========================================
# Stage 1: Dependencies
# ==========================================
FROM node:20-alpine AS deps
WORKDIR /app

# Copy package files trước (tận dụng Docker layer cache)
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

# ==========================================
# Stage 2: Builder
# ==========================================
FROM node:20-alpine AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ==========================================
# Stage 3: Production Runner
# ==========================================
FROM node:20-alpine AS runner
WORKDIR /app

# Tạo user non-root để bảo mật
RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nodeuser

# Copy chỉ những gì cần thiết
COPY --from=deps --chown=nodeuser:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodeuser:nodejs /app/dist ./dist
COPY --chown=nodeuser:nodejs package.json .

# Chạy với user non-root
USER nodeuser

EXPOSE 3000
ENV NODE_ENV=production

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "dist/server.js"]
```