辣评版本管理与构建系统(十七)

 

历史说明

本文包含两类内容:

  1. 当时已落地的构建与发布实践;
  2. 同阶段的方案草稿与历史脚本示例(用于记录演进思路)。

为避免歧义,当前仓库可直接使用的工程化入口主要是:build.shbuild.ps1local-build.shdocker/Dockerfiledocker/docker-compose.ymlconfig.example.json
文中提及的 VERSIONversion.jsonscripts/version.sh 等内容可视为历史方案示例。


版本管理系统概述

随着辣评项目的不断发展,我们需要一个规范的版本管理系统来追踪项目的演进历程。本文记录了版本号管理系统和构建系统的实现过程。

系统目标

  • 实现自动化版本号管理
  • 统一构建脚本
  • 支持多平台构建
  • 优化构建产物结构
  • 提升部署效率

版本号管理系统

版本号规范

采用语义化版本号(Semantic Versioning):MAJOR.MINOR.PATCH

  • MAJOR:重大更新,不兼容的 API 修改
  • MINOR:新增功能,向下兼容
  • PATCH:Bug 修复,向下兼容

版本文件结构

project/
├── VERSION                 # 版本号文件
├── CHANGELOG.md           # 变更日志
└── version.json           # 版本信息(JSON格式)

VERSION 文件

1.5.0

version.json 文件

说明:以下 version.json 为版本元数据结构示例,用于说明字段设计。

{
  "version": "1.5.0",
  "buildDate": "2026-02-27",
  "buildNumber": "20260227001",
  "gitCommit": "d12e866",
  "gitBranch": "dev",
  "changelog": [
    {
      "version": "1.5.0",
      "date": "2026-02-27",
      "changes": [
        "feat: 添加版本号管理系统",
        "feat: 优化构建脚本输出目录结构",
        "feat: 添加 Windows PowerShell 构建脚本"
      ]
    }
  ]
}

版本管理脚本

说明:以下 scripts/version.sh 为历史方案示例,当前仓库未默认提供该脚本文件。

#!/bin/bash
# scripts/version.sh

VERSION_FILE="VERSION"
VERSION_JSON="version.json"

# 读取当前版本
get_current_version() {
    if [ -f "$VERSION_FILE" ]; then
        cat "$VERSION_FILE"
    else
        echo "0.0.0"
    fi
}

# 更新版本号
update_version() {
    local version_type=$1
    local current_version=$(get_current_version)

    IFS='.' read -r major minor patch <<< "$current_version"

    case $version_type in
        major)
            major=$((major + 1))
            minor=0
            patch=0
            ;;
        minor)
            minor=$((minor + 1))
            patch=0
            ;;
        patch)
            patch=$((patch + 1))
            ;;
        *)
            echo "错误:版本类型必须是 major、minor 或 patch"
            exit 1
            ;;
    esac

    new_version="$major.$minor.$patch"
    echo "$new_version" > "$VERSION_FILE"

    # 更新 version.json
    update_version_json "$new_version"

    echo "版本已更新:$current_version -> $new_version"
}

# 更新 version.json
update_version_json() {
    local version=$1
    local build_date=$(date +%Y-%m-%d)
    local build_number=$(date +%Y%m%d%H%M)
    local git_commit=$(git rev-parse --short HEAD)
    local git_branch=$(git rev-parse --abbrev-ref HEAD)

    cat > "$VERSION_JSON" <<EOF
{
  "version": "$version",
  "buildDate": "$build_date",
  "buildNumber": "$build_number",
  "gitCommit": "$git_commit",
  "gitBranch": "$git_branch"
}
EOF
}

# 显示当前版本
show_version() {
    local version=$(get_current_version)
    echo "当前版本:$version"

    if [ -f "$VERSION_JSON" ]; then
        echo ""
        echo "详细信息:"
        cat "$VERSION_JSON"
    fi
}

# 主函数
main() {
    case $1 in
        major|minor|patch)
            update_version $1
            ;;
        show)
            show_version
            ;;
        *)
            echo "用法:$0 {major|minor|patch|show}"
            echo ""
            echo "  major  - 主版本号 +1 (不兼容的更新)"
            echo "  minor  - 次版本号 +1 (新功能)"
            echo "  patch  - 修订号 +1 (Bug修复)"
            echo "  show   - 显示当前版本"
            exit 1
            ;;
    esac
}

main "$@"

构建脚本优化

Bash 构建脚本

#!/bin/bash
# build.sh

set -e

echo "========================================="
echo "辣评项目构建脚本"
echo "========================================="

# 读取版本号
VERSION=$(cat VERSION 2>/dev/null || echo "unknown")
echo "版本号:$VERSION"

# 清理旧的构建产物
echo ""
echo "清理旧的构建产物..."
rm -rf dist/
rm -rf admin-vue/dist/

# 构建前端
echo ""
echo "构建前端..."
cd admin-vue
npm install
npm run build
cd ..

# 创建输出目录
echo ""
echo "创建输出目录..."
mkdir -p dist/laping-$VERSION

