version_management_guide.md 11 KB

📦 客户端Exe版本管理完整方案

🎯 用户下载内容详解

不是下载源代码!用户下载的是什么?

用户下载的是编译好的、可执行的更新包,而不是源代码。

不同平台的下载内容

# Windows平台
# 下载内容: 完整的exe安装包或更新补丁
# 文件大小: 通常20-100MB
# 包含内容:
# ├── youdangdang.exe (主程序)
# ├── resources/ (内置资源)
# ├── chromium/ (内置浏览器)
# └── data/ (应用数据)

# macOS平台
# 下载内容: .dmg磁盘镜像或.app应用程序包
# 文件大小: 通常50-200MB
# 包含内容:
# ├── 游铛铛.app/
# │   ├── Contents/
# │   │   ├── MacOS/ (可执行文件)
# │   │   ├── Resources/ (图标、资源)
# │   │   └── Frameworks/ (依赖库)
# │   └── chromium/ (内置浏览器)

# Linux平台
# 下载内容: .AppImage自包含可执行文件
# 文件大小: 通常40-150MB
# 包含内容:
# └── youdangdang.AppImage (自包含一切的单文件)

🏢 公司服务器端Exe版本管理

核心架构

graph TB
    subgraph "开发环境"
        A[代码仓库] --> B[CI/CD流水线]
        B --> C[编译打包]
        C --> D[生成更新包]
    end

    subgraph "版本管理服务器"
        E[版本数据库] --> F[API服务]
        D --> G[上传更新包]
        G --> H[CDN存储]
        H --> I[分发网络]
    end

    subgraph "客户端"
        J[版本检查] --> F
        F --> K[下载更新]
        K --> I
    end

    L[管理后台] --> E
    L --> F

版本管理数据库设计

-- 版本信息表
CREATE TABLE app_versions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    version VARCHAR(20) NOT NULL,           -- 版本号,如 "1.0.1"
    version_code INT NOT NULL,              -- 版本代码,如 101
    platform ENUM('windows', 'macos', 'linux') NOT NULL,
    arch ENUM('x86_64', 'aarch64', 'arm64') NOT NULL,
    file_name VARCHAR(255) NOT NULL,        -- 文件名
    file_path VARCHAR(500) NOT NULL,        -- 存储路径
    file_size BIGINT NOT NULL,              -- 文件大小
    file_hash VARCHAR(128) NOT NULL,        -- SHA256哈希
    signature TEXT,                         -- 数字签名
    release_notes TEXT,                     -- 发布说明
    is_forced BOOLEAN DEFAULT FALSE,        -- 是否强制更新
    is_active BOOLEAN DEFAULT TRUE,         -- 是否激活
    download_count INT DEFAULT 0,           -- 下载次数
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    UNIQUE KEY unique_version_platform (version, platform, arch)
);

-- 版本发布记录表
CREATE TABLE version_releases (
    id INT PRIMARY KEY AUTO_INCREMENT,
    version_id INT NOT NULL,
    release_type ENUM('major', 'minor', 'patch', 'beta', 'alpha') DEFAULT 'minor',
    release_channel ENUM('stable', 'beta', 'dev') DEFAULT 'stable',
    min_version VARCHAR(20),                -- 最低支持版本
    max_version VARCHAR(20),                -- 最高支持版本
    target_users JSON,                      -- 目标用户群体
    rollout_percentage DECIMAL(5,2) DEFAULT 100.00, -- 灰度发布百分比
    is_active BOOLEAN DEFAULT TRUE,
    released_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    FOREIGN KEY (version_id) REFERENCES app_versions(id)
);

-- 用户版本记录表
CREATE TABLE user_versions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL,
    current_version VARCHAR(20),
    last_updated TIMESTAMP NULL,
    update_status ENUM('up_to_date', 'update_available', 'updating', 'update_failed') DEFAULT 'up_to_date',
    platform VARCHAR(50),
    device_info JSON,                       -- 设备信息
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_user_version (user_id, current_version)
);

版本管理API接口

# /api/admin/versions - 版本管理接口
@app.post("/versions")
async def upload_version(
    version: str = Form(...),
    platform: str = Form(...),
    file: UploadFile = File(...),
    release_notes: str = Form(...),
    is_forced: bool = Form(False)
):
    """
    上传新版本
    1. 验证版本号格式
    2. 计算文件哈希
    3. 生成数字签名
    4. 上传到CDN存储
    5. 保存到数据库
    """
    # 实现版本上传逻辑
    pass

@app.put("/versions/{version_id}/release")
async def release_version(
    version_id: int,
    rollout_percentage: float = 100.0,
    target_users: List[str] = None
):
    """
    发布版本
    支持灰度发布和定向发布
    """
    # 实现版本发布逻辑
    pass

@app.delete("/versions/{version_id}")
async def rollback_version(version_id: int):
    """
    回滚版本
    将指定版本标记为非活跃状态
    """
    # 实现版本回滚逻辑
    pass

# /api/updates - 客户端更新检查接口
@app.get("/updates/{platform}/{current_version}")
async def check_updates(platform: str, current_version: str):
    """
    检查更新
    返回最新可用版本信息
    """
    # 根据平台和当前版本返回更新信息
    latest_version = await get_latest_version(platform, current_version)

    if not latest_version:
        return Response(status_code=204)  # 无更新

    return {
        "version": latest_version.version,
        "notes": latest_version.release_notes,
        "pub_date": latest_version.created_at.isoformat(),
        "platforms": {
            f"{platform}-{latest_version.arch}": {
                "signature": latest_version.signature,
                "url": generate_download_url(latest_version),
                "size": latest_version.file_size
            }
        }
    }

