250 lines
8.1 KiB
YAML
250 lines
8.1 KiB
YAML
name: Deploy to Production
|
||
|
||
on:
|
||
push:
|
||
branches:
|
||
- main
|
||
workflow_dispatch: # 允许手动触发
|
||
|
||
env:
|
||
DEPLOY_PATH: /home/atai/kt-financial-system
|
||
APP_NAME: kt-financial-system
|
||
HEALTH_CHECK_URL: http://172.16.74.149:8080
|
||
|
||
jobs:
|
||
build-and-test:
|
||
name: Build and Test
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v3
|
||
with:
|
||
fetch-depth: 0 # 获取完整历史,用于版本号生成
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v3
|
||
with:
|
||
node-version: '20'
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v2
|
||
with:
|
||
version: 9
|
||
|
||
- name: Get pnpm store directory
|
||
id: pnpm-cache
|
||
shell: bash
|
||
run: |
|
||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||
|
||
- name: Setup pnpm cache
|
||
uses: actions/cache@v3
|
||
with:
|
||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||
restore-keys: |
|
||
${{ runner.os }}-pnpm-store-
|
||
|
||
- name: Install dependencies
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Build project
|
||
run: pnpm build
|
||
|
||
- name: Run tests
|
||
run: pnpm test:unit || echo "No tests configured"
|
||
continue-on-error: true
|
||
|
||
deploy:
|
||
name: Deploy to Server
|
||
runs-on: ubuntu-latest
|
||
needs: build-and-test
|
||
|
||
steps:
|
||
- name: Deploy to server
|
||
uses: appleboy/ssh-action@v1.0.0
|
||
with:
|
||
host: ${{ secrets.SERVER_HOST || '172.16.74.149' }}
|
||
username: ${{ secrets.SERVER_USER || 'atai' }}
|
||
password: ${{ secrets.SERVER_PASSWORD || 'wengewudi666808' }}
|
||
port: ${{ secrets.SERVER_PORT || '22' }}
|
||
command_timeout: 30m
|
||
script: |
|
||
set -e # 遇到错误立即退出
|
||
|
||
echo "🚀 开始部署 KT财务系统..."
|
||
|
||
# 设置部署路径
|
||
DEPLOY_PATH="${DEPLOY_PATH}"
|
||
|
||
# 切换到部署目录
|
||
cd /home/atai
|
||
|
||
# 如果目录不存在,克隆仓库
|
||
if [ ! -d "kt-financial-system" ]; then
|
||
echo "📥 克隆代码仓库..."
|
||
git clone https://gitea.ktyun.cc/chenjiangjiang/kt-financial-system.git
|
||
cd kt-financial-system
|
||
else
|
||
cd kt-financial-system
|
||
|
||
# 保存当前版本信息
|
||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
||
echo "📌 当前版本: $CURRENT_COMMIT"
|
||
|
||
# 拉取最新代码
|
||
echo "📥 拉取最新代码..."
|
||
git fetch origin main
|
||
git reset --hard origin/main
|
||
|
||
NEW_COMMIT=$(git rev-parse HEAD)
|
||
echo "📌 新版本: $NEW_COMMIT"
|
||
|
||
if [ "$CURRENT_COMMIT" = "$NEW_COMMIT" ]; then
|
||
echo "ℹ️ 代码无变化,跳过部署"
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
# 显示最新提交信息
|
||
echo "📝 最新提交:"
|
||
git log -1 --pretty=format:"%h - %an: %s" || true
|
||
|
||
# 停止旧容器(保留数据卷)
|
||
echo "🛑 停止旧容器..."
|
||
sudo docker-compose down || true
|
||
|
||
# 构建新镜像
|
||
echo "🏗️ 构建新镜像..."
|
||
sudo docker-compose build --no-cache
|
||
|
||
# 启动新容器
|
||
echo "🚀 启动新容器..."
|
||
sudo docker-compose up -d
|
||
|
||
# 等待服务启动
|
||
echo "⏳ 等待服务启动..."
|
||
sleep 10
|
||
|
||
# 确认PostgreSQL已就绪
|
||
echo "⏳ 等待PostgreSQL就绪..."
|
||
POSTGRES_READY=0
|
||
for i in {1..10}; do
|
||
if sudo docker-compose exec -T postgres pg_isready -U kt_financial -d kt_financial > /dev/null 2>&1; then
|
||
echo "✅ PostgreSQL 已就绪"
|
||
POSTGRES_READY=1
|
||
break
|
||
fi
|
||
echo " 第${i}次重试..."
|
||
sleep 3
|
||
done
|
||
if [ "$POSTGRES_READY" -ne 1 ]; then
|
||
echo "❌ PostgreSQL 未在预期时间内就绪"
|
||
exit 1
|
||
fi
|
||
|
||
# 导入财务交易数据
|
||
echo "📦 导入财务数据..."
|
||
sudo docker-compose exec -T kt-financial \
|
||
bash -lc "pnpm --filter @vben/backend import:data -- --csv /app/data/finance/finance-combined.csv --year 2025"
|
||
|
||
# 验证数据条数
|
||
echo "🔢 检查交易记录条数..."
|
||
sudo docker-compose exec -T postgres \
|
||
psql -U kt_financial -d kt_financial -c "SELECT COUNT(*) AS transaction_count FROM finance_transactions;"
|
||
|
||
# 1. 检查容器状态
|
||
echo "📊 容器状态:"
|
||
sudo docker-compose ps
|
||
|
||
# 2. 检查端口占用情况
|
||
echo ""
|
||
echo "🔍 检查端口8080占用:"
|
||
sudo lsof -i :8080 || echo "端口8080未被占用"
|
||
|
||
# 3. 检查容器内部监听情况
|
||
echo ""
|
||
echo "🔍 检查容器内部监听:"
|
||
CONTAINER_ID=$(sudo docker-compose ps -q kt-financial 2>/dev/null || echo "")
|
||
if [ -n "$CONTAINER_ID" ]; then
|
||
sudo docker exec $CONTAINER_ID ss -tlnp | grep ':80' || echo "容器内无80端口监听"
|
||
fi
|
||
|
||
# 4. 检查容器详细日志(增加行数)
|
||
echo ""
|
||
echo "📝 容器日志(最近100行):"
|
||
sudo docker-compose logs --tail=100
|
||
|
||
# 5. 检查容器健康状态
|
||
echo ""
|
||
echo "🏥 容器健康检查:"
|
||
sudo docker inspect --format='{{.State.Health.Status}}' $CONTAINER_ID 2>/dev/null || echo "未配置健康检查"
|
||
|
||
# 清理旧镜像和悬空镜像
|
||
echo ""
|
||
echo "🧹 清理旧镜像..."
|
||
sudo docker image prune -f
|
||
|
||
echo "✅ 部署完成!"
|
||
|
||
- name: Health Check
|
||
if: success()
|
||
uses: appleboy/ssh-action@v1.0.0
|
||
with:
|
||
host: ${{ secrets.SERVER_HOST || '172.16.74.149' }}
|
||
username: ${{ secrets.SERVER_USER || 'atai' }}
|
||
password: ${{ secrets.SERVER_PASSWORD || 'wengewudi666808' }}
|
||
port: ${{ secrets.SERVER_PORT || '22' }}
|
||
command_timeout: 10m
|
||
script: |
|
||
set -e
|
||
echo "🔍 执行健康检查..."
|
||
sleep 20
|
||
|
||
for i in {1..10}; do
|
||
echo ""
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
echo "尝试 ${i}/10: 检查服务 ${{ env.HEALTH_CHECK_URL }}"
|
||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||
|
||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 ${{ env.HEALTH_CHECK_URL }} || true)
|
||
echo "响应: ${HTTP_CODE}"
|
||
|
||
if printf "%s" "$HTTP_CODE" | grep -qE "200|301|302"; then
|
||
echo "✅ 服务健康检查通过!HTTP状态码正常"
|
||
echo ""
|
||
echo "🎉 部署成功!服务已正常运行"
|
||
exit 0
|
||
fi
|
||
|
||
if [ "$i" -eq 5 ]; then
|
||
echo ""
|
||
echo "⚠️ 第5次尝试失败,执行深度诊断..."
|
||
echo ""
|
||
echo "🔍 检查容器运行状态:"
|
||
cd /home/atai/kt-financial-system
|
||
sudo docker-compose ps || true
|
||
echo ""
|
||
echo "📝 最新容器日志:"
|
||
sudo docker-compose logs --tail=50 || true
|
||
fi
|
||
|
||
sleep 6
|
||
done
|
||
|
||
echo ""
|
||
echo "❌ 服务健康检查失败:无法在多次重试后获得 200/301/302 响应"
|
||
exit 1
|
||
|
||
- name: Send notification on success
|
||
if: success()
|
||
run: |
|
||
echo "✅ 部署成功!"
|
||
echo "🌐 访问地址: ${{ env.HEALTH_CHECK_URL }}"
|
||
|
||
- name: Send notification on failure
|
||
if: failure()
|
||
run: |
|
||
echo "❌ 部署失败!请检查日志"
|