feat(attachment): 新增 +delete 按 id/uuid 删除附件

This commit is contained in:
Taoyouce 2026-07-07 15:46:56 +00:00
parent cd5338f303
commit b068b4a775
6 changed files with 53 additions and 3 deletions

View File

@ -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 <attachment_id> -o ./app-v1.0.0.tar.gz
# Delete an attachment by id
gitlink-cli attachment +delete -i <attachment_id>
```
### CI/CD Operations

View File

@ -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 <attachment_id> -o ./app-v1.0.0.tar.gz
# 按 id 删除附件
gitlink-cli attachment +delete -i <attachment_id>
```
### 流水线管理

View File

@ -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",

View File

@ -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": "附件上传与下载",

View File

@ -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)
},
},
}
}

View File

@ -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)
}
}