fix(milestone): make +create --description/--due-date optional to match platform API
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
9749a4c832
commit
f43afa75a6
|
|
@ -0,0 +1,20 @@
|
|||
# milestone +create 放宽必填参数
|
||||
|
||||
## 背景
|
||||
|
||||
`milestone +create` 之前把 `--description` 与 `--due-date` 标记为必填,
|
||||
但平台 v1 API 创建里程碑仅要求 `name`(已在生产环境
|
||||
`POST /api/v1/:owner/:repo/milestones` 用仅含 `{"name": ...}` 的请求验证成功)。
|
||||
CLI 侧的额外限制迫使用户为可选字段编造内容。
|
||||
|
||||
## 变更
|
||||
|
||||
- `--description` 与 `--due-date` 改为可选;未提供时请求体中省略对应字段。
|
||||
- `milestonePayload` 的 `requireAll` 参数收敛为 `requireName`,仅校验 `--name`。
|
||||
|
||||
## 验证
|
||||
|
||||
- `go test ./shortcuts/milestone/`(新增 `TestMilestoneCreateNameOnly`
|
||||
断言未提供的可选字段不出现在请求体中)
|
||||
- `go vet ./...`
|
||||
- 生产 gitlink.org.cn 实测:`milestone +create -n <name>` 仅带名称创建成功。
|
||||
|
|
@ -46,8 +46,8 @@ func Shortcuts() []*common.Shortcut {
|
|||
Description: "Create a milestone",
|
||||
Flags: []common.Flag{
|
||||
{Name: "name", Short: "n", Usage: "Milestone name", Required: true},
|
||||
{Name: "description", Short: "d", Usage: "Milestone description", Required: true},
|
||||
{Name: "due-date", Usage: "Due date in YYYY-MM-DD format", Required: true},
|
||||
{Name: "description", Short: "d", Usage: "Milestone description"},
|
||||
{Name: "due-date", Usage: "Due date in YYYY-MM-DD format"},
|
||||
},
|
||||
Run: func(ctx *common.RuntimeContext) error {
|
||||
if err := ctx.ResolveOwnerRepo(); err != nil {
|
||||
|
|
@ -168,7 +168,7 @@ func milestoneStatusPath(ctx *common.RuntimeContext, id string) string {
|
|||
return fmt.Sprintf("%s/milestones/%s/update_status", ctx.RepoPath(), url.PathEscape(id))
|
||||
}
|
||||
|
||||
func milestonePayload(ctx *common.RuntimeContext, requireAll bool) (map[string]interface{}, error) {
|
||||
func milestonePayload(ctx *common.RuntimeContext, requireName bool) (map[string]interface{}, error) {
|
||||
payload := map[string]interface{}{}
|
||||
if name := ctx.Arg("name"); name != "" {
|
||||
payload["name"] = name
|
||||
|
|
@ -180,11 +180,9 @@ func milestonePayload(ctx *common.RuntimeContext, requireAll bool) (map[string]i
|
|||
payload["effective_date"] = dueDate
|
||||
}
|
||||
|
||||
if requireAll {
|
||||
for _, name := range []string{"name", "description", "due-date"} {
|
||||
if _, err := ctx.RequireArg(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if requireName {
|
||||
if _, err := ctx.RequireArg("name"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return payload, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,31 @@ func TestMilestoneCreatePayload(t *testing.T) {
|
|||
assertEqual(t, payload["effective_date"], "2026-07-01")
|
||||
}
|
||||
|
||||
func TestMilestoneCreateNameOnly(t *testing.T) {
|
||||
var payload map[string]interface{}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assertRequest(t, r, "POST", "/v1/owner/repo/milestones.json")
|
||||
payload = decodeJSON(t, r)
|
||||
writeJSON(t, w, map[string]interface{}{"status": 0, "message": "success"})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
err := runMilestoneShortcut(t, server, "create", map[string]string{
|
||||
"name": "v1.1",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create shortcut failed: %v", err)
|
||||
}
|
||||
|
||||
assertEqual(t, payload["name"], "v1.1")
|
||||
if _, ok := payload["description"]; ok {
|
||||
t.Fatalf("description should be omitted when not provided")
|
||||
}
|
||||
if _, ok := payload["effective_date"]; ok {
|
||||
t.Fatalf("effective_date should be omitted when not provided")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMilestoneViewWithIssueFilters(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assertRequest(t, r, "GET", "/v1/owner/repo/milestones/7.json")
|
||||
|
|
|
|||
Loading…
Reference in New Issue