Files
ewoooc/docs/CI_CD_EVALUATION.md
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

18 KiB
Raw Permalink Blame History

MOMO Pro System - CI/CD 機制評估報告

執行摘要

本文件評估 MOMO Pro System 導入 CI/CD持續整合/持續部署)機制的建議方案。

現況分析

  • 部署方式:手動執行 deploy.sh 腳本(使用 gcloud 命令)
  • 版本控制:本地 Git 倉庫,尚未設定遠端倉庫
  • 測試覆蓋:無自動化測試套件
  • 部署環境GCP VM (asia-east1-a), e2-standard-2

建議方案GitHub Actions推薦或 GitLab CI


1. 平台選擇評估

1.1 GitHub Actions推薦

優點

  • 與 GitHub 原生整合,無需額外設定
  • 每月 2,000 分鐘免費額度(私有倉庫)
  • 公有倉庫完全免費
  • 豐富的 Marketplace Actions 可重用
  • 文件齊全,社群活躍
  • 支援 Self-hosted Runners可在 GCP VM 上運行,節省成本)

缺點

  • 需要將程式碼推送到 GitHub
  • 超過免費額度後需付費($0.008/分鐘)
  • 相對 GitLab CI功能較精簡

適用場景

  • 開源或小型團隊專案
  • 需要快速上手的 CI/CD 解決方案
  • 預算有限,希望最大化利用免費額度

成本估算

  • 免費額度2,000 分鐘/月(私有倉庫)
  • 每次 CI/CD 執行約 5-10 分鐘
  • 預計每月約 100-200 次部署 → 完全免費(使用 Self-hosted Runner

1.2 GitLab CI

優點

  • 可以 Self-hosted完全控制
  • 內建 Container Registry
  • 更強大的 Pipeline 配置功能
  • 免費版功能豐富
  • 每月 400 分鐘免費額度私有倉庫GitLab.com

缺點

  • Self-hosted 需要額外維護
  • GitLab.com 免費額度較少400 分鐘)
  • 學習曲線較陡峭
  • 如果使用 GitLab.com需要遷移程式碼

適用場景

  • 大型企業專案
  • 需要更複雜的 Pipeline 流程
  • 已有 GitLab 基礎設施

成本估算

  • GitLab.com 免費額度400 分鐘/月
  • Self-hosted需額外 VM 資源(約 $20-50/月)

1.3 建議結論

推薦 GitHub Actions,理由:

  1. 免費額度充足2,000 分鐘 + Self-hosted Runner 無限制)
  2. 與 GitHub 生態系統整合度高
  3. 學習成本低,快速上手
  4. 可在現有 GCP VM 上運行 Self-hosted Runner完全免費

2. CI/CD Pipeline 設計

2.1 Pipeline 階段規劃

┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Trigger   │ -> │    Build    │ -> │    Test     │ -> │   Deploy    │
│ (Git Push)  │    │  (安裝依賴)  │    │  (自動測試)  │    │ (部署到GCP) │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

2.2 建議的 Workflow

階段 1程式碼檢查Linting & Security

  • 觸發條件Pull Request 或 Push 到 main/develop
  • 執行內容
    • Python 語法檢查flake8 / pylint
    • 安全漏洞掃描bandit
    • 程式碼格式檢查black
  • 目標:確保程式碼品質和安全性
  • 執行時間~1-2 分鐘

