feat: 添加自动化部署方案(Docker + 远程服务器两套方案)
- 新增 deploy/docker/:Docker 本机模拟部署,含 Dockerfile、docker-compose、deploy.sh 一键脚本 - 新增 deploy/remote/:远程服务器部署,含 SSH 自动上传、重启、回滚脚本 - 新增 deploy/README.md:完整使用手册,含现状分析、落地调整工作清单、命令速查 - 新增 build.sh/start.sh:本地构建和启动脚本(含飞书通知) - 新增前端 .env.docker 环境配置,API 指向测试服务器 - 前端 package.json 新增 build-docker 命令 - 更新 .gitignore:排除 IDE 配置、SQL 数据、Docker 敏感文件 - 前端 UI 样式优化(多个页面组件) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
237
build.sh
Executable file
237
build.sh
Executable file
@@ -0,0 +1,237 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# SmartClean 构建打包脚本(带飞书通知)
|
||||
# 用法:
|
||||
# ./build.sh # 构建所有模块(public + web + task + frontend)
|
||||
# ./build.sh web # 仅构建后端 web (含 public)
|
||||
# ./build.sh task # 仅构建后端 task (含 public)
|
||||
# ./build.sh backend # 构建后端 web + task
|
||||
# ./build.sh front # 仅构建前端
|
||||
# ./build.sh front-test # 构建前端测试环境包
|
||||
|
||||
# ===== 飞书 Webhook 配置 =====
|
||||
FEISHU_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/5703e8cc-6998-46a6-af9d-8c5102cc8c1e"
|
||||
|
||||
# ===== 初始化 =====
|
||||
export SDKMAN_DIR="$HOME/.sdkman"
|
||||
source "$SDKMAN_DIR/bin/sdkman-init.sh"
|
||||
sdk use java 8.0.432-zulu > /dev/null 2>&1
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PUBLIC_DIR="$ROOT_DIR/backend/xiaoqu-intellectual-public"
|
||||
WEB_DIR="$ROOT_DIR/backend/xiaoqu-intellectual-web"
|
||||
TASK_DIR="$ROOT_DIR/backend/xiaoqu-intellectual-task"
|
||||
FRONT_DIR="$ROOT_DIR/frontend/witcleansystem"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
BUILD_START_TIME=$(date +%s)
|
||||
BUILD_RESULTS=()
|
||||
HAS_ERROR=0
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# ===== 飞书通知函数 =====
|
||||
send_feishu_notify() {
|
||||
local title="$1"
|
||||
local content="$2"
|
||||
local color="$3" # green / red / yellow
|
||||
|
||||
# 构建富文本消息
|
||||
local json_content
|
||||
json_content=$(cat <<EOJSON
|
||||
{
|
||||
"msg_type": "interactive",
|
||||
"card": {
|
||||
"header": {
|
||||
"title": {
|
||||
"tag": "plain_text",
|
||||
"content": "$title"
|
||||
},
|
||||
"template": "$color"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"tag": "markdown",
|
||||
"content": "$content"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
EOJSON
|
||||
)
|
||||
|
||||
curl -s -X POST "$FEISHU_WEBHOOK" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$json_content" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
# ===== 构建函数 =====
|
||||
build_public() {
|
||||
log_info "编译 public 模块..."
|
||||
local start=$(date +%s)
|
||||
cd "$PUBLIC_DIR"
|
||||
local output
|
||||
output=$(mvn clean install -q -DskipTests 2>&1)
|
||||
local rc=$?
|
||||
local elapsed=$(( $(date +%s) - start ))
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
log_info "public 模块编译成功 (${elapsed}s)"
|
||||
BUILD_RESULTS+=("✅ **public 模块** — 编译成功 (${elapsed}s)")
|
||||
else
|
||||
log_error "public 模块编译失败"
|
||||
HAS_ERROR=1
|
||||
BUILD_RESULTS+=("❌ **public 模块** — 编译失败 (${elapsed}s)")
|
||||
BUILD_RESULTS+=("错误信息: $(echo "$output" | tail -5 | sed 's/"/\\"/g')")
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_web() {
|
||||
log_info "打包 Web 服务 (ROOT.war)..."
|
||||
local start=$(date +%s)
|
||||
cd "$WEB_DIR"
|
||||
local output
|
||||
output=$(mvn clean package -q -DskipTests 2>&1)
|
||||
local rc=$?
|
||||
local elapsed=$(( $(date +%s) - start ))
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
local war_file="$WEB_DIR/target/ROOT.war"
|
||||
local war_size=""
|
||||
if [ -f "$war_file" ]; then
|
||||
war_size=" | 文件大小: $(du -h "$war_file" | cut -f1)"
|
||||
fi
|
||||
log_info "Web 服务打包成功 (${elapsed}s)$war_size"
|
||||
BUILD_RESULTS+=("✅ **Web 服务 (ROOT.war)** — 打包成功 (${elapsed}s)$war_size")
|
||||
else
|
||||
log_error "Web 服务打包失败"
|
||||
HAS_ERROR=1
|
||||
BUILD_RESULTS+=("❌ **Web 服务** — 打包失败 (${elapsed}s)")
|
||||
BUILD_RESULTS+=("错误信息: $(echo "$output" | tail -5 | sed 's/"/\\"/g')")
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_task() {
|
||||
log_info "打包 Task 服务..."
|
||||
local start=$(date +%s)
|
||||
cd "$TASK_DIR"
|
||||
local output
|
||||
output=$(mvn clean package -q -DskipTests 2>&1)
|
||||
local rc=$?
|
||||
local elapsed=$(( $(date +%s) - start ))
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
log_info "Task 服务打包成功 (${elapsed}s)"
|
||||
BUILD_RESULTS+=("✅ **Task 服务** — 打包成功 (${elapsed}s)")
|
||||
else
|
||||
log_error "Task 服务打包失败"
|
||||
HAS_ERROR=1
|
||||
BUILD_RESULTS+=("❌ **Task 服务** — 打包失败 (${elapsed}s)")
|
||||
BUILD_RESULTS+=("错误信息: $(echo "$output" | tail -5 | sed 's/"/\\"/g')")
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_front() {
|
||||
local mode="${1:-build}" # build 或 build-test
|
||||
local mode_label="生产"
|
||||
[ "$mode" = "build-test" ] && mode_label="测试"
|
||||
|
||||
log_info "构建前端 (${mode_label}环境)..."
|
||||
local start=$(date +%s)
|
||||
cd "$FRONT_DIR"
|
||||
|
||||
if [ ! -d "node_modules" ]; then
|
||||
log_warn "未检测到 node_modules, 正在安装依赖..."
|
||||
npm install
|
||||
fi
|
||||
|
||||
local output
|
||||
output=$(npm run "$mode" 2>&1)
|
||||
local rc=$?
|
||||
local elapsed=$(( $(date +%s) - start ))
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
log_info "前端构建成功 (${mode_label}, ${elapsed}s)"
|
||||
BUILD_RESULTS+=("✅ **前端 (${mode_label})** — 构建成功 (${elapsed}s)")
|
||||
else
|
||||
log_error "前端构建失败"
|
||||
HAS_ERROR=1
|
||||
BUILD_RESULTS+=("❌ **前端 (${mode_label})** — 构建失败 (${elapsed}s)")
|
||||
BUILD_RESULTS+=("错误信息: $(echo "$output" | tail -5 | sed 's/"/\\"/g')")
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ===== 发送构建汇总通知 =====
|
||||
send_build_summary() {
|
||||
local total_elapsed=$(( $(date +%s) - BUILD_START_TIME ))
|
||||
local branch=$(cd "$ROOT_DIR" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
local commit=$(cd "$ROOT_DIR" && git log -1 --format='%h %s' 2>/dev/null || echo "unknown")
|
||||
local build_target="${1:-all}"
|
||||
local hostname=$(hostname)
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
local status_emoji="✅"
|
||||
local title_status="成功"
|
||||
local color="green"
|
||||
if [ $HAS_ERROR -ne 0 ]; then
|
||||
status_emoji="❌"
|
||||
title_status="失败"
|
||||
color="red"
|
||||
fi
|
||||
|
||||
# 拼接结果列表
|
||||
local detail=""
|
||||
for item in "${BUILD_RESULTS[@]}"; do
|
||||
detail="${detail}\n${item}"
|
||||
done
|
||||
|
||||
local content="**构建目标:** ${build_target}\\n**分支:** ${branch}\\n**最新提交:** ${commit}\\n**构建机器:** ${hostname}\\n**时间:** ${timestamp}\\n**总耗时:** ${total_elapsed}s\\n\\n---\\n${detail}"
|
||||
|
||||
send_feishu_notify "${status_emoji} SmartClean 构建${title_status}" "$content" "$color"
|
||||
log_info "飞书通知已发送"
|
||||
}
|
||||
|
||||
# ===== 主流程 =====
|
||||
TARGET="${1:-all}"
|
||||
|
||||
case "$TARGET" in
|
||||
web)
|
||||
build_public && build_web
|
||||
;;
|
||||
task)
|
||||
build_public && build_task
|
||||
;;
|
||||
backend)
|
||||
build_public && build_web && build_task
|
||||
;;
|
||||
front)
|
||||
build_front "build"
|
||||
;;
|
||||
front-test)
|
||||
build_front "build-test"
|
||||
;;
|
||||
all)
|
||||
build_public && build_web && build_task
|
||||
build_front "build"
|
||||
;;
|
||||
*)
|
||||
echo "用法: $0 {all|web|task|backend|front|front-test}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
send_build_summary "$TARGET"
|
||||
|
||||
if [ $HAS_ERROR -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user