init: 初始化项目
This commit is contained in:
267
docs/UPDATE_CHECK.md
Normal file
267
docs/UPDATE_CHECK.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 更新检查 API 文档
|
||||
|
||||
## 🔧 修复内容
|
||||
|
||||
### 已修复的 Bug
|
||||
|
||||
1. ✅ **版本比较逻辑错误**
|
||||
- 之前:使用字符串比较(`"1.10.0" < "1.9.0"` 错误)
|
||||
- 现在:实现语义化版本号比较(semver)
|
||||
|
||||
2. ✅ **Asset 查询错误处理缺失**
|
||||
- 之前:查询失败时返回空 URL
|
||||
- 现在:正确处理错误并返回明确的错误信息
|
||||
|
||||
3. ✅ **参数验证缺失**
|
||||
- 现在:验证所有必需参数(app, version, platform, arch)
|
||||
|
||||
4. ✅ **排序逻辑优化**
|
||||
- 之前:按 version 字符串排序
|
||||
- 现在:按 pub_date 排序,更准确
|
||||
|
||||
5. ✅ **响应格式统一**
|
||||
- 现在使用统一的响应格式,并添加 checksum 字段
|
||||
|
||||
## 📝 API 使用
|
||||
|
||||
### 端点
|
||||
|
||||
```
|
||||
GET /api/check-update
|
||||
```
|
||||
|
||||
### 请求参数
|
||||
|
||||
| 参数 | 类型 | 必需 | 说明 |
|
||||
|------|------|------|------|
|
||||
| app | string | ✅ | 应用 ID |
|
||||
| version | string | ✅ | 当前版本号 |
|
||||
| platform | string | ✅ | 平台(windows/darwin/linux) |
|
||||
| arch | string | ✅ | 架构(amd64/arm64/386) |
|
||||
|
||||
### 响应格式
|
||||
|
||||
**有更新:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"update": true,
|
||||
"version": "1.2.0",
|
||||
"notes": "更新说明\n- 新功能\n- Bug修复",
|
||||
"url": "http://localhost:9050/files/releases/2/windows-amd64/app.exe",
|
||||
"checksum": "sha256哈希值"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**无需更新:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "ok",
|
||||
"data": {
|
||||
"update": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应:**
|
||||
```json
|
||||
{
|
||||
"code": 500,
|
||||
"msg": "no asset found for this platform and architecture"
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 测试示例
|
||||
|
||||
### PowerShell 测试
|
||||
|
||||
```powershell
|
||||
# 测试更新检查(需要更新)
|
||||
$params = @{
|
||||
app = "test-app"
|
||||
version = "1.0.0"
|
||||
platform = "windows"
|
||||
arch = "amd64"
|
||||
}
|
||||
$query = ($params.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join "&"
|
||||
Invoke-RestMethod -Uri "http://localhost:9050/api/check-update?$query"
|
||||
|
||||
# 测试更新检查(已是最新)
|
||||
$params = @{
|
||||
app = "test-app"
|
||||
version = "2.0.0"
|
||||
platform = "windows"
|
||||
arch = "amd64"
|
||||
}
|
||||
$query = ($params.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join "&"
|
||||
Invoke-RestMethod -Uri "http://localhost:9050/api/check-update?$query"
|
||||
|
||||
# 测试不存在的平台
|
||||
$params = @{
|
||||
app = "test-app"
|
||||
version = "1.0.0"
|
||||
platform = "windows"
|
||||
arch = "arm" # 假设没有这个架构的版本
|
||||
}
|
||||
$query = ($params.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join "&"
|
||||
Invoke-RestMethod -Uri "http://localhost:9050/api/check-update?$query"
|
||||
```
|
||||
|
||||
### curl 测试
|
||||
|
||||
```bash
|
||||
# 测试更新检查
|
||||
curl "http://localhost:9050/api/check-update?app=test-app&version=1.0.0&platform=windows&arch=amd64"
|
||||
|
||||
# 测试参数缺失
|
||||
curl "http://localhost:9050/api/check-update?app=test-app"
|
||||
```
|
||||
|
||||
## 📦 版本号比较规则
|
||||
|
||||
实现了完整的语义化版本号(semver)比较:
|
||||
|
||||
### 支持的版本格式
|
||||
|
||||
- `1.0.0` - 标准格式
|
||||
- `v1.0.0` - 带 v 前缀
|
||||
- `1.0.0-beta.1` - 预发布版本
|
||||
- `1.0.0+build.123` - 构建元数据
|
||||
|
||||
### 比较规则
|
||||
|
||||
1. **主版本号优先**:`2.0.0 > 1.9.9`
|
||||
2. **次版本号次之**:`1.10.0 > 1.9.0`
|
||||
3. **修订号最后**:`1.0.10 > 1.0.9`
|
||||
4. **预发布版本**:`1.0.0 > 1.0.0-rc.1 > 1.0.0-beta.1 > 1.0.0-alpha.1`
|
||||
|
||||
### 示例
|
||||
|
||||
```go
|
||||
// pkg/util/version.go
|
||||
|
||||
CompareVersion("1.10.0", "1.9.0") // 返回 1 (1.10.0 > 1.9.0)
|
||||
CompareVersion("2.0.0", "1.99.99") // 返回 1 (2.0.0 > 1.99.99)
|
||||
CompareVersion("1.0.0", "1.0.0-beta") // 返回 1 (正式版 > 预发布版)
|
||||
CompareVersion("v1.0.0", "1.0.0") // 返回 0 (相等)
|
||||
|
||||
IsNewerVersion("1.0.0", "1.1.0") // 返回 true
|
||||
IsNewerVersion("1.1.0", "1.0.0") // 返回 false
|
||||
```
|
||||
|
||||
## 🔄 完整更新流程
|
||||
|
||||
### 1. 准备数据
|
||||
|
||||
```powershell
|
||||
# 创建应用
|
||||
Invoke-RestMethod -Method POST -Uri "http://localhost:9050/api/apps" `
|
||||
-ContentType "application/json" `
|
||||
-Body '{"id":"my-app","name":"我的应用","description":"测试"}'
|
||||
|
||||
# 创建版本 1.0.0
|
||||
Invoke-RestMethod -Method POST -Uri "http://localhost:9050/api/releases" `
|
||||
-ContentType "application/json" `
|
||||
-Body '{"appID":"my-app","version":"1.0.0","notes":"初始版本","channel":"stable","pubDate":"2026-03-10T10:00:00Z"}'
|
||||
|
||||
# 上传 1.0.0 的 Windows 版本
|
||||
$form = @{
|
||||
file = Get-Item -Path "D:\app-v1.0.0.exe"
|
||||
platform = "windows"
|
||||
arch = "amd64"
|
||||
}
|
||||
Invoke-RestMethod -Uri "http://localhost:9050/api/releases/1/assets/upload" -Method Post -Form $form
|
||||
|
||||
# 创建版本 1.1.0
|
||||
Invoke-RestMethod -Method POST -Uri "http://localhost:9050/api/releases" `
|
||||
-ContentType "application/json" `
|
||||
-Body '{"appID":"my-app","version":"1.1.0","notes":"新增功能","channel":"stable","pubDate":"2026-03-11T10:00:00Z"}'
|
||||
|
||||
# 上传 1.1.0 的 Windows 版本
|
||||
$form = @{
|
||||
file = Get-Item -Path "D:\app-v1.1.0.exe"
|
||||
platform = "windows"
|
||||
arch = "amd64"
|
||||
}
|
||||
Invoke-RestMethod -Uri "http://localhost:9050/api/releases/2/assets/upload" -Method Post -Form $form
|
||||
```
|
||||
|
||||
### 2. 客户端检查更新
|
||||
|
||||
```powershell
|
||||
# 用户当前使用 1.0.0,检查更新
|
||||
$response = Invoke-RestMethod -Uri "http://localhost:9050/api/check-update?app=my-app&version=1.0.0&platform=windows&arch=amd64"
|
||||
|
||||
if ($response.data.update) {
|
||||
Write-Host "发现新版本: $($response.data.version)"
|
||||
Write-Host "更新说明: $($response.data.notes)"
|
||||
Write-Host "下载地址: $($response.data.url)"
|
||||
Write-Host "校验和: $($response.data.checksum)"
|
||||
|
||||
# 下载更新
|
||||
Invoke-WebRequest -Uri $response.data.url -OutFile "app-update.exe"
|
||||
|
||||
# 验证校验和(可选)
|
||||
$hash = (Get-FileHash -Path "app-update.exe" -Algorithm SHA256).Hash
|
||||
if ($hash.ToLower() -eq $response.data.checksum) {
|
||||
Write-Host "✅ 文件校验通过"
|
||||
} else {
|
||||
Write-Host "❌ 文件校验失败"
|
||||
}
|
||||
} else {
|
||||
Write-Host "✅ 当前已是最新版本"
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ 错误处理
|
||||
|
||||
所有可能的错误情况:
|
||||
|
||||
| 错误信息 | 原因 | 解决方法 |
|
||||
|---------|------|---------|
|
||||
| `app is required` | 缺少 app 参数 | 提供应用 ID |
|
||||
| `version is required` | 缺少 version 参数 | 提供当前版本号 |
|
||||
| `platform is required` | 缺少 platform 参数 | 提供平台信息 |
|
||||
| `arch is required` | 缺少 arch 参数 | 提供架构信息 |
|
||||
| `no release found for this app` | 应用没有发布版本 | 先创建版本发布 |
|
||||
| `no asset found for this platform and architecture` | 没有对应平台的安装包 | 上传对应平台的资源 |
|
||||
| `asset URL is empty` | 资源记录存在但 URL 为空 | 检查资源数据完整性 |
|
||||
|
||||
## ✅ 改进总结
|
||||
|
||||
### 修复前的问题
|
||||
|
||||
```go
|
||||
// ❌ 错误的版本比较
|
||||
if req.Version >= latest.Version { // "1.10.0" < "1.9.0" !
|
||||
return &CheckResponse{Update: false}, nil
|
||||
}
|
||||
|
||||
// ❌ 没有错误处理
|
||||
db.Where(...).First(&asset) // 忽略了错误
|
||||
return &CheckResponse{URL: asset.URL} // URL 可能为空
|
||||
```
|
||||
|
||||
### 修复后
|
||||
|
||||
```go
|
||||
// ✅ 正确的版本比较
|
||||
if !util.IsNewerVersion(req.Version, latest.Version) {
|
||||
return &CheckResponse{Update: false}, nil
|
||||
}
|
||||
|
||||
// ✅ 完整的错误处理
|
||||
err = db.Where(...).First(&ast).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("no asset found...")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
```
|
||||
|
||||
现在更新检查功能已经完全可靠!🎉
|
||||
Reference in New Issue
Block a user