Files
map-client-vue/release.sh
2025-10-15 15:49:56 +08:00

275 lines
9.1 KiB
Bash
Executable File
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.

#!/bin/bash
set -e
# ==========================================
# Git 自动发布脚本 v2.0
# ==========================================
# 功能:
# 1. 检查分支和工作区状态
# 2. 从 release.md 提取版本信息
# 3. 创建并推送 Git 标签
# 4. 通过 API 在 Gitea 创建 Release
# 5. 自动处理字符集问题
#
# 使用方法:
# export GITEA_TOKEN="your_token_here"
# ./release.sh
#
# 要求:
# - release.md 文件存在且包含版本号
# - GITEA_TOKEN 环境变量已设置
# - 安装了 jq 命令
#
# 更新日志:
# v2.0 - 添加字符集自动降级处理
# - 改进错误提示和日志输出
# - 添加 Release 创建验证
# ==========================================
# 0. 检查必要工具
if ! command -v jq &> /dev/null; then
echo "❌ 错误:未安装 jq 命令"
echo "💡 安装方法:"
echo " macOS: brew install jq"
echo " Ubuntu: sudo apt-get install jq"
echo " CentOS: sudo yum install jq"
exit 1
fi
# 1. 检查分支
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" != "main" ]; then
echo "❌ 错误:请在 main 分支运行,当前是 $branch"
exit 1
fi
echo "✅ 分支: $branch"
# 2. 检查工作区是否干净
if [ -n "$(git status --porcelain)" ]; then
echo "❌ 错误:工作区有未提交的更改,请先提交或 stash"
git status
exit 1
fi
echo "✅ 工作区干净"
# 3. 更新代码
echo "⬇️ 拉取远程代码..."
git fetch origin
git pull origin main
echo "✅ 已同步最新代码"
# 4. 从 release.md 提取版本和说明
if [ ! -f release.md ]; then
echo "❌ 未找到 release.md"
exit 1
fi
# 提取最后一个版本号(去掉 ## 和空格)
VERSION=$(grep "^## v" release.md | tail -n 1 | sed 's/^## *//')
if [ -z "$VERSION" ]; then
echo "❌ release.md 中未找到版本号"
exit 1
fi
# 提取该版本块的内容(从版本标题下一行到下一个版本或文件结尾)
TAG_MESSAGE=$(awk "
/^## $VERSION\$/ { flag=1; next }
/^## v[0-9]/ && flag { exit }
flag { print }
" release.md)
# 提取标题(第一个非空的实质性内容行,通常是 "发布时间:" 后的第一行)
# 跳过空行和"发布时间:"行,取第一个 ### 标题
RELEASE_TITLE=$(echo "$TAG_MESSAGE" | grep -m 1 "^###" | sed 's/^### *//' | sed 's/^[🎯✨🔧🐛📦]* *//')
# 如果没有找到 ### 标题,尝试找第一个非空行
if [ -z "$RELEASE_TITLE" ]; then
RELEASE_TITLE=$(echo "$TAG_MESSAGE" | grep -v "^$" | grep -v "^发布时间:" | head -n 1)
fi
# 如果还是没有,使用版本号作为标题
if [ -z "$RELEASE_TITLE" ]; then
RELEASE_TITLE="Release $VERSION"
fi
echo "📝 版本号: $VERSION"
echo "📌 标题: $RELEASE_TITLE"
echo "📄 内容预览:"
echo "$TAG_MESSAGE" | head -n 10
echo "..."
# 5. 创建 tag如已存在则删除后重建
if git rev-parse "$VERSION" >/dev/null 2>&1; then
echo "⚠️ 标签 $VERSION 已存在,删除旧标签..."
git tag -d "$VERSION"
git push origin ":refs/tags/$VERSION"
fi
git tag -a "$VERSION" -m "$TAG_MESSAGE"
echo "✅ 已创建 tag $VERSION"
# 6. 推送代码和 tag
echo "🚀 推送到远程..."
git push origin main
git push origin "$VERSION"
# 7. 创建 Gitea Release
echo ""
echo "🌐 创建 Gitea Release..."
# 自动解析 GITEA_URL 和 REPO
remote_url=$(git config --get remote.origin.url)
if [[ "$remote_url" == ssh://git@biboer.cn:21174/* ]]; then
# 特殊处理 biboer.cn:21174 的情况Web 界面在 /gitea 路径下
GITEA_URL="https://biboer.cn/gitea"
GITEA_REPO=$(echo "$remote_url" | sed 's|ssh://git@biboer\.cn:21174/||' | sed 's|\.git$||')
elif [[ "$remote_url" =~ ^ssh://([^/]+)/([^/]+)/(.+)\.git$ ]]; then
GITEA_URL="https://${BASH_REMATCH[1]}"
GITEA_REPO="${BASH_REMATCH[2]}/${BASH_REMATCH[3]}"
elif [[ "$remote_url" =~ ^([^@]+@[^:]+):([^/]+)/(.+)\.git$ ]]; then
# git@biboer.cn:21174/gavin/note-to-mp.git
hostport=$(echo "${BASH_REMATCH[1]}" | cut -d@ -f2)
GITEA_URL="https://${hostport}"
GITEA_REPO="${BASH_REMATCH[2]}/${BASH_REMATCH[3]}"
else
echo "❌ 无法解析远程地址: $remote_url"
exit 1
fi
if [ -z "$GITEA_TOKEN" ]; then
echo "⚠️ 未设置 GITEA_TOKEN只推送了 tag没有创建 Release"
exit 0
fi
# 7.1 检查远程是否已存在该版本的 Release如果存在则删除
echo "🔍 检查远程 Release 是否已存在..."
check_response=$(curl -s -w "\n%{http_code}" \
-X GET "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases/tags/$VERSION" \
-H "Authorization: token $GITEA_TOKEN")
check_http_code=$(echo "$check_response" | tail -n 1)
check_body=$(echo "$check_response" | sed '$d')
if [ "$check_http_code" -eq 200 ]; then
# Release 已存在,获取 Release ID 并删除
release_id=$(echo "$check_body" | jq -r '.id')
echo "⚠️ 远程已存在 Release $VERSION (ID: $release_id),正在删除..."
delete_response=$(curl -s -w "\n%{http_code}" \
-X DELETE "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases/$release_id" \
-H "Authorization: token $GITEA_TOKEN")
delete_http_code=$(echo "$delete_response" | tail -n 1)
if [ "$delete_http_code" -eq 204 ] || [ "$delete_http_code" -eq 200 ]; then
echo "✅ 已删除旧的 Release"
else
echo "⚠️ 删除 Release 失败 (HTTP $delete_http_code),但将继续创建新的..."
fi
elif [ "$check_http_code" -eq 404 ]; then
echo "✅ 远程不存在该 Release可以创建"
else
echo "⚠️ 检查 Release 状态失败 (HTTP $check_http_code),但将继续创建..."
fi
# 7.2 直接用 shell 拼接 JSON不用 jq不用临时文件
JSON_PAYLOAD="{\n \"tag_name\": \"$VERSION\",\n \"name\": \"$VERSION - $RELEASE_TITLE\",\n \"body\": \"$(echo "$TAG_MESSAGE" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/"/\\"/g')\",\n \"draft\": false,\n \"prerelease\": false\n}"
echo "🔄 尝试创建 Release (直接拼接 JSON)..."
response=$(curl -s -w "\n%{http_code}" \
-X POST "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: token $GITEA_TOKEN" \
-d "$JSON_PAYLOAD")
http_code=$(echo "$response" | tail -n 1)
response_body=$(echo "$response" | sed '$d')
if [ "$http_code" -eq 201 ]; then
echo "✅ Release 创建成功: $VERSION"
release_url=$(echo "$response_body" | jq -r '.html_url')
echo "🔗 Release 地址: $release_url"
elif [[ "$response_body" == *"Conversion from collation"* ]] || [[ "$response_body" == *"utf8"* ]]; then
echo "⚠️ 检测到字符集问题,尝试使用英文版本..."
echo "🐛 调试信息 - HTTP Code: $http_code"
echo "🐛 调试信息 - Response Body: $response_body"
# 创建简化的英文版本
ENGLISH_BODY="## Release Notes\n\nThis is release $VERSION: $RELEASE_TITLE\n\nFor detailed Chinese release notes, please see:\n- release.md in the repository\n- Or visit: $GITEA_URL/$GITEA_REPO/src/branch/main/release.md\n\n### Quick Start\n\n\`\`\`bash\ngit pull origin main\ncd web && npm install\nnpm run dev\n\`\`\`"
JSON_PAYLOAD_EN=$(jq -n -c \
--arg version "$VERSION" \
--arg name "$VERSION - $RELEASE_TITLE" \
--arg body "$ENGLISH_BODY" \
'{
tag_name: $version,
name: $name,
body: $body,
draft: false,
prerelease: false
}')
response=$(curl -s -w "\n%{http_code}" \
-X POST "$GITEA_URL/api/v1/repos/$GITEA_REPO/releases" \
-H "Content-Type: application/json; charset=utf-8" \
-H "Authorization: token $GITEA_TOKEN" \
-d "$JSON_PAYLOAD_EN")
http_code=$(echo "$response" | tail -n 1)
response_body=$(echo "$response" | sed '$d')
if [ "$http_code" -eq 201 ]; then
echo "✅ Release 创建成功 (英文版): $VERSION"
release_url=$(echo "$response_body" | jq -r '.html_url')
echo "🔗 Release 地址: $release_url"
echo "💡 提示: 可以在 Gitea Web 界面手动编辑添加中文说明"
else
echo "❌ Release 创建失败HTTP $http_code"
echo "📄 错误信息: $response_body"
echo ""
echo "💡 手动创建步骤:"
echo " 1. 访问: $GITEA_URL/$GITEA_REPO/releases"
echo " 2. 点击 '新建发布'"
echo " 3. 选择标签: $VERSION"
echo " 4. 从 release.md 复制说明"
fi
else
echo "❌ Release 创建失败HTTP $http_code"
echo "📄 错误信息: $response_body"
echo ""
echo "💡 手动创建步骤:"
echo " 1. 访问: $GITEA_URL/$GITEA_REPO/releases"
echo " 2. 点击 '新建发布'"
echo " 3. 选择标签: $VERSION"
echo " 4. 从 release.md 复制说明"
fi
echo ""
echo "🎉 发布完成!"
echo "📦 版本:$VERSION"
echo ""
echo "📊 发布总结:"
echo " ✅ Git 标签已推送"
echo " ✅ 代码已推送到远程"
if [ "$http_code" -eq 201 ]; then
echo " ✅ Gitea Release 已创建"
echo ""
echo "🔗 访问地址:"
echo " - Release: $release_url"
echo " - 标签列表: $GITEA_URL/$GITEA_REPO/tags"
echo " - 提交历史: $GITEA_URL/$GITEA_REPO/commits/branch/main"
else
echo " ⚠️ Gitea Release 创建失败(需手动创建)"
echo ""
echo "🔗 相关链接:"
echo " - 仓库: $GITEA_URL/$GITEA_REPO"
echo " - 发布页: $GITEA_URL/$GITEA_REPO/releases"
fi
echo ""
echo "🚀 用户升级指南:"
echo " git pull origin main"
echo " cd web && npm install"
echo " npm run dev"