階段 2自動化測試Testing

  • 觸發條件:通過階段 1
  • 執行內容
    • 單元測試pytest
    • 整合測試(測試資料庫操作)
    • API 端點測試(測試 Flask routes
  • 目標:確保功能正確性
  • 執行時間~2-3 分鐘

階段 3建置與打包Build

  • 觸發條件:通過階段 2
  • 執行內容
    • 安裝 Python 依賴pip install -r requirements.txt
    • 檢查依賴版本衝突
    • 建置文件版本號
  • 目標:確保可部署性
  • 執行時間~1-2 分鐘

階段 4部署Deployment

  • 觸發條件
    • 自動觸發Push 到 main 分支
    • 手動觸發:透過 GitHub Actions UI 手動執行
  • 執行內容
    • 備份遠端資料庫
    • 上傳程式碼到 GCP VM
    • 重啟服務systemctl restart momo
    • 健康檢查(確認服務正常運行)
    • 失敗時自動回滾
  • 目標:零停機部署
  • 執行時間~3-5 分鐘

3. 具體實作方案

3.1 GitHub Actions 實作

目錄結構

.github/
└── workflows/
    ├── ci.yml           # 持續整合(測試、檢查)
    ├── deploy.yml       # 持續部署(部署到 GCP
    └── backup.yml       # 定期備份任務(每日)

範例:.github/workflows/ci.yml

name: CI - Continuous Integration

on:
  pull_request:
    branches: [main, develop]
  push:
    branches: [develop]

jobs:
  lint:
    name: 程式碼檢查
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: 設定 Python 環境
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'

      - name: 安裝檢查工具
        run: |
          pip install flake8 bandit black

      - name: Python 語法檢查
        run: flake8 app.py scheduler.py --max-line-length=120

      - name: 安全漏洞掃描
        run: bandit -r . -x ./venv,./lib

      - name: 程式碼格式檢查
        run: black --check app.py scheduler.py

  test:
    name: 自動化測試
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v4

      - name: 設定 Python 環境
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'

      - name: 安裝依賴
        run: |
          pip install -r requirements.txt
          pip install pytest pytest-cov

      - name: 執行測試
        run: |
          pytest tests/ -v --cov=. --cov-report=html

      - name: 上傳測試覆蓋率報告
        uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: htmlcov/

範例:.github/workflows/deploy.yml

name: CD - Deploy to GCP

on:
  push:
    branches: [main]
  workflow_dispatch:  # 允許手動觸發

jobs:
  deploy:
    name: 部署到 GCP Production
    runs-on: ubuntu-latest
    environment:
      name: production
      url: http://35.194.172.48

    steps:
      - uses: actions/checkout@v4

      - name: 設定 GCP 認證
        uses: google-github-actions/auth@v2
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}

      - name: 設定 gcloud CLI
        uses: google-github-actions/setup-gcloud@v2

      - name: 備份遠端資料庫
        run: |
          gcloud compute ssh momo-server \
            --zone=asia-east1-a \
            --command="bash ~/momo_pro_system/backup_system.py"

      - name: 上傳程式碼
        run: |
          gcloud compute scp --recurse \
            --exclude='.git' --exclude='venv' --exclude='logs' \
            ./*.py ./*.html \
            momo-server:~/momo_pro_system/ \
            --zone=asia-east1-a

      - name: 重啟服務
        run: |
          gcloud compute ssh momo-server \
            --zone=asia-east1-a \
            --command="sudo systemctl restart momo"

      - name: 健康檢查
        run: |
          sleep 10
          gcloud compute ssh momo-server \
            --zone=asia-east1-a \
            --command="
              if sudo systemctl is-active --quiet momo; then
                echo '✓ 服務運行正常'
                exit 0
              else
                echo '✗ 服務啟動失敗'
                sudo journalctl -u momo -n 50 --no-pager
                exit 1
              fi
            "

      - name: 部署失敗時回滾
        if: failure()
        run: |
          echo "部署失敗,執行回滾..."
          gcloud compute ssh momo-server \
            --zone=asia-east1-a \
            --command="bash ~/momo_pro_system/rollback_latest.sh"

3.2 Self-hosted Runner 設定(節省成本)

在 GCP VM 上安裝 GitHub Actions Runner讓 CI/CD 在自己的伺服器上執行(完全免費)。

安裝步驟(在 GCP VM 上執行)

# 1. 建立 Runner 目錄
mkdir -p ~/actions-runner && cd ~/actions-runner

# 2. 下載 Runner
curl -o actions-runner-linux-x64-2.313.0.tar.gz \
  -L https://github.com/actions/runner/releases/download/v2.313.0/actions-runner-linux-x64-2.313.0.tar.gz

# 3. 解壓縮
tar xzf ./actions-runner-linux-x64-2.313.0.tar.gz

# 4. 配置 Runner需要 GitHub Token
./config.sh --url https://github.com/YOUR_USERNAME/momo_pro_system \
  --token YOUR_TOKEN

# 5. 安裝為系統服務
sudo ./svc.sh install
sudo ./svc.sh start

使用 Self-hosted Runner 後,所有 CI/CD 任務都在您的 GCP VM 上執行,完全免費


4. 自動化測試策略

4.1 測試框架選擇pytest

建議使用 pytest 作為主要測試框架,理由:

  • Python 最流行的測試框架
  • 語法簡潔,易於編寫和維護
  • 豐富的插件生態系統
  • 支援測試覆蓋率報告

4.2 測試架構規劃

tests/
├── __init__.py
├── conftest.py              # pytest 配置和 fixtures
├── test_app.py              # Flask 路由測試
├── test_database.py         # 資料庫操作測試
├── test_scheduler.py        # 排程器測試
├── test_crawler.py          # 爬蟲測試
└── test_email.py            # 郵件發送測試

4.3 測試範例

tests/conftest.py(測試配置)

import pytest
from app import app, db

@pytest.fixture
def client():
    """Flask 測試客戶端"""
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'

    with app.test_client() as client:
        with app.app_context():
            db.create_all()
        yield client

@pytest.fixture
def auth_client(client):
    """已登入的測試客戶端"""
    client.post('/login', data={
        'username': 'admin',
        'password': 'test_password'
    })
    return client

tests/test_app.py(路由測試)

def test_index_redirect(client):
    """測試首頁重定向到登入頁面"""
    response = client.get('/')
    assert response.status_code == 302
    assert '/login' in response.location

def test_login_success(client):
    """測試登入成功"""
    response = client.post('/login', data={
        'username': 'admin',
        'password': 'correct_password'
    })
    assert response.status_code == 302
    assert '/' in response.location

def test_dashboard_access(auth_client):
    """測試已登入用戶可訪問儀表板"""
    response = auth_client.get('/dashboard')
    assert response.status_code == 200
    assert b'dashboard' in response.data.lower()

tests/test_database.py(資料庫測試)

from datetime import date

def test_sales_query(auth_client):
    """測試銷售數據查詢"""
    # 插入測試數據
    from database.models import RealtimeSalesMonthly
    test_data = RealtimeSalesMonthly(
        日期=date.today(),
        商品ID='TEST001',
        商品名稱='測試商品',
        銷售數量=100,
        銷售金額=5000
    )
    db.session.add(test_data)
    db.session.commit()

    # 查詢測試
    result = RealtimeSalesMonthly.query.filter_by(商品ID='TEST001').first()
    assert result is not None
    assert result.銷售數量 == 100

4.4 測試執行

# 執行所有測試
pytest tests/ -v

# 執行測試並生成覆蓋率報告
pytest tests/ --cov=. --cov-report=html

# 執行特定測試檔案
pytest tests/test_app.py -v

# 執行特定測試函數
pytest tests/test_app.py::test_login_success -v

5. 零停機部署策略

5.1 Blue-Green 部署(推薦)

概念維護兩個相同的生產環境Blue 和 Green部署時切換流量。

實作方式

# 1. 部署到 Green 環境(新版本)
gcloud compute ssh momo-server --command="
  # 複製當前版本到 blue 目錄
  cp -r ~/momo_pro_system ~/momo_pro_system_blue

  # 部署新版本到 green 目錄
  cd ~/momo_pro_system_green
  git pull origin main

  # 啟動 Green 服務Port 5001
  sudo systemctl restart momo-green
"

# 2. 健康檢查 Green 環境
curl http://localhost:5001/health

# 3. 切換 Nginx 流量到 Green
# 修改 /etc/nginx/sites-available/momo
# proxy_pass http://127.0.0.1:5001;  # 從 5000 切換到 5001

# 4. 重新載入 Nginx無停機
sudo nginx -s reload

# 5. 停止 Blue 環境
sudo systemctl stop momo-blue

優點

  • 完全零停機
  • 可快速回滾(切換回 Blue
  • 可進行 A/B 測試

缺點

  • 需要雙倍資源(兩個服務同時運行)
  • 配置較複雜

5.2 Rolling 更新(簡化版,推薦用於小型專案)

概念:先更新程式碼,然後快速重啟服務。

實作方式(現有 deploy.sh 已實現):

# 1. 備份資料庫
bash ~/momo_pro_system/backup_system.py

# 2. 上傳新程式碼
gcloud compute scp *.py *.html momo-server:~/momo_pro_system/

# 3. 重啟服務Gunicorn graceful reload
sudo systemctl reload momo  # 使用 reload 而非 restart

# 4. 健康檢查
sleep 5
curl http://localhost:5000/health || {
  echo "部署失敗,回滾..."
  # 從備份還原
  bash ~/momo_pro_system/rollback_latest.sh
}

優點

  • 簡單易實作
  • 資源消耗少
  • 適合小型專案

缺點

  • 有短暫停機(約 2-5 秒)
  • 回滾較慢

5.3 建議實作

階段 1立即可行:使用 Rolling 更新 + Gunicorn Graceful Reload

  • 修改 momo.service,使用 ExecReload=/bin/kill -HUP $MAINPID
  • 部署時執行 systemctl reload momo 而非 restart

階段 2長期目標Blue-Green 部署

  • 當業務量增長後,再實作完整的 Blue-Green 部署

6. 密鑰管理

6.1 GitHub Secrets 配置

需要在 GitHub Repository Settings > Secrets 中新增:

Secret 名稱 說明 取得方式
GCP_SA_KEY GCP Service Account JSON 金鑰 在 GCP Console 建立 Service Account 並下載 JSON
GCP_PROJECT_ID GCP 專案 ID GCP Console 查看
GCP_ZONE GCP VM 區域 asia-east1-a
GCP_INSTANCE GCP VM 實例名稱 momo-server
ADMIN_PASSWORD_HASH 管理員密碼雜湊 現有 generate_password_hash.py 生成

6.2 GCP Service Account 權限

需要賦予 Service Account 以下權限:

  • Compute Instance Admin (v1) - 管理 VM
  • Service Account User - 使用 Service Account
  • Storage Object Viewer - 讀取 Cloud Storage如果使用

7. 實作階段規劃

階段 1基礎設施準備1-2 天)

  • 將專案推送到 GitHub 私有倉庫
  • 建立 GCP Service Account 並配置權限
  • 在 GitHub 設定 Secrets
  • 安裝 Self-hosted Runner可選節省成本

階段 2建立測試框架3-5 天)

  • 安裝 pytest 和相關插件
  • 撰寫基本測試(路由測試、資料庫測試)
  • 建立測試數據 fixtures
  • 達到 >60% 測試覆蓋率

階段 3設定 CI Pipeline1-2 天)

  • 建立 .github/workflows/ci.yml
  • 配置程式碼檢查flake8, bandit
  • 配置自動化測試
  • 測試 PR 觸發 CI

階段 4設定 CD Pipeline2-3 天)

  • 建立 .github/workflows/deploy.yml
  • 整合現有 deploy.sh 腳本
  • 實作自動備份機制
  • 實作健康檢查和回滾
  • 測試自動部署流程

階段 5優化與監控持續進行

  • 整合 Prometheus 監控到 CI/CD
  • 設定部署失敗通知Slack / Email
  • 優化部署速度
  • 建立部署文件和 Runbook

總計時間:約 1-2 週(根據團隊經驗調整)


8. 成本分析

8.1 GitHub Actions使用 Self-hosted Runner

  • 費用$0/月(完全免費)
  • 說明:所有 CI/CD 任務在 GCP VM 上執行,不消耗 GitHub 提供的分鐘數

8.2 GitHub Actions使用 GitHub-hosted Runner

  • 免費額度2,000 分鐘/月(私有倉庫)
  • 預估使用
    • 每次 CI: 5 分鐘
    • 每次 CD: 5 分鐘
    • 每月約 100 次部署 = 1,000 分鐘
  • 費用$0/月(在免費額度內)

8.3 GitLab CISelf-hosted

  • 額外 VM 成本$20-50/月(需要額外的 Runner VM
  • 維護成本:需要額外的系統維護時間

8.4 總結

建議使用 GitHub Actions + Self-hosted Runner,完全免費且功能完整。


9. 風險評估

風險 影響 機率 緩解措施
部署失敗導致服務中斷 實作自動回滾機制 + 健康檢查
測試覆蓋不足,未發現 Bug 逐步提升測試覆蓋率至 >80%
GCP Service Account 金鑰洩漏 使用 GitHub Secrets + 定期輪換金鑰
CI/CD Pipeline 執行時間過長 使用 Self-hosted Runner + 快取依賴
資料庫遷移失敗 部署前自動備份 + 測試環境驗證

10. 建議與結論

10.1 核心建議

  1. 採用 GitHub Actions 作為 CI/CD 平台
  2. 使用 Self-hosted Runner 節省成本(完全免費)
  3. 分階段實作,先建立 CI再建立 CD
  4. 優先建立測試框架,確保程式碼品質
  5. 實作自動回滾機制,降低部署風險

10.2 立即可執行的行動

  1. 將專案推送到 GitHub私有倉庫
  2. 建立 tests/ 目錄並撰寫基本測試
  3. 建立 .github/workflows/ci.yml(先實作 CI
  4. 驗證 CI 正常運作後,再建立 deploy.yml(實作 CD

10.3 長期目標

  • 測試覆蓋率 >80%
  • 平均部署時間 <5 分鐘
  • 自動化部署成功率 >95%
  • 零停機部署Blue-Green

附錄

A. 相關文件

B. 參考專案


文件版本1.0 撰寫日期2026-01-14 下次更新:實作完成後更新實際成果和經驗