@app.get("/updates/download/{version}/{platform}/{filename}")
async def download_update(version: str, platform: str, filename: str):
    """
    下载更新包
    从CDN重定向或直接提供下载
    """
    # 生成下载链接并返回
    pass

版本发布流程

1. 开发构建阶段

# 1. 代码提交到主分支
git push origin main

# 2. CI/CD 自动触发构建
# - 拉取最新代码
# - 运行测试
# - 编译不同平台版本
# - 生成更新包

# 3. 构建产物
npm run tauri:build -- --target all

# 输出结果:
# ├── bundles/
# │   ├── windows-x86_64/
# │   │   └── youdangdang_1.0.1_x64-setup.exe
# │   ├── macos-x86_64/
# │   │   └── youdangdang_1.0.1_x64.dmg
# │   └── linux-x86_64/
# │       └── youdangdang_1.0.1_amd64.AppImage

2. 版本管理阶段

# 管理员通过管理后台上传版本
POST /api/admin/versions
{
    "version": "1.0.1",
    "platform": "windows",
    "file": "youdangdang_1.0.1_x64-setup.exe",
    "release_notes": "- 修复扫货功能bug\n- 提升稳定性",
    "is_forced": false
}

# 系统自动处理:
# 1. 验证文件完整性
# 2. 计算SHA256哈希
# 3. 生成数字签名
# 4. 上传到CDN存储
# 5. 保存版本信息到数据库

3. 版本发布阶段

# 设置灰度发布
PUT /api/admin/versions/123/release
{
    "rollout_percentage": 10.0,  # 先发布给10%的用户
    "target_users": ["vip_users"]  # 只发布给VIP用户
}

# 观察使用情况后全量发布
PUT /api/admin/versions/123/release
{
    "rollout_percentage": 100.0
}

版本控制策略

语义化版本控制

主版本.次版本.补丁版本[-预发布标签]

1.0.0        # 初始版本
1.0.1        # 补丁版本
1.1.0        # 次版本(新增功能)
2.0.0        # 主版本(重大变更)
1.0.0-alpha  # 预发布版本
1.0.0-beta   # 测试版本

发布策略

class VersionStrategy:
    @staticmethod
    def should_force_update(version: str) -> bool:
        """判断是否需要强制更新"""
        major, minor, patch = version.split('.')

        # 主版本升级强制更新
        if int(major) > 1:
            return True

        # 包含安全修复的版本强制更新
        if 'SECURITY' in release_notes:
            return True

        return False

    @staticmethod
    def get_rollout_percentage(version: str, days_since_release: int) -> float:
        """根据发布时间动态调整发布比例"""
        if days_since_release < 1:
            return 1.0   # 第一天1%用户
        elif days_since_release < 3:
            return 10.0  # 前三天10%用户
        elif days_since_release < 7:
            return 50.0  # 第一周50%用户
        else:
            return 100.0 # 之后全量发布

监控和统计

版本使用统计

-- 版本分布统计
SELECT
    current_version,
    COUNT(*) as user_count,
    COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() as percentage
FROM user_versions
WHERE last_updated >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY current_version
ORDER BY user_count DESC;

-- 更新成功率统计
SELECT
    DATE(updated_at) as date,
    SUM(CASE WHEN update_status = 'up_to_date' THEN 1 ELSE 0 END) as success_count,
    SUM(CASE WHEN update_status = 'update_failed' THEN 1 ELSE 0 END) as failed_count,
    ROUND(
        SUM(CASE WHEN update_status = 'up_to_date' THEN 1 ELSE 0 END) * 100.0 /
        COUNT(*), 2
    ) as success_rate
FROM user_versions
WHERE updated_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(updated_at);

实时监控指标

  • 版本覆盖率: 各版本用户占比
  • 更新成功率: 更新操作成功比例
  • 下载速度: 平均下载耗时
  • 错误率: 更新失败率
  • 回滚率: 版本回滚频率

🔒 安全保障

数字签名机制

# 1. 生成密钥对
tauri signer generate

# 2. 签名更新包
tauri signer sign -k private_key.pem update.exe

# 3. 客户端验证签名
tauri updater verify -k public_key.pem update.exe

访问控制

# 版本管理API需要管理员权限
@app.post("/admin/versions")
async def upload_version(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_admin_user)  # 验证管理员权限
):
    # 只有管理员能上传版本
    pass

🚀 最佳实践

版本发布节奏

  • 补丁版本: 每周发布(修复bug)
  • 次版本: 每月发布(新增功能)
  • 主版本: 每季度发布(重大更新)

灰度发布策略

  1. 开发环境测试 (1%)
  2. 内部测试用户 (5%)
  3. VIP用户 (20%)
  4. 普通用户 (100%)

回滚准备

  • 保留最近5个版本
  • 自动备份用户数据
  • 一键回滚功能
  • 监控回滚影响

📋 故障排除

常见问题

版本文件损坏

现象: 客户端提示签名验证失败
解决: 重新生成签名,重新上传

CDN分发延迟

现象: 用户无法下载最新版本
解决: 检查CDN缓存策略,强制刷新

版本兼容性问题

现象: 某些用户无法更新
解决: 检查系统要求,添加兼容性检查

总结:公司服务器端通过专门的版本管理系统来管理exe文件,客户端下载的是编译好的可执行包,整个流程包括构建、上传、发布、分发等环节,确保安全、可控、高效的版本管理。