Files
agv-control-slam/scripts/create_release.sh
2025-11-15 14:31:47 +08:00

374 lines
8.6 KiB
Bash
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
# 版本发布脚本
# 用途: 创建版本发布归档生成release notes创建git tag
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 打印带颜色的信息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查是否在项目根目录
check_project_root() {
if [ ! -f "FILE_ORGANIZATION.md" ]; then
print_error "请在项目根目录运行此脚本"
exit 1
fi
}
# 检查是否在git仓库中
check_git_repo() {
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_error "不在git仓库中"
exit 1
fi
}
# 显示使用说明
show_usage() {
echo "使用方法: $0 <版本号> [发布类型]"
echo ""
echo "参数:"
echo " 版本号 格式: X.Y.Z (如: 1.2.0)"
echo " 发布类型 Major | Minor | Patch (可选,默认根据版本号判断)"
echo ""
echo "示例:"
echo " $0 1.2.0"
echo " $0 1.2.0 Minor"
echo " $0 2.0.0 Major"
echo ""
echo "说明:"
echo " - Major: 重大版本更新可能包含不兼容的API变更"
echo " - Minor: 次要版本更新,新增功能但向后兼容"
echo " - Patch: 补丁版本仅包含bug修复"
exit 1
}
# 验证版本号格式
validate_version() {
local version=$1
if ! [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
print_error "版本号格式错误,应为 X.Y.Z"
exit 1
fi
}
# 判断发布类型
determine_release_type() {
local version=$1
local provided_type=$2
if [ -n "$provided_type" ]; then
echo "$provided_type"
return
fi
# 自动判断
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
local last_version=${last_tag#v}
IFS='.' read -r -a curr_parts <<< "$version"
IFS='.' read -r -a last_parts <<< "$last_version"
if [ "${curr_parts[0]}" -gt "${last_parts[0]}" ]; then
echo "Major"
elif [ "${curr_parts[1]}" -gt "${last_parts[1]}" ]; then
echo "Minor"
else
echo "Patch"
fi
}
# 获取当前日期
get_date() {
date +%Y-%m-%d
}
# 创建版本归档目录
create_version_dirs() {
local version=$1
local version_path="archives/versions/v${version}"
print_info "创建版本归档目录: ${version_path}"
mkdir -p "${version_path}/backup"
print_success "目录创建完成"
echo "${version_path}"
}
# 获取commit统计
get_commit_stats() {
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$last_tag" ]; then
# 如果没有tag统计所有commit
git rev-list --count HEAD
else
# 统计从上个tag到现在的commit
git rev-list --count ${last_tag}..HEAD
fi
}
# 获取变更的文件数
get_changed_files() {
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$last_tag" ]; then
git diff --name-only --diff-filter=ACMR | wc -l
else
git diff --name-only --diff-filter=ACMR ${last_tag}..HEAD | wc -l
fi
}
# 生成release notes
create_release_notes() {
local version=$1
local release_type=$2
local release_date=$3
local version_path=$4
local notes_path="${version_path}/release_notes.md"
local template_path=".claude/templates/release_notes_template.md"
print_info "生成Release Notes: ${notes_path}"
local commit_count=$(get_commit_stats)
local file_count=$(get_changed_files)
local last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
local last_version=${last_tag#v}
# 如果模板存在,使用模板
if [ -f "${template_path}" ]; then
cp "${template_path}" "${notes_path}"
# 替换模板变量
sed -i "s/{{VERSION}}/${version}/g" "${notes_path}"
sed -i "s/{{RELEASE_DATE}}/${release_date}/g" "${notes_path}"
sed -i "s/{{RELEASE_TYPE}}/${release_type}/g" "${notes_path}"
sed -i "s/{{COMMIT_COUNT}}/${commit_count}/g" "${notes_path}"
sed -i "s/{{FILE_COUNT}}/${file_count}/g" "${notes_path}"
sed -i "s/{{OLD_VERSION}}/${last_version}/g" "${notes_path}"
sed -i "s/{{PREVIOUS_VERSION}}/${last_version}/g" "${notes_path}"
else
# 创建基本release notes
cat > "${notes_path}" << EOF
# Release Notes - v${version}
**发布日期**: ${release_date}
**版本号**: ${version}
**发布类型**: ${release_type}
---
## 版本概述
[简要描述本版本的主要更新内容]
## 重要变更 ⚠️
[列出所有重大变更]
## 新增功能 ✨
- [功能1]
- [功能2]
## Bug修复 🐛
- [Bug修复1]
- [Bug修复2]
## 性能优化 🚀
- [优化项1]
- [优化项2]
## 统计数据
- **总提交数**: ${commit_count}
- **修改文件数**: ${file_count}
- **上一版本**: ${last_version}
## 升级指南
### 从 v${last_version} 升级
1. 备份当前版本
2. 更新代码
3. 重新编译
4. 测试验证
## 获取此版本
\`\`\`bash
git clone <repo_url>
git checkout v${version}
\`\`\`
---
**归档位置**: \`archives/versions/v${version}/\`
EOF
fi
print_success "Release Notes生成完成"
echo "${notes_path}"
}
# 创建git tag
create_git_tag() {
local version=$1
local tag_name="v${version}"
print_info "检查是否已存在tag: ${tag_name}"
if git rev-parse "${tag_name}" >/dev/null 2>&1; then
print_warning "Tag ${tag_name} 已存在"
read -p "是否删除并重新创建? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
git tag -d "${tag_name}"
print_info "已删除旧tag"
else
print_info "跳过创建tag"
return
fi
fi
print_info "创建git tag: ${tag_name}"
git tag -a "${tag_name}" -m "Release version ${version}"
print_success "Git tag创建完成"
echo ""
print_info "推送tag到远程仓库:"
echo " git push origin ${tag_name}"
}
# 可选:备份代码
backup_code() {
local version_path=$1
echo ""
read -p "是否备份完整代码到归档目录? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_info "创建代码备份..."
local backup_file="${version_path}/backup/source_code.tar.gz"
tar -czf "${backup_file}" \
--exclude='.git' \
--exclude='build' \
--exclude='archives' \
--exclude='*.o' \
--exclude='*.so' \
--exclude='*.dll' \
src/ include/ examples/ CMakeLists.txt
print_success "代码备份完成: ${backup_file}"
else
print_info "跳过代码备份"
fi
}
# 显示下一步操作
show_next_steps() {
local version=$1
local notes_path=$2
local version_path=$3
echo ""
print_success "版本发布归档创建完成!"
echo ""
echo "📁 版本目录: ${version_path}"
echo "📄 Release Notes: ${notes_path}"
echo "🏷️ Git Tag: v${version}"
echo ""
print_info "下一步操作:"
echo " 1. 编辑Release Notes: vim ${notes_path}"
echo " 2. 检查并补充版本信息"
echo " 3. 提交归档: git add archives/versions/ && git commit -m \"release: v${version}\""
echo " 4. 推送tag: git push origin v${version}"
echo " 5. 在GitHub/GitLab创建Release"
echo ""
}
# 主函数
main() {
# 检查参数
if [ $# -lt 1 ]; then
show_usage
fi
local version=$1
local release_type=$2
# 验证版本号
validate_version "${version}"
# 检查环境
check_project_root
check_git_repo
# 确定发布类型
release_type=$(determine_release_type "${version}" "${release_type}")
# 获取日期
local release_date=$(get_date)
print_info "开始创建版本发布"
print_info "版本号: ${version}"
print_info "发布类型: ${release_type}"
print_info "发布日期: ${release_date}"
echo ""
# 确认
read -p "确认创建版本 v${version}? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "取消操作"
exit 0
fi
# 创建版本目录
local version_path=$(create_version_dirs "${version}")
# 生成Release Notes
local notes_path=$(create_release_notes "${version}" "${release_type}" "${release_date}" "${version_path}")
# 创建Git Tag
create_git_tag "${version}"
# 可选备份
backup_code "${version_path}"
# 显示下一步操作
show_next_steps "${version}" "${notes_path}" "${version_path}"
}
# 运行主函数
main "$@"