# 复制前端构建产物
echo "复制前端构建产物..."
cp -r admin-vue/dist dist/laping-$VERSION/frontend

# 构建后端
echo ""
echo "构建后端..."
cd cmd/server
go build -o ../../dist/laping-$VERSION/laping-server main.go
cd ../..

# 复制配置文件
echo ""
echo "复制配置文件..."
cp config.json.example dist/laping-$VERSION/config.json
cp README.md dist/laping-$VERSION/
cp VERSION dist/laping-$VERSION/

# 创建启动脚本
echo ""
echo "创建启动脚本..."
cat > dist/laping-$VERSION/start.sh <<'EOF'
#!/bin/bash
echo "启动辣评服务..."
./laping-server
EOF
chmod +x dist/laping-$VERSION/start.sh

# 打包
echo ""
echo "打包..."
cd dist
tar -czf laping-$VERSION.tar.gz laping-$VERSION/
cd ..

echo ""
echo "========================================="
echo "构建完成!"
echo "输出目录:dist/laping-$VERSION/"
echo "压缩包:dist/laping-$VERSION.tar.gz"
echo "========================================="

Windows PowerShell 构建脚本

# build.ps1

Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "辣评项目构建脚本 (Windows)" -ForegroundColor Cyan
Write-Host "=========================================" -ForegroundColor Cyan

# 读取版本号
$VERSION = Get-Content -Path "VERSION" -ErrorAction SilentlyContinue
if (-not $VERSION) {
    $VERSION = "unknown"
}
Write-Host "版本号:$VERSION" -ForegroundColor Green

# 清理旧的构建产物
Write-Host ""
Write-Host "清理旧的构建产物..." -ForegroundColor Yellow
Remove-Item -Path "dist" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "admin-vue\dist" -Recurse -Force -ErrorAction SilentlyContinue

# 构建前端
Write-Host ""
Write-Host "构建前端..." -ForegroundColor Yellow
Set-Location -Path "admin-vue"
npm install
npm run build
Set-Location -Path ".."

# 创建输出目录
Write-Host ""
Write-Host "创建输出目录..." -ForegroundColor Yellow
$outputDir = "dist\laping-$VERSION"
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null

# 复制前端构建产物
Write-Host "复制前端构建产物..." -ForegroundColor Yellow
Copy-Item -Path "admin-vue\dist" -Destination "$outputDir\frontend" -Recurse

# 构建后端
Write-Host ""
Write-Host "构建后端..." -ForegroundColor Yellow
Set-Location -Path "cmd\server"
go build -o "..\..\$outputDir\laping-server.exe" main.go
Set-Location -Path "..\..\"

# 复制配置文件
Write-Host ""
Write-Host "复制配置文件..." -ForegroundColor Yellow
Copy-Item -Path "config.json.example" -Destination "$outputDir\config.json"
Copy-Item -Path "README.md" -Destination "$outputDir\"
Copy-Item -Path "VERSION" -Destination "$outputDir\"

# 创建启动脚本
Write-Host ""
Write-Host "创建启动脚本..." -ForegroundColor Yellow
$startScript = @"
@echo off
echo 启动辣评服务...
laping-server.exe
pause
"@
Set-Content -Path "$outputDir\start.bat" -Value $startScript

# 打包
Write-Host ""
Write-Host "打包..." -ForegroundColor Yellow
Compress-Archive -Path $outputDir -DestinationPath "dist\laping-$VERSION.zip" -Force

Write-Host ""
Write-Host "=========================================" -ForegroundColor Cyan
Write-Host "构建完成!" -ForegroundColor Green
Write-Host "输出目录:$outputDir" -ForegroundColor Green
Write-Host "压缩包:dist\laping-$VERSION.zip" -ForegroundColor Green
Write-Host "=========================================" -ForegroundColor Cyan

构建产物优化

优化前的目录结构

dist/
├── laping-server           # 后端可执行文件
├── index.html              # 前端入口
├── assets/                 # 前端资源
│   ├── index-xxx.js
│   └── index-xxx.css
└── config.json             # 配置文件

问题:

  • 前后端文件混在一起
  • 不便于管理和部署
  • 升级时容易出错

优化后的目录结构

dist/laping-1.5.0/
├── laping-server           # 后端可执行文件
├── frontend/               # 前端目录
│   ├── index.html
│   └── assets/
│       ├── index-xxx.js
│       └── index-xxx.css
├── config.json             # 配置文件
├── VERSION                 # 版本文件
├── README.md               # 说明文档
└── start.sh                # 启动脚本

优势:

  • 前后端分离,结构清晰
  • 便于独立更新前端或后端
  • 版本信息明确
  • 包含启动脚本,开箱即用

Docker 部署方案

Dockerfile

# 多阶段构建
FROM node:18-alpine AS frontend-builder

WORKDIR /app/admin-vue
COPY admin-vue/package*.json ./
RUN npm install
COPY admin-vue/ ./
RUN npm run build

