Skip to content

Commit 7bdccf6

Browse files
committed
feat: add auto-update functionality
✨ Features: - Auto-check for updates every 24 hours - Auto-download and install new versions (configurable) - Manual update command: qkflow update-cli - Smart update detection from GitHub Releases - Safe update with automatic backup and rollback - Platform-specific binary download (macOS/Linux/Windows) 🔧 Configuration: - Add auto_update config (default: true) - Add github_owner and github_repo config - Update init wizard to configure auto-update - Support AUTO_UPDATE environment variable 📚 Documentation: - Add AUTO_UPDATE.md guide - Document all update features and workflows 🛡️ Safety: - Background silent checking (non-blocking) - Automatic backup before update - Rollback on failure - 24-hour check interval with timestamp file
1 parent 28efec3 commit 7bdccf6

6 files changed

Lines changed: 571 additions & 6 deletions

File tree

go-version/AUTO_UPDATE.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# 自动更新功能
2+
3+
## 概述
4+
5+
qkflow 内置了智能的自动更新功能,可以确保你始终使用最新版本,享受最新特性和 bug 修复。
6+
7+
## 特性
8+
9+
-**自动检查更新** - 每24小时自动检查一次新版本
10+
-**后台静默运行** - 不影响当前命令的执行
11+
-**智能更新** - 发现新版本时自动下载并安装
12+
-**可配置** - 可以选择启用或禁用自动更新
13+
-**手动更新** - 随时可以手动触发更新
14+
-**安全备份** - 更新失败时自动恢复旧版本
15+
16+
## 工作原理
17+
18+
### 1. 自动检查
19+
20+
每次运行 qkflow 命令时(除了 `init``version``help``update-cli`),系统会:
21+
22+
1. 检查距离上次检查更新是否已超过 24 小时
23+
2. 如果是,则在后台检查 GitHub Releases 的最新版本
24+
3. 比较当前版本和最新版本
25+
26+
### 2. 自动更新(默认开启)
27+
28+
如果发现新版本且启用了自动更新:
29+
30+
```bash
31+
🎉 New version available: v1.1.0 (current: v1.0.0)
32+
⬇️ Downloading update...
33+
✅ Successfully updated to version v1.1.0! Please restart qkflow.
34+
```
35+
36+
系统会:
37+
1. 从 GitHub Releases 下载对应平台的二进制文件
38+
2. 备份当前版本
39+
3. 替换为新版本
40+
4. 提示重启 qkflow
41+
42+
### 3. 手动更新模式
43+
44+
如果禁用了自动更新,只会提示:
45+
46+
```bash
47+
🎉 New version available: v1.1.0 (current: v1.0.0)
48+
Run 'qkflow update-cli' to update, or visit: https://github.com/Wangggym/quick-workflow/releases
49+
```
50+
51+
## 配置自动更新
52+
53+
### 初始化时配置
54+
55+
运行 `qkflow init` 时会询问:
56+
57+
```bash
58+
Enable automatic updates? (recommended) [Y/n]:
59+
```
60+
61+
-`Y` 或 直接回车:启用自动更新(推荐)
62+
-`n`:禁用自动更新
63+
64+
### 修改配置
65+
66+
编辑配置文件 `~/.qkflow/config.yaml`(或 iCloud Drive 路径):
67+
68+
```yaml
69+
# 启用自动更新(推荐)
70+
auto_update: true
71+
72+
# 或禁用自动更新
73+
auto_update: false
74+
```
75+
76+
修改后,下次运行 qkflow 命令时生效。
77+
78+
### 使用环境变量
79+
80+
```bash
81+
# 临时禁用自动更新
82+
export AUTO_UPDATE=false
83+
qkflow pr create
84+
85+
# 临时启用自动更新
86+
export AUTO_UPDATE=true
87+
qkflow pr create
88+
```
89+
90+
## 手动更新
91+
92+
随时可以手动检查并更新到最新版本:
93+
94+
```bash
95+
qkflow update-cli
96+
```
97+
98+
这会:
99+
1. 立即检查最新版本
100+
2. 如果有新版本,下载并安装
101+
3. 如果已是最新版本,显示确认信息
102+
103+
示例输出:
104+
105+
```bash
106+
# 有新版本
107+
🎉 New version available: v1.1.0 (current: v1.0.0)
108+
⬇️ Downloading update...
109+
✅ Successfully updated to version v1.1.0! Please restart qkflow.
110+
111+
# 已是最新版本
112+
✅ You are already running the latest version (v1.0.0)
113+
```
114+
115+
## 更新频率
116+
117+
- **检查频率**: 每 24 小时检查一次
118+
- **时间戳文件**: `~/.qkflow/.last_update_check`
119+
- **超时设置**: API 请求 5 秒超时,下载 5 分钟超时
120+
121+
可以手动删除时间戳文件来强制立即检查:
122+
123+
```bash
124+
rm ~/.qkflow/.last_update_check
125+
```
126+
127+
## 支持的平台
128+
129+
自动更新支持所有 qkflow 支持的平台:
130+
131+
- ✅ macOS (Intel) - `qkflow-darwin-amd64`
132+
- ✅ macOS (Apple Silicon) - `qkflow-darwin-arm64`
133+
- ✅ Linux (amd64) - `qkflow-linux-amd64`
134+
- ✅ Windows (amd64) - `qkflow-windows-amd64.exe`
135+
136+
## 安全性
137+
138+
### 下载来源
139+
140+
- 所有二进制文件从 GitHub Releases 官方下载
141+
- URL: `https://api.github.com/repos/Wangggym/quick-workflow/releases/latest`
142+
- 使用 HTTPS 加密传输
143+
144+
### 更新流程
145+
146+
1. 下载到临时文件
147+
2. 设置可执行权限
148+
3. 备份当前版本 (`qkflow.backup`)
149+
4. 替换为新版本
150+
5. 删除备份文件
151+
6. 如果失败,自动恢复备份
152+
153+
### 权限要求
154+
155+
更新需要对二进制文件所在目录有写权限:
156+
157+
- 如果安装在 `/usr/local/bin/`,需要 sudo 权限
158+
- 如果安装在 `~/bin/``GOPATH/bin`,不需要特殊权限
159+
160+
## 常见问题
161+
162+
### Q: 自动更新会中断我的工作吗?
163+
164+
A: 不会。更新检查在后台运行,不阻塞当前命令。只有在下载完成后才会提示重启。
165+
166+
### Q: 更新失败怎么办?
167+
168+
A: 系统会自动恢复备份。你可以手动运行 `qkflow update-cli` 重试,或访问 GitHub Releases 手动下载。
169+
170+
### Q: 如何查看当前版本?
171+
172+
```bash
173+
qkflow version
174+
```
175+
176+
### Q: 如何禁用自动更新?
177+
178+
编辑 `~/.qkflow/config.yaml`
179+
180+
```yaml
181+
auto_update: false
182+
```
183+
184+
或使用环境变量:
185+
186+
```bash
187+
export AUTO_UPDATE=false
188+
```
189+
190+
### Q: 能否回滚到旧版本?
191+
192+
可以。访问 [GitHub Releases](https://github.com/Wangggym/quick-workflow/releases) 下载特定版本的二进制文件,手动替换即可。
193+
194+
### Q: 自动更新失败会显示错误吗?
195+
196+
A: 不会。为了不影响用户体验,更新失败时静默处理。可以手动运行 `qkflow update-cli` 查看详细错误。
197+
198+
## 最佳实践
199+
200+
1. **推荐启用自动更新** - 确保始终使用最新版本,享受最新特性和 bug 修复
201+
202+
2. **定期手动检查** - 如果禁用了自动更新,建议定期运行:
203+
```bash
204+
qkflow update-cli
205+
```
206+
207+
3. **在重要操作前更新** - 在执行重要操作前,确保使用最新版本:
208+
```bash
209+
qkflow update-cli
210+
qkflow pr create
211+
```
212+
213+
4. **CI/CD 环境** - 在 CI/CD 中,建议禁用自动更新,使用固定版本:
214+
```bash
215+
export AUTO_UPDATE=false
216+
```
217+
218+
## 更新日志
219+
220+
查看完整的更新历史和版本说明:
221+
222+
👉 [GitHub Releases](https://github.com/Wangggym/quick-workflow/releases)
223+
224+
## 反馈
225+
226+
如果在使用自动更新功能时遇到问题,请:
227+
228+
- 🐛 [报告 Bug](https://github.com/Wangggym/quick-workflow/issues/new?labels=bug)
229+
- 💡 [提出建议](https://github.com/Wangggym/quick-workflow/issues/new?labels=enhancement)
230+
231+
---
232+
233+
**享受无缝的自动更新体验!** 🚀
234+

go-version/cmd/qkflow/commands/init.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ func runInit(cmd *cobra.Command, args []string) {
4848
}
4949
cfg.GitHubToken = ghToken
5050

51+
// GitHub Owner
52+
githubOwner, err := ui.PromptInput("Enter your GitHub username or organization:", true)
53+
if err != nil {
54+
ui.Error(fmt.Sprintf("Failed to get GitHub owner: %v", err))
55+
return
56+
}
57+
cfg.GitHubOwner = githubOwner
58+
59+
// GitHub Repo
60+
githubRepo, err := ui.PromptInput("Enter your GitHub repository name:", true)
61+
if err != nil {
62+
ui.Error(fmt.Sprintf("Failed to get GitHub repo: %v", err))
63+
return
64+
}
65+
cfg.GitHubRepo = githubRepo
66+
5167
// Jira Service Address
5268
jiraAddr, err := ui.PromptInput("Enter your Jira service address (e.g., https://your-domain.atlassian.net):", true)
5369
if err != nil {
@@ -82,6 +98,19 @@ func runInit(cmd *cobra.Command, args []string) {
8298
}
8399
}
84100

101+
// Auto Update (default: true)
102+
autoUpdate, err := ui.PromptConfirm("Enable automatic updates? (recommended)", true)
103+
if err == nil {
104+
cfg.AutoUpdate = autoUpdate
105+
} else {
106+
cfg.AutoUpdate = true // Default to true
107+
}
108+
if cfg.AutoUpdate {
109+
ui.Success("✅ Auto-update enabled - qkflow will keep itself up to date")
110+
} else {
111+
ui.Info("ℹ️ Auto-update disabled - run 'qkflow update-cli' to update manually")
112+
}
113+
85114
// Save configuration
86115
if err := config.Save(cfg); err != nil {
87116
ui.Error(fmt.Sprintf("Failed to save configuration: %v", err))
@@ -101,9 +130,11 @@ func runInit(cmd *cobra.Command, args []string) {
101130
fmt.Println()
102131

103132
ui.Info("You can now use the following commands:")
104-
fmt.Println(" qkflow pr create - Create a PR and update Jira")
105-
fmt.Println(" qkflow pr merge - Merge a PR and update Jira")
106-
fmt.Println(" qkflow update - Quick commit and push with PR title")
133+
fmt.Println(" qkflow pr create - Create a PR and update Jira")
134+
fmt.Println(" qkflow pr merge - Merge a PR and update Jira")
135+
fmt.Println(" qkflow update - Quick commit and push with PR title")
136+
fmt.Println(" qkflow update-cli - Update qkflow to the latest version")
137+
fmt.Println(" qkflow jira list - List Jira status mappings")
107138
fmt.Println()
108139
}
109140

go-version/cmd/qkflow/commands/root.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/Wangggym/quick-workflow/internal/ui"
7+
"github.com/Wangggym/quick-workflow/internal/updater"
78
"github.com/Wangggym/quick-workflow/internal/utils"
89
"github.com/Wangggym/quick-workflow/pkg/config"
910
"github.com/spf13/cobra"
@@ -22,16 +23,17 @@ var rootCmd = &cobra.Command{
2223
Long: `qkflow is a CLI tool to streamline your GitHub and Jira workflow.
2324
It automates common tasks like creating PRs, updating Jira status, and more.`,
2425
PersistentPreRun: func(cmd *cobra.Command, args []string) {
25-
// 对于某些命令不需要检查配置
26-
skipConfigCheck := []string{"init", "version", "help"}
26+
// 对于某些命令不需要检查配置和更新
27+
skipConfigCheck := []string{"init", "version", "help", "update-cli"}
2728
for _, skip := range skipConfigCheck {
2829
if cmd.Name() == skip || cmd.Parent().Name() == skip {
2930
return
3031
}
3132
}
3233

3334
// 检查配置
34-
if _, err := config.Load(); err != nil {
35+
cfg, err := config.Load()
36+
if err != nil {
3537
ui.Error(fmt.Sprintf("Failed to load config: %v", err))
3638
ui.Warning("Please run 'qkflow init' to configure the tool")
3739
return
@@ -40,6 +42,13 @@ It automates common tasks like creating PRs, updating Jira status, and more.`,
4042
if !config.IsConfigured() {
4143
ui.Warning("Configuration incomplete. Please run 'qkflow init' to complete setup")
4244
}
45+
46+
// 检查更新(后台静默执行,不阻塞主流程)
47+
go func() {
48+
if err := updater.CheckAndUpdate(Version, cfg.AutoUpdate); err != nil {
49+
// 静默失败,不影响主流程
50+
}
51+
}()
4352
},
4453
}
4554

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package commands
2+
3+
import (
4+
"github.com/Wangggym/quick-workflow/internal/updater"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
var updateCLICmd = &cobra.Command{
9+
Use: "update-cli",
10+
Short: "Update qkflow to the latest version",
11+
Long: `Check for updates and install the latest version of qkflow.`,
12+
Run: func(cmd *cobra.Command, args []string) {
13+
if err := updater.ManualUpdate(Version); err != nil {
14+
cmd.PrintErrf("Failed to update: %v\n", err)
15+
return
16+
}
17+
},
18+
}
19+
20+
func init() {
21+
rootCmd.AddCommand(updateCLICmd)
22+
}
23+

0 commit comments

Comments
 (0)