Files
2026FIFAWorldCup/.gitea/workflows/cd.yaml
wooo 3ff54df247
Some checks failed
2026 World Cup Quant Platform - Production Deployment / Code Quality, Security Gate & Testing (push) Successful in 3m34s
2026 World Cup Quant Platform - Production Deployment / Deploy to Production VM via Gitea CD (push) Failing after 14s
ci: harden production ssh deploy target
2026-06-18 12:11:11 +08:00

171 lines
5.9 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: 2026 World Cup Quant Platform - Production Deployment
on:
push:
branches:
- main
jobs:
test-and-lint:
name: Code Quality, Security Gate & Testing
runs-on: ewoooc-dedicated-runner
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Security policy gate
run: |
set -euo pipefail
echo "== 檢查禁止進入正式部署的臨時維運腳本 =="
forbidden_files="
iwooos_javae_monitor.sh
iwooos_autopatch.py
fix_guardian.py
fix_register.sh
fix_wazuh.sh
ops/harden-host.sh
"
for file in $forbidden_files; do
if [ -e "$file" ]; then
echo "禁止部署:$file 不得存在於正式產品 repo。"
exit 1
fi
done
echo "== 檢查硬編碼密碼、手工 SSH 修補與挖礦 IOC =="
if grep -RInE '(sshpass|sudo -S|WAZUH_PASS\s*=|YOUR_BOT_TOKEN|xmrig|kinsing|kdevtmpfsi|stratum|pool\.supportxmr\.com|221\.156\.167\.200|0936223270|Wooo-0936223270)' \
--exclude-dir=.git \
--exclude-dir=.gitea \
--exclude-dir=node_modules \
--exclude-dir=.next \
--exclude=package-lock.json \
--exclude='*.md' \
.; then
echo "禁止部署:偵測到硬編碼密碼、挖礦 IOC 或手工 SSH 修補痕跡。"
exit 1
fi
- name: Setup Python Environment
run: |
apt-get update -qq
apt-get install -y -qq python3-pip python3-venv
python3 -m venv venv
echo "PATH=$PWD/venv/bin:$PATH" >> $GITHUB_ENV
- name: Install Backend Dependencies
run: |
pip install -r platform/backend/requirements.txt pytest pip-audit
- name: Python dependency audit
run: pip-audit -r platform/backend/requirements.txt
- name: Run Backend Quant Engine Tests
run: |
if find platform/backend -type f \( -name 'test_*.py' -o -name '*_test.py' \) | grep -q .; then
pytest platform/backend
else
echo "未找到後端 pytest 測試檔,改以 Python 編譯檢查作為最低安全閘門。"
python -m compileall -q platform/backend/app
fi
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Frontend Dependencies
run: |
cd platform/web
npm ci --legacy-peer-deps
- name: Frontend dependency audit
run: |
cd platform/web
npm audit --audit-level=high
- name: Run Frontend Linting
run: |
cd platform/web
npm run lint
- name: Validate Docker Compose
env:
DB_PASSWORD: ci-placeholder-db-password
REDIS_PASSWORD: ci-placeholder-redis-password
NEXTAUTH_SECRET: ci-placeholder-nextauth-secret
run: docker compose -f docker-compose.prod.yml config -q
deploy-docker:
name: Deploy to Production VM via Gitea CD
needs: test-and-lint
runs-on: ewoooc-dedicated-runner
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install rsync and ssh
run: apt-get update -qq && apt-get install -y -qq rsync openssh-client
- name: Configure SSH Key
env:
PROD_SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
PROD_SERVER_IP_SECRET: ${{ secrets.PROD_SERVER_IP }}
PROD_SERVER_USER_SECRET: ${{ secrets.PROD_SERVER_USER }}
run: |
set -euo pipefail
PROD_SERVER_IP="${PROD_SERVER_IP_SECRET:-192.168.0.188}"
PROD_SERVER_USER="${PROD_SERVER_USER_SECRET:-ollama}"
if [ -z "$PROD_SERVER_IP" ] || [ -z "$PROD_SERVER_USER" ]; then
echo "禁止部署:正式主機 IP 或使用者未設定。"
exit 1
fi
if [ -z "${PROD_SSH_PRIVATE_KEY:-}" ]; then
echo "禁止部署Gitea secret PROD_SSH_PRIVATE_KEY 未設定。"
exit 1
fi
echo "PROD_SERVER_IP=$PROD_SERVER_IP" >> "$GITHUB_ENV"
echo "PROD_SERVER_USER=$PROD_SERVER_USER" >> "$GITHUB_ENV"
echo "部署目標:$PROD_SERVER_USER@$PROD_SERVER_IP"
mkdir -p ~/.ssh
printf '%s\n' "$PROD_SSH_PRIVATE_KEY" > ~/.ssh/id_deploy
chmod 600 ~/.ssh/id_deploy
ssh-keyscan -T 10 "$PROD_SERVER_IP" >> ~/.ssh/known_hosts
- name: Sync Files to Production
run: |
set -euo pipefail
printf "%s\n" "${{ github.sha }}" > REVISION
rsync -az --delete --delay-updates -e "ssh -i ~/.ssh/id_deploy" \
--exclude='.git/' \
--exclude='.gitea/' \
--exclude='node_modules/' \
--exclude='.next/' \
--exclude='venv/' \
--exclude='__pycache__/' \
--exclude='.env' \
./ "$PROD_SERVER_USER@$PROD_SERVER_IP:/opt/fifa2026/current/"
- name: Restart Docker Containers
run: |
set -euo pipefail
ssh -i ~/.ssh/id_deploy "$PROD_SERVER_USER@$PROD_SERVER_IP" 'bash -se' <<'DEPLOY_SCRIPT'
set -euo pipefail
echo "[Deploy] Starting deployment for 2026fifa.wooo.work"
cd /opt/fifa2026/current
for file in iwooos_javae_monitor.sh iwooos_autopatch.py fix_guardian.py fix_register.sh fix_wazuh.sh ops/harden-host.sh; do
if [ -e "$file" ]; then
echo "[Deploy] Forbidden emergency script still exists on production: $file"
exit 1
fi
done
docker compose -f docker-compose.prod.yml config -q
docker compose -f docker-compose.prod.yml build --pull
docker compose -f docker-compose.prod.yml up -d --remove-orphans
docker image prune -f
echo "[Deploy] Deployment completed successfully."
DEPLOY_SCRIPT