版本管理脚本#

脚本说明#

版本管理脚本用于管理项目版本,包括版本号管理、Git标签管理、变更日志生成等。

脚本代码#

#!/bin/bash

# 版本管理脚本
# 功能:管理项目版本、Git标签、变更日志
# 作者:System Admin
# 日期:2024-01-01

set -euo pipefail

# 配置变量
PROJECT_DIR=""
VERSION_FILE="version.txt"
CHANGELOG_FILE="CHANGELOG.md"
VERSION_TYPE="patch"
COMMIT_MESSAGE=""
DRY_RUN=false

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

# 检查项目目录
check_project_dir() {
    if [ ! -d "$PROJECT_DIR" ]; then
        log_error "项目目录不存在: $PROJECT_DIR"
        return 1
    fi
    
    return 0
}

# 检查Git仓库
check_git_repo() {
    if [ ! -d ".git" ]; then
        log_error "不是Git仓库"
        return 1
    fi
    
    return 0
}

# 获取当前版本
get_current_version() {
    local dir=$1
    
    if [ -f "$dir/$VERSION_FILE" ]; then
        cat "$dir/$VERSION_FILE"
    else
        echo "0.0.0"
    fi
}

# 解析版本号
parse_version() {
    local version=$1
    
    local major=$(echo "$version" | cut -d. -f1)
    local minor=$(echo "$version" | cut -d. -f2)
    local patch=$(echo "$version" | cut -d. -f3)
    
    echo "$major $minor $patch"
}

# 计算新版本号
calculate_new_version() {
    local current_version=$1
    local version_type=$2
    
    local major minor patch
    read major minor patch <<< $(parse_version "$current_version")
    
    case $version_type in
        major)
            major=$((major + 1))
            minor=0
            patch=0
            ;;
        minor)
            minor=$((minor + 1))
            patch=0
            ;;
        patch)
            patch=$((patch + 1))
            ;;
        *)
            log_error "无效的版本类型: $version_type"
            return 1
            ;;
    esac
    
    echo "${major}.${minor}.${patch}"
}

# 更新版本号
update_version() {
    local dir=$1
    local new_version=$2
    
    log_info "更新版本号: $new_version"
    
    echo "$new_version" > "$dir/$VERSION_FILE"
    
    # 更新package.json
    if [ -f "$dir/package.json" ]; then
        sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$new_version\"/" "$dir/package.json"
    fi
    
    # 更新setup.py
    if [ -f "$dir/setup.py" ]; then
        sed -i "s/version='[^']*'/version='$new_version'/" "$dir/setup.py"
    fi
    
    # 更新pyproject.toml
    if [ -f "$dir/pyproject.toml" ]; then
        sed -i "s/version = \"[^\"]*\"/version = \"$new_version\"/" "$dir/pyproject.toml"
    fi
    
    log_info "版本号更新完成"
}

# 创建Git标签
create_git_tag() {
    local version=$1
    local message=$2
    
    log_info "创建Git标签: v$version"
    
    if [ "$DRY_RUN" = true ]; then
        log_info "[DRY RUN] 将创建标签: v$version"
        return 0
    fi
    
    # 创建标签
    git tag -a "v$version" -m "$message"
    
    # 推送标签
    git push origin "v$version"
    
    log_info "Git标签创建完成"
}

# 获取Git提交历史
get_git_commits() {
    local since_tag=$1
    
    if [ -z "$since_tag" ]; then
        git log --pretty=format:"%h - %s (%an, %ar)" --no-merges
    else
        git log --pretty=format:"%h - %s (%an, %ar)" --no-merges "$since_tag..HEAD"
    fi
}

# 生成变更日志
generate_changelog() {
    local dir=$1
    local version=$2
    local version_type=$3
    
    log_info "生成变更日志: $version"
    
    local changelog_file="$dir/$CHANGELOG_FILE"
    local date=$(date +%Y-%m-%d)
    local previous_version=$(get_current_version "$dir")
    
    # 获取Git提交历史
    local commits=$(get_git_commits "v$previous_version")
    
    # 生成变更日志
    local new_changelog="## [$version] - $date\n\n"
    
    case $version_type in
        major)
            new_changelog+="### Breaking Changes\n\n"
            ;;
        minor)
            new_changelog+="### Added\n\n"
            ;;
        patch)
            new_changelog+="### Fixed\n\n"
            ;;
    esac
    
    new_changelog+="$commits\n\n"
    
    # 更新变更日志文件
    if [ -f "$changelog_file" ]; then
        # 在文件开头插入新内容
        local existing_content=$(cat "$changelog_file")
        echo -e "$new_changelog$existing_content" > "$changelog_file"
    else
        echo -e "$new_changelog" > "$changelog_file"
    fi
    
    log_info "变更日志生成完成"
}

# 显示版本信息
show_version_info() {
    local dir=$1
    
    log_info "显示版本信息"
    
    local current_version=$(get_current_version "$dir")
    
    echo "版本信息"
    echo "========"
    echo "当前版本: $current_version"
    
    # 显示Git标签
    echo ""
    echo "Git标签:"
    git tag -l | sort -V | tail -5
    
    # 显示最新提交
    echo ""
    echo "最新提交:"
    git log -1 --pretty=format:"%h - %s (%an, %ar)"
}

# 预览版本变更
preview_version_change() {
    local dir=$1
    local version_type=$2
    
    log_info "预览版本变更"
    
    local current_version=$(get_current_version "$dir")
    local new_version=$(calculate_new_version "$current_version" "$version_type")
    
    echo "版本变更预览"
    echo "============"
    echo "当前版本: $current_version"
    echo "版本类型: $version_type"
    echo "新版本: $new_version"
}

# 发布版本
release_version() {
    local dir=$1
    local version_type=$2
    local message=$3
    
    log_info "发布版本: $version_type"
    
    # 检查Git仓库
    if ! check_git_repo; then
        return 1
    fi
    
    # 检查是否有未提交的更改
    if [ -n "$(git status --porcelain)" ]; then
        log_error "存在未提交的更改"
        return 1
    fi
    
    # 获取当前版本
    local current_version=$(get_current_version "$dir")
    
    # 计算新版本
    local new_version=$(calculate_new_version "$current_version" "$version_type")
    
    # 更新版本号
    update_version "$dir" "$new_version"
    
    # 提交版本更新
    if [ "$DRY_RUN" = false ]; then
        git add "$VERSION_FILE"
        if [ -f "package.json" ]; then
            git add package.json
        fi
        if [ -f "setup.py" ]; then
            git add setup.py
        fi
        if [ -f "pyproject.toml" ]; then
            git add pyproject.toml
        fi
        
        git commit -m "chore: bump version to $new_version"
        git push
    fi
    
    # 生成变更日志
    generate_changelog "$dir" "$new_version" "$version_type"
    
    # 提交变更日志
    if [ "$DRY_RUN" = false ]; then
        git add "$CHANGELOG_FILE"
        git commit -m "docs: update changelog for $new_version"
        git push
    fi
    
    # 创建Git标签
    create_git_tag "$new_version" "Release version $new_version"
    
    log_info "版本发布完成: $new_version"
}

# 回滚版本
rollback_version() {
    local dir=$1
    local version=$2
    
    log_info "回滚版本: $version"
    
    # 检查标签是否存在
    if ! git rev-parse "v$version" &>/dev/null; then
        log_error "标签不存在: v$version"
        return 1
    fi
    
    # 回退到指定版本
    if [ "$DRY_RUN" = false ]; then
        git checkout "v$version"
        git push -f origin HEAD
    fi
    
    # 更新版本文件
    echo "$version" > "$dir/$VERSION_FILE"
    
    log_info "版本回滚完成: $version"
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] <命令> [参数]"
    echo ""
    echo "选项:"
    echo "  -d <目录>        项目目录"
    echo "  -m <消息>        提交消息"
    echo "  -n               试运行模式"
    echo "  -h               显示帮助信息"
    echo ""
    echo "命令:"
    echo "  show                      显示版本信息"
    echo "  preview <类型>            预览版本变更(major/minor/patch)"
    echo "  release <类型>            发布版本(major/minor/patch)"
    echo "  rollback <版本>           回滚版本"
    echo "  tag <版本> <消息>         创建Git标签"
    echo "  changelog                 生成变更日志"
    echo ""
    echo "示例:"
    echo "  $0 -d /path/to/project show"
    echo "  $0 -d /path/to/project preview patch"
    echo "  $0 -d /path/to/project release patch"
    echo "  $0 -d /path/to/project rollback 1.0.0"
    echo "  $0 -d /path/to/project tag 1.0.0 \"Release 1.0.0\""
}

# 主函数
main() {
    # 解析选项
    while getopts "d:m:nh" opt; do
        case $opt in
            d)
                PROJECT_DIR="$OPTARG"
                log_info "项目目录: $PROJECT_DIR"
                ;;
            m)
                COMMIT_MESSAGE="$OPTARG"
                log_info "提交消息: $COMMIT_MESSAGE"
                ;;
            n)
                DRY_RUN=true
                log_info "试运行模式"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查项目目录
    if [ -z "$PROJECT_DIR" ]; then
        PROJECT_DIR=$(pwd)
        log_info "使用当前目录: $PROJECT_DIR"
    fi
    
    if ! check_project_dir; then
        exit 1
    fi
    
    # 检查命令
    if [ $# -eq 0 ]; then
        log_error "缺少命令"
        show_help
        exit 1
    fi
    
    COMMAND=$1
    shift
    
    # 执行命令
    case $COMMAND in
        show)
            show_version_info "$PROJECT_DIR"
            ;;
        preview)
            if [ $# -eq 0 ]; then
                log_error "缺少版本类型"
                show_help
                exit 1
            fi
            preview_version_change "$PROJECT_DIR" "$1"
            ;;
        release)
            if [ $# -eq 0 ]; then
                log_error "缺少版本类型"
                show_help
                exit 1
            fi
            local message=${COMMIT_MESSAGE:-"Release version"}
            release_version "$PROJECT_DIR" "$1" "$message"
            ;;
        rollback)
            if [ $# -eq 0 ]; then
                log_error "缺少版本号"
                show_help
                exit 1
            fi
            rollback_version "$PROJECT_DIR" "$1"
            ;;
        tag)
            if [ $# -lt 2 ]; then
                log_error "缺少参数"
                show_help
                exit 1
            fi
            create_git_tag "$1" "$2"
            ;;
        changelog)
            local current_version=$(get_current_version "$PROJECT_DIR")
            local new_version=$(calculate_new_version "$current_version" "patch")
            generate_changelog "$PROJECT_DIR" "$new_version" "patch"
            ;;
        *)
            log_error "无效的命令: $COMMAND"
            show_help
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x version_manager.sh
  2. 基本用法:

    # 显示版本信息
    ./version_manager.sh -d /path/to/project show
    
    # 预览版本变更
    ./version_manager.sh -d /path/to/project preview patch
    
    # 发布补丁版本
    ./version_manager.sh -d /path/to/project release patch
    
    # 发布次版本
    ./version_manager.sh -d /path/to/project release minor
    
    # 发布主版本
    ./version_manager.sh -d /path/to/project release major
  3. 高级用法:

    # 试运行模式
    ./version_manager.sh -n -d /path/to/project release patch
    
    # 指定提交消息
    ./version_manager.sh -m "Release 1.0.0" -d /path/to/project release major
    
    # 回滚版本
    ./version_manager.sh -d /path/to/project rollback 1.0.0
    
    # 创建Git标签
    ./version_manager.sh -d /path/to/project tag 1.0.0 "Release 1.0.0"
    
    # 生成变更日志
    ./version_manager.sh -d /path/to/project changelog

功能特点#

  • 版本号管理(遵循语义化版本规范)
  • Git标签管理
  • 变更日志生成
  • 版本发布
  • 版本回滚
  • 试运行模式
  • 多项目支持

依赖项#

  • git: 用于版本控制

注意事项#

  1. 需要Git仓库环境
  2. 发布前确保代码已提交
  3. 版本号遵循语义化版本规范
  4. 试运行模式不会实际执行操作
  5. 回滚操作会强制推送,请谨慎使用