From 691961072a1cf191bc614903eaa71893e9eaa83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E8=BF=AA=E6=96=87?= <3117675914@qq.com> Date: Wed, 3 Jun 2026 09:02:06 +0800 Subject: [PATCH] feat: issue +journals/+series-update, ci +activate/+deactivate/+authorize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - issue +journals: 查看 Issue 活动日志 - issue +series-update: 批量更新 Issue 状态 - ci +activate: 激活 CI/CD - ci +deactivate: 停用 CI/CD - ci +authorize: 检查 CI/CD 授权状态 Co-Authored-By: Claude Opus 4.8 --- shortcuts/ci/ci.go | 42 ++++++++++++++++++++++++ shortcuts/issue/issue.go | 70 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/shortcuts/ci/ci.go b/shortcuts/ci/ci.go index 6794c47..0cd3b14 100644 --- a/shortcuts/ci/ci.go +++ b/shortcuts/ci/ci.go @@ -95,6 +95,48 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { } return ctx.Output(env) }, + { + Name: "activate", + Description: "为仓库激活 CI/CD 功能", + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/activate", nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, + { + Name: "deactivate", + Description: "停用仓库的 CI/CD 功能", + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + env, err := ctx.CallAPI("DELETE", ctx.RepoPath()+"/deactivate", nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, + { + Name: "authorize", + Description: "检查仓库的 CI/CD 授权状态", + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + env, err := ctx.CallAPI("GET", ctx.RepoPath()+"/ci_authorize", nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, }, } } diff --git a/shortcuts/issue/issue.go b/shortcuts/issue/issue.go index 808d7fd..bab0f69 100644 --- a/shortcuts/issue/issue.go +++ b/shortcuts/issue/issue.go @@ -363,6 +363,76 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { return ctx.Output(env) }, }, + { + Name: "journals", + Description: "查看 Issue 的活动日志(评论、状态变更等)", + Flags: []common.Flag{ + {Name: "number", Short: "n", Usage: "Issue 编号(网页 URL 中的数字)", Required: true}, + }, + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + number, err := ctx.RequireArg("number") + if err != nil { + return err + } + path := fmt.Sprintf("%s/issues/%s/journals", v1RepoPath(ctx), number) + env, err := ctx.CallAPI("GET", path, nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, + { + Name: "series-update", + Description: "批量更新多个 Issue 的状态(一键关闭/重开多个 Issue)", + Flags: []common.Flag{ + {Name: "ids", Usage: "Issue ID 列表(逗号分隔,如 1,2,3)", Required: true}, + {Name: "status", Short: "s", Usage: "目标状态: open / closed", Required: true}, + }, + Run: func(ctx *common.RuntimeContext) error { + if err := ctx.ResolveOwnerRepo(); err != nil { + return err + } + idsStr, err := ctx.RequireArg("ids") + if err != nil { + return err + } + status, err := ctx.RequireArg("status") + if err != nil { + return err + } + + // 解析逗号分隔的 ID 列表 + idParts := strings.Split(idsStr, ",") + ids := make([]int, 0, len(idParts)) + for _, p := range idParts { + id, err := strconv.Atoi(strings.TrimSpace(p)) + if err != nil { + return fmt.Errorf("无效的 Issue ID: %s", p) + } + ids = append(ids, id) + } + + // 转换状态为数字 + statusID, err := normalizeIssueStatus(status) + if err != nil { + return err + } + + body := map[string]interface{}{ + "ids": ids, + "status_id": statusID, + } + env, err := ctx.CallAPI("POST", ctx.RepoPath()+"/issues/series_update", body) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, } }