FROM golang:1.21-alpine AS backend-builder

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN cd cmd/server && go build -o /app/laping-server main.go

FROM alpine:latest

WORKDIR /app

# 安装运行时依赖
RUN apk --no-cache add ca-certificates tzdata

# 复制构建产物
COPY --from=backend-builder /app/laping-server .
COPY --from=frontend-builder /app/admin-vue/dist ./frontend
COPY config.json.example ./config.json
COPY VERSION .

# 设置时区
ENV TZ=Asia/Shanghai

# 暴露端口
EXPOSE 8888

# 启动服务
CMD ["./laping-server"]

docker-compose.yml

version: '3.8'

services:
  laping:
    build: .
    container_name: laping-server
    ports:
      - "8888:8888"
    volumes:
      - ./data:/app/data
      - ./config.json:/app/config.json
      - ./uploads:/app/uploads
    environment:
      - TZ=Asia/Shanghai
    restart: unless-stopped
    networks:
      - laping-network

networks:
  laping-network:
    driver: bridge

构建和运行

# 构建镜像
docker-compose build

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f

# 停止服务
docker-compose down

自动化构建流程

GitHub Actions 配置

# .github/workflows/build.yml
name: Build and Release

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: Get version
      id: version
      run: echo "VERSION=$(cat VERSION)" >> $GITHUB_OUTPUT

    - name: Build
      run: |
        chmod +x build.sh
        ./build.sh

    - name: Create Release
      uses: softprops/action-gh-release@v1
      with:
        files: dist/laping-$.tar.gz
        body: |
          Release $

          See CHANGELOG.md for details.
      env:
        GITHUB_TOKEN: $

部署脚本

deploy.sh

#!/bin/bash
# deploy.sh - 部署脚本

set -e

SERVER="user@your-server.com"
DEPLOY_PATH="/opt/laping"
VERSION=$(cat VERSION)

echo "部署辣评 v$VERSION 到服务器..."

# 上传构建产物
echo "上传文件..."
scp dist/laping-$VERSION.tar.gz $SERVER:/tmp/

# 在服务器上执行部署
ssh $SERVER << EOF
    set -e

    # 停止服务
    echo "停止服务..."
    systemctl stop laping || true

    # 备份旧版本
    if [ -d "$DEPLOY_PATH" ]; then
        echo "备份旧版本..."
        mv $DEPLOY_PATH $DEPLOY_PATH.backup.\$(date +%Y%m%d%H%M%S)
    fi

    # 解压新版本
    echo "解压新版本..."
    mkdir -p $DEPLOY_PATH
    tar -xzf /tmp/laping-$VERSION.tar.gz -C $DEPLOY_PATH --strip-components=1

    # 恢复配置文件
    if [ -f "$DEPLOY_PATH.backup.*/config.json" ]; then
        echo "恢复配置文件..."
        cp $DEPLOY_PATH.backup.*/config.json $DEPLOY_PATH/
    fi

    # 设置权限
    chmod +x $DEPLOY_PATH/laping-server

    # 启动服务
    echo "启动服务..."
    systemctl start laping

    # 清理
    rm /tmp/laping-$VERSION.tar.gz

    echo "部署完成!"
EOF

echo "部署成功!"

版本发布流程

发布检查清单

  1. 代码检查
    • 所有测试通过
    • 代码已合并到主分支
    • 无未解决的 Bug
  2. 文档更新
    • 更新 CHANGELOG.md
    • 更新 README.md
    • 更新 API 文档
  3. 版本更新
    • 运行 ./scripts/version.sh {major|minor|patch}
    • 提交版本更新
  4. 构建测试
    • 运行 ./build.sh
    • 测试构建产物
  5. 发布
    • 创建 Git Tag
    • 推送到远程仓库
    • 创建 GitHub Release

发布命令

# 1. 更新版本号(根据更新类型选择)
./scripts/version.sh minor

# 2. 提交版本更新
git add VERSION version.json CHANGELOG.md
git commit -m "chore: bump version to $(cat VERSION)"

# 3. 创建标签
git tag -a v$(cat VERSION) -m "Release v$(cat VERSION)"

# 4. 推送
git push origin dev
git push origin v$(cat VERSION)

# 5. 构建
./build.sh

# 6. 部署(可选)
./deploy.sh

总结

版本管理与构建系统的建立为辣评项目的持续发展提供了坚实的基础。通过规范的版本号管理、统一的构建脚本、优化的产物结构和自动化的部署流程,我们显著提升了开发和运维效率。

关键成果

  • 实现了语义化版本号管理
  • 统一了多平台构建脚本
  • 优化了构建产物结构
  • 建立了 Docker 部署方案
  • 实现了自动化发布流程

最佳实践

  • 使用语义化版本号
  • 保持构建脚本简洁
  • 前后端分离部署
  • 自动化构建和发布
  • 完善的文档和检查清单

本文遵守 Attribution-NonCommercial 4.0 International 许可协议。 Attribution-NonCommercial 4.0 International