Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 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>
18 KiB
18 KiB
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,理由:
- 免費額度充足(2,000 分鐘 + Self-hosted Runner 無限制)
- 與 GitHub 生態系統整合度高
- 學習成本低,快速上手
- 可在現有 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)- 管理 VMService Account User- 使用 Service AccountStorage 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 Pipeline(1-2 天)
- 建立
.github/workflows/ci.yml - 配置程式碼檢查(flake8, bandit)
- 配置自動化測試
- 測試 PR 觸發 CI
階段 4:設定 CD Pipeline(2-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 CI(Self-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 核心建議
- 採用 GitHub Actions 作為 CI/CD 平台
- 使用 Self-hosted Runner 節省成本(完全免費)
- 分階段實作,先建立 CI,再建立 CD
- 優先建立測試框架,確保程式碼品質
- 實作自動回滾機制,降低部署風險
10.2 立即可執行的行動
- 將專案推送到 GitHub(私有倉庫)
- 建立
tests/目錄並撰寫基本測試 - 建立
.github/workflows/ci.yml(先實作 CI) - 驗證 CI 正常運作後,再建立
deploy.yml(實作 CD)
10.3 長期目標
- 測試覆蓋率 >80%
- 平均部署時間 <5 分鐘
- 自動化部署成功率 >95%
- 零停機部署(Blue-Green)
附錄
A. 相關文件
B. 參考專案
文件版本:1.0 撰寫日期:2026-01-14 下次更新:實作完成後更新實際成果和經驗