diff --git a/README.md b/README.md index e10c5dd6..6392e548 100644 --- a/README.md +++ b/README.md @@ -483,6 +483,9 @@ gitlink-cli attachment +upload -f ./dist/app-v1.0.0.tar.gz -d "v1.0.0 release as # Download an attachment by id to a local file gitlink-cli attachment +download -i -o ./app-v1.0.0.tar.gz + +# Delete an attachment by id +gitlink-cli attachment +delete -i ``` ### CI/CD Operations diff --git a/README.zh-CN.md b/README.zh-CN.md index f8747a81..b878bf9a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -474,6 +474,9 @@ gitlink-cli attachment +upload -f ./dist/app-v1.0.0.tar.gz -d "v1.0.0 发布产 # 按 id 下载附件到本地文件 gitlink-cli attachment +download -i -o ./app-v1.0.0.tar.gz + +# 按 id 删除附件 +gitlink-cli attachment +delete -i ``` ### 流水线管理 diff --git a/internal/i18n/locales/en-US.json b/internal/i18n/locales/en-US.json index f376ffe8..184ada00 100644 --- a/internal/i18n/locales/en-US.json +++ b/internal/i18n/locales/en-US.json @@ -1,6 +1,8 @@ { "cmd.api.long": "Send arbitrary HTTP requests to the GitLink API. Authentication is injected automatically.", "cmd.api.short": "Make raw API requests to GitLink", + "cmd.attachment.delete.long": "Delete a platform attachment by id or uuid. Only the attachment owner can delete it.", + "cmd.attachment.delete.short": "Delete an attachment by id", "cmd.attachment.download.long": "Download a platform attachment by id and stream it to a local file.", "cmd.attachment.download.short": "Download an attachment to a local file", "cmd.attachment.short": "Attachment upload and download", diff --git a/internal/i18n/locales/zh-CN.json b/internal/i18n/locales/zh-CN.json index b6481957..9e623da2 100644 --- a/internal/i18n/locales/zh-CN.json +++ b/internal/i18n/locales/zh-CN.json @@ -1,6 +1,8 @@ { "cmd.api.long": "向 GitLink API 发送任意 HTTP 请求。认证信息会自动注入。", "cmd.api.short": "向 GitLink 发起原始 API 请求", + "cmd.attachment.delete.long": "按 id 或 uuid 删除平台附件。仅附件所有者可删除。", + "cmd.attachment.delete.short": "按 id 删除附件", "cmd.attachment.download.long": "按 id 下载平台附件并流式写入本地文件。", "cmd.attachment.download.short": "下载附件到本地文件", "cmd.attachment.short": "附件上传与下载", diff --git a/shortcuts/attachment/attachment.go b/shortcuts/attachment/attachment.go index fadd1009..1677d7bc 100644 --- a/shortcuts/attachment/attachment.go +++ b/shortcuts/attachment/attachment.go @@ -82,5 +82,24 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut { }) }, }, + { + Name: "delete", + Description: tr.T("cmd.attachment.delete.short"), + Long: tr.T("cmd.attachment.delete.long"), + Flags: []common.Flag{ + {Name: "id", Short: "i", Usage: tr.T("flag.attachment.id"), Required: true}, + }, + Run: func(ctx *common.RuntimeContext) error { + id, err := ctx.RequireArg("id") + if err != nil { + return err + } + env, err := ctx.Client.Delete("/attachments/"+id, nil) + if err != nil { + return err + } + return ctx.Output(env) + }, + }, } } diff --git a/shortcuts/attachment/attachment_test.go b/shortcuts/attachment/attachment_test.go index a67bf4b0..54a049f3 100644 --- a/shortcuts/attachment/attachment_test.go +++ b/shortcuts/attachment/attachment_test.go @@ -16,8 +16,8 @@ import ( func TestShortcutsRegistered(t *testing.T) { shortcuts := Shortcuts() - if len(shortcuts) != 2 { - t.Fatalf("expected 2 shortcuts, got %d", len(shortcuts)) + if len(shortcuts) != 3 { + t.Fatalf("expected 3 shortcuts, got %d", len(shortcuts)) } names := map[string]bool{} for _, s := range shortcuts { @@ -26,7 +26,7 @@ func TestShortcutsRegistered(t *testing.T) { t.Fatalf("shortcut %q has empty description", s.Name) } } - for _, want := range []string{"upload", "download"} { + for _, want := range []string{"upload", "download", "delete"} { if !names[want] { t.Fatalf("missing shortcut %q", want) } @@ -190,3 +190,24 @@ func TestDownloadHTTPError(t *testing.T) { t.Fatal("output file should not be created on HTTP error") } } + +func TestDeleteAttachment(t *testing.T) { + var gotMethod, gotPath string + ctx := newTestContext(t, func(w http.ResponseWriter, r *http.Request) { + gotMethod = r.Method + gotPath = r.URL.Path + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{"status": 0, "message": "删除成功"}) + }, map[string]string{"id": "abc-uuid"}) + ctx.Tr = i18n.Default() + + if err := findShortcut(t, "delete").Run(ctx); err != nil { + t.Fatalf("delete error: %v", err) + } + if gotMethod != http.MethodDelete { + t.Fatalf("method = %q, want DELETE", gotMethod) + } + if gotPath != "/attachments/abc-uuid.json" { + t.Fatalf("path = %q, want /attachments/abc-uuid.json", gotPath) + } +}