build.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #!/bin/bash
  2. # 功能:
  3. # 非交互式用法:
  4. # ./build.sh <环境编号> [更新Excel] [发布]
  5. # 示例:
  6. # ./build.sh 1 1 0 # 使用当前分支,构建dev环境,更新Excel并导表,不发布
  7. # make build 1 1 0
  8. # 参数说明:
  9. # <环境编号> : 1=dev, 2=test, 3=dev&test, 4=prod
  10. # [更新Excel]: y/Y/1 表示更新并导表,其他值或省略表示跳过
  11. # [发布] : y/Y/1 表示 push 发布仓库,其他值或省略表示跳过
  12. # 特点:
  13. # - 默认使用当前 git 分支
  14. # - 全程无需交互输入,适合脚本/CI 调用
  15. #
  16. # 交互式用法:
  17. # ./build.sh
  18. # 交互步骤:
  19. # 1) 选择代码分支(默认当前分支),如选择其他分支则执行 git 切换
  20. # 2) 选择是否更新 Excel 仓库及 commit/hash/branch,并在该引用上执行导表
  21. # 并将生成/输出文件复制到项目的 etc/data 和 etc/data_map 下
  22. # 3) 选择构建类型(dev/test/prod)
  23. # 4) 选择是否将 publish 内容推送到发布仓库
  24. #
  25. # 注意:
  26. # - 假定脚本位于 e:\f1\server\etc\script 中,脚本会自动切换到仓库根目录以进行 git 操作
  27. PUBLISH_GIT_URL="ssh://git@git.chun-pu.com:9022/f1/server-publish.git"
  28. EXCEL_GIT_URL="ssh://git@git.chun-pu.com:9022/f1/excel.git"
  29. _tmp_dirs=()
  30. cleanup() {
  31. for d in "${_tmp_dirs[@]:-}"; do
  32. [[ -d "$d" ]] && rm -rf "$d"
  33. done
  34. return 0
  35. }
  36. trap cleanup EXIT
  37. # 检查并进入仓库根目录
  38. repo_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
  39. if [[ -z "$repo_root" ]]; then
  40. echo "未检测到 git 仓库,请在项目仓库内运行此脚本。"
  41. exit 1
  42. fi
  43. cd "$repo_root"
  44. build_arg="${1:-}" #分支id
  45. update_excel_arg="${2:-}" #是否更新excel
  46. do_publish_arg="${3:-}" #是否发布到仓库
  47. noninteractive=false
  48. if [[ -n "$build_arg" ]]; then
  49. noninteractive=true
  50. fi
  51. # 1) 分支选择与切换(默认当前分支)
  52. repo_branch_current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
  53. if $noninteractive; then
  54. target_branch="$repo_branch_current"
  55. echo "非交互模式:使用当前分支 ${target_branch}"
  56. else
  57. read -p "请输入要编译的分支(回车使用当前分支 ${repo_branch_current}): " target_branch
  58. target_branch=${target_branch:-$repo_branch_current}
  59. fi
  60. if [[ "$target_branch" != "$repo_branch_current" ]]; then
  61. echo "切换到分支 ${target_branch} ..."
  62. git fetch origin || true
  63. if git rev-parse --verify --quiet "refs/heads/${target_branch}"; then
  64. git checkout "$target_branch"
  65. git pull origin "$target_branch" --rebase || true
  66. repo_branch_current=$(git rev-parse --abbrev-ref HEAD)
  67. echo "当前分支: ${repo_branch_current}"
  68. else
  69. echo "不存在该分支,脚本终止。"
  70. exit 1
  71. fi
  72. fi
  73. # 获取当前分支的 hash
  74. repo_hash=$(git rev-parse HEAD 2>/dev/null || true)
  75. repo_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
  76. # 2) Excel 导表:询问是否需要更新Excel,回车默认跳过
  77. if $noninteractive; then
  78. case "$update_excel_arg" in
  79. y|Y|1)
  80. update_excel="y"
  81. ;;
  82. *)
  83. update_excel=""
  84. ;;
  85. esac
  86. echo "非交互模式:Excel 更新选项: ${update_excel:-跳过}"
  87. else
  88. read -p "是否需要更新 Excel 仓库?(y/n,回车跳过) " update_excel
  89. fi
  90. excel_hash=""
  91. excel_branch=""
  92. if [[ "$update_excel" =~ ^[Yy]$ ]]; then
  93. excel_tmp="$repo_root/_excel/"
  94. if [[ -d "$repo_root/_excel/" ]]; then
  95. echo "检测到已存在的 Excel 仓库,执行更新..."
  96. cd "$excel_tmp" || {
  97. echo "进入 Excel 仓库失败:${excel_tmp}"
  98. exit 2
  99. }
  100. git pull --rebase || true
  101. else
  102. git clone "$EXCEL_GIT_URL" "$excel_tmp" || {
  103. echo "克隆 Excel 仓库失败:${EXCEL_GIT_URL}"
  104. exit 2
  105. }
  106. cd "$excel_tmp" || {
  107. echo "进入 Excel 仓库失败:${excel_tmp}"
  108. exit 2
  109. }
  110. fi
  111. # 提示输入分支号,回车使用远程默认分支
  112. if $noninteractive; then
  113. excel_ref=""
  114. else
  115. read -p "请输入 Excel 仓库的 commit/hash/branch(回车使用远程默认分支): " excel_ref
  116. fi
  117. if [[ -z "${excel_ref}" ]]; then
  118. # 使用远程默认分支
  119. default_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
  120. if [[ -n "$default_branch" ]]; then
  121. echo "未输入引用,使用默认分支: ${default_branch}"
  122. else
  123. echo "默认分支未找到,终止脚本。"
  124. exit 2
  125. fi
  126. else
  127. # 输入了引用,尝试检出:优先当作本地/commit/short-hash,再尝试远程分支/标签
  128. echo "尝试检出指定引用: ${excel_ref} ..."
  129. if git rev-parse --verify --quiet "$excel_ref"; then
  130. git checkout -f "$excel_ref"
  131. else
  132. echo "无法检出指定引用: ${excel_ref},请确认输入是否正确"
  133. exit 2
  134. fi
  135. fi
  136. excel_hash=$(git rev-parse HEAD 2>/dev/null || true)
  137. excel_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
  138. echo "当前 Excel 仓库位于: ${excel_branch}"
  139. else
  140. echo "跳过 Excel 更新"
  141. fi
  142. # 执行导表,输出到output目录
  143. if [[ -n "$update_excel" ]] && [[ "$update_excel" =~ ^[Yy]$ ]]; then
  144. if [[ -f "$repo_root/_excel/bin/ee_linux" ]]; then
  145. echo "检测到 $repo_root/_excel/bin/ee_linux,开始执行导表..."
  146. cd "$repo_root/_excel/bin/" || true
  147. if [[ "$(uname -s)" == "MINGW"* ]]; then
  148. ./ee.exe --path=./server.json
  149. else
  150. ./ee_linux --path=./server.json
  151. fi
  152. echo "导表完成,复制生成的文件到项目..."
  153. cp -r "$repo_root/_excel/output/server_go/"* "$repo_root/internal/data/" 2>/dev/null || true
  154. cp -r "$repo_root/_excel/output/server_json/"* "$repo_root/etc/data/" 2>/dev/null || true
  155. cp -r "$repo_root/_excel/data_map/"* "$repo_root/etc/data_map/" 2>/dev/null || true
  156. else
  157. echo "$repo_root/_excel/bin/ee_linux 未找到,导表失败。"
  158. exit 2
  159. fi
  160. else
  161. echo "跳过导表步骤"
  162. fi
  163. cd "$repo_root" || true
  164. # 3) 编译源代码
  165. os_name=$(expr substr $(uname -s) 1 5 || true)
  166. build_user=$(whoami || true)
  167. build_time=$(date +"%Y-%m-%d %H:%M:%S" || true)
  168. publish_dir="$repo_root/publish"
  169. publish_dir_etc="${publish_dir}/etc/"
  170. publish_dir_etc_data="${publish_dir_etc}data/"
  171. publish_dir_etc_data_map="${publish_dir_etc}data_map/"
  172. publish_dir_etc_lua="${publish_dir_etc}lua/"
  173. publish_dir_etc_profile="${publish_dir_etc}profile/"
  174. publish_dir_etc_profile_include="${publish_dir_etc}profile/include/"
  175. main_file="$repo_root/nodes/main.go"
  176. # 回到 etc/script 以保持原相对路径引用
  177. cd "$repo_root/etc/script" || true
  178. # 构建相关函数(基于原脚本逻辑,使用绝对路径读取数据/文件)
  179. function clean_publish() {
  180. rm -rf "$publish_dir" 2>/dev/null || true
  181. mkdir -p "$publish_dir" "$publish_dir_etc" "$publish_dir_etc_data" "$publish_dir_etc_data_map" "$publish_dir_etc_lua" "$publish_dir_etc_profile"
  182. }
  183. function go_build() {
  184. local outname="$1"
  185. f_repo_hash="'f1-game/internal/version.RepoHash=${repo_hash}'"
  186. f_repo_branch="'f1-game/internal/version.RepoBranch=${repo_branch}'"
  187. f_excel_hash="'f1-game/internal/version.ExcelHash=${excel_hash}'"
  188. f_excel_branch="'f1-game/internal/version.ExcelBranch=${excel_branch}'"
  189. f_build_user="'f1-game/internal/version.BuildUser=${build_user}'"
  190. f_build_time="'f1-game/internal/version.BuildTime=${build_time}'"
  191. echo "[BUILD-${number}] ${f_repo_hash}"
  192. echo "[BUILD-${number}] ${f_repo_branch}"
  193. echo "[BUILD-${number}] ${f_excel_hash}"
  194. echo "[BUILD-${number}] ${f_excel_branch}"
  195. echo "[BUILD-${number}] ${f_build_user}"
  196. echo "[BUILD-${number}] ${f_build_time}"
  197. # 使用 $repo_root 相对的 main_file
  198. go build -ldflags "-X ${f_repo_hash} -X ${f_repo_branch} -X ${f_excel_hash} -X ${f_excel_branch} -X ${f_build_user} -X ${f_build_time}" -o "$publish_dir/${outname}" "$repo_root/nodes/main.go"
  199. echo "[BUILD-${number}] go build complete!"
  200. echo ""
  201. }
  202. function copy_etc_files() {
  203. echo "[BUILD-${number}] copy etc files."
  204. mkdir -p "$publish_dir_etc_data" "$publish_dir_etc_data_map" "$publish_dir_etc_lua" || true
  205. cp -r "$repo_root/etc/data/"* "$publish_dir_etc_data" 2>/dev/null || true
  206. cp -r "$repo_root/etc/data_embed/"* "$publish_dir_etc_data" 2>/dev/null || true
  207. cp -r "$repo_root/etc/data_map/"* "$publish_dir_etc_data_map" 2>/dev/null || true
  208. cp -r "$repo_root/etc/lua/"* "$publish_dir_etc_lua" 2>/dev/null || true
  209. }
  210. function build_dev() {
  211. clean_publish
  212. echo "[BUILD-${number}] dev profile..."
  213. export CGO_ENABLED=0
  214. export GOOS=linux
  215. export GOARCH=amd64
  216. go_build "node"
  217. copy_etc_files
  218. echo "[BUILD-${number}] copy profile include files."
  219. cp -r "$repo_root/etc/profile/include" "$publish_dir_etc_profile" 2>/dev/null || true
  220. echo "[BUILD-${number}] copy linux files."
  221. cp "$repo_root/etc/profile/dev.json" "$publish_dir_etc_profile" 2>/dev/null || true
  222. cp "$repo_root/etc/cli/cli.sh" "$publish_dir" 2>/dev/null || true
  223. cp "$repo_root/etc/cli/docker.sh" "$publish_dir" 2>/dev/null || true
  224. cp -r "$repo_root/tool/bin/"* "$publish_dir" 2>/dev/null || true
  225. cp "$repo_root/etc/docker/dev.yaml" "$publish_dir" 2>/dev/null || true
  226. cp "$repo_root/etc/docker/db.yaml" "$publish_dir" 2>/dev/null || true
  227. echo "[BUILD-${number}] exit."
  228. }
  229. function build_test() {
  230. clean_publish
  231. echo "[BUILD-${number}] test profile..."
  232. export CGO_ENABLED=0
  233. export GOOS=linux
  234. export GOARCH=amd64
  235. go_build "node"
  236. copy_etc_files
  237. echo "[BUILD-${number}] copy profile files."
  238. cp "$repo_root/etc/profile/test.json" "$publish_dir_etc_profile" 2>/dev/null || true
  239. echo "[BUILD-${number}] copy run script files."
  240. cp "$repo_root/etc/cli/docker.sh" "$publish_dir" 2>/dev/null || true
  241. cp -r "$repo_root/tool/bin/"* "$publish_dir" 2>/dev/null || true
  242. cp -r "$repo_root/etc/docker/test.yaml" "$publish_dir/test.yaml" 2>/dev/null || true
  243. cp "$repo_root/etc/docker/db.yaml" "$publish_dir" 2>/dev/null || true
  244. echo "[BUILD-${number}] exit."
  245. }
  246. function build_dev_test() {
  247. clean_publish
  248. echo "[BUILD-${number}] dev & test profile..."
  249. export CGO_ENABLED=0
  250. export GOOS=linux
  251. export GOARCH=amd64
  252. go_build "node"
  253. copy_etc_files
  254. echo "[BUILD-${number}] copy profile files."
  255. cp -r "$repo_root/etc/profile/include" "$publish_dir_etc_profile" 2>/dev/null || true
  256. cp "$repo_root/etc/profile/dev.json" "$publish_dir_etc_profile" 2>/dev/null || true
  257. cp "$repo_root/etc/profile/test.json" "$publish_dir_etc_profile" 2>/dev/null || true
  258. echo "[BUILD-${number}] copy run script files."
  259. cp "$repo_root/etc/cli/docker.sh" "$publish_dir" 2>/dev/null || true
  260. cp -r "$repo_root/tool/bin/"* "$publish_dir" 2>/dev/null || true
  261. cp -r "$repo_root/etc/docker/dev.yaml" "$publish_dir/dev.yaml" 2>/dev/null || true
  262. cp -r "$repo_root/etc/docker/test.yaml" "$publish_dir/test.yaml" 2>/dev/null || true
  263. cp "$repo_root/etc/docker/db.yaml" "$publish_dir" 2>/dev/null || true
  264. echo "[BUILD-${number}] exit."
  265. }
  266. # 若需,可实现 build_prod
  267. function build_prod() {
  268. clean_publish
  269. echo "[BUILD-${number}] prod profile..."
  270. export CGO_ENABLED=0
  271. export GOOS=linux
  272. export GOARCH=amd64
  273. go_build "node"
  274. copy_etc_files
  275. echo "[BUILD-${number}] copy profile files."
  276. cp "$repo_root/etc/profile/prod.json" "$publish_dir_etc_profile" 2>/dev/null || true
  277. cp -r "$repo_root/etc/profile/include" "$publish_dir_etc_profile" 2>/dev/null || true
  278. cp "$repo_root/etc/cli/cli.sh" "$publish_dir" 2>/dev/null || true
  279. cp -r "$repo_root/tool/bin/"* "$publish_dir" 2>/dev/null || true
  280. cp "$repo_root/etc/docker/prod.yaml" "$publish_dir" 2>/dev/null || true
  281. cp "$repo_root/etc/docker/db.yaml" "$publish_dir" 2>/dev/null || true
  282. echo "[BUILD-${number}] exit."
  283. }
  284. echo "------------------------------------------------------"
  285. echo "OS Name : ${os_name}"
  286. echo "Code Path : ${repo_root}"
  287. echo "Repo Hash : ${repo_hash}"
  288. echo "Repo Branch : ${repo_branch}"
  289. echo "Excel Hash : ${excel_hash}"
  290. echo "Excel Branch : ${excel_branch}"
  291. echo "Build User : ${build_user}"
  292. echo "Build Time : ${build_time}"
  293. echo "------------------------------------------------------"
  294. echo ""
  295. if $noninteractive; then
  296. number="$build_arg"
  297. echo "非交互模式:构建环境编号: ${number}"
  298. echo ""
  299. else
  300. echo "请选择构建的环境:"
  301. echo "[1] dev"
  302. echo "[2] test"
  303. echo "[3] dev & test"
  304. echo "[4] prod"
  305. echo "[9] exit"
  306. echo ""
  307. read -p "请输入选项编号: " number
  308. echo ""
  309. fi
  310. case $number in
  311. 1)
  312. build_dev
  313. ;;
  314. 2)
  315. build_test
  316. ;;
  317. 3)
  318. build_dev_test
  319. ;;
  320. 4)
  321. build_prod
  322. ;;
  323. 9)
  324. echo "退出"
  325. exit 0
  326. ;;
  327. *)
  328. echo "输入不正确,退出。"
  329. exit 1
  330. ;;
  331. esac
  332. # 5) 上传到发布仓库
  333. echo "准备将 publish 内容推送到发布仓库: ${PUBLISH_GIT_URL}"
  334. echo ""
  335. if $noninteractive; then
  336. case "$do_publish_arg" in
  337. y|Y|1)
  338. do_publish="y"
  339. ;;
  340. *)
  341. do_publish="n"
  342. ;;
  343. esac
  344. echo "非交互模式:发布选项: ${do_publish}"
  345. else
  346. read -p "是否将本次编译结果push到发布仓库?(y/n,回车跳过)" do_publish
  347. fi
  348. if [[ "$do_publish" =~ ^[Yy]$ ]]; then
  349. echo "开始推送发布内容..."
  350. pub_tmp=$(mktemp -d -t publish_repo_XXXX)
  351. _tmp_dirs+=("$pub_tmp")
  352. git clone "$PUBLISH_GIT_URL" "$pub_tmp"
  353. rm -rf "$pub_tmp"/*
  354. cp -r "$publish_dir/"* "$pub_tmp"/ 2>/dev/null || true
  355. pushd "$pub_tmp" >/dev/null
  356. git add --all
  357. git commit -m "auto build from repo:${repo_branch}@${repo_hash}, excel:${excel_branch}@${excel_hash}" || echo "Nothing to commit"
  358. git push origin master || echo "git push 失败,请检查网络或权限。"
  359. popd >/dev/null
  360. else
  361. echo "取消发布。"
  362. exit 0
  363. fi
  364. echo "exit"
  365. exit 0