forked from Gitlink/gitlink-cli
fix: 修复 label API 路径和字段名,batch-label 现在实际生效
- Label 列表 API 路径从 /v1/:owner/:repo/labels 改为 /:owner/:repo/labels(v0 前缀) - Label 数据解析从 env.Data 改为从 env.Data["issue_tags"] 提取 - Issue PATCH 中 label 字段从 label_ids 改为 issue_tag_ids(GitLink 正确字段名) - 新增 getTagIDs() 函数处理 GET issue 返回的 tags 对象数组 - 端到端验证:add/remove/set/dry-run/幂等/多标签/数字ID 全部通过
This commit is contained in:
parent
a4507ca9e9
commit
d183bc2c5d
|
|
@ -395,7 +395,7 @@ func ResolveUserID(ctx *common.RuntimeContext, name string) (int, error) {
|
|||
|
||||
// ResolveLabelID 把 label 名称解析为数字 label ID。
|
||||
// 若 name 本身是数字则直接返回;否则首次按当前仓库拉取全部 label
|
||||
// (GET /v1/{owner}/{repo}/labels)并按仓库维度缓存,后续直接走缓存。
|
||||
// (GET /{owner}/{repo}/labels,v0 前缀)并按仓库维度缓存,后续直接走缓存。
|
||||
func ResolveLabelID(ctx *common.RuntimeContext, name string) (int, error) {
|
||||
if id, err := strconv.Atoi(name); err == nil {
|
||||
return id, nil
|
||||
|
|
@ -416,14 +416,24 @@ func ResolveLabelID(ctx *common.RuntimeContext, name string) (int, error) {
|
|||
resolverCacheMu.Unlock()
|
||||
|
||||
// 缓存未命中,从 API 拉取该仓库的全部 label
|
||||
env, err := ctx.CallAPI("GET", v1RepoPath(ctx)+"/labels", nil)
|
||||
env, err := ctx.CallAPI("GET", fmt.Sprintf("/%s/%s/labels", ctx.Owner, ctx.Repo), nil)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("resolve label: %w", err)
|
||||
}
|
||||
|
||||
items, err := parseDataArray(env.Data)
|
||||
// API 返回 {"status":0, "issue_tags":[...], ...},client.Do 把整个响应包在 envelope 里,
|
||||
// 所以 env.Data 是包含 issue_tags 键的 map,需要先提取 issue_tags 再解析数组。
|
||||
rawMap, ok := env.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("resolve label: unexpected response type %T", env.Data)
|
||||
}
|
||||
itemsRaw, ok := rawMap["issue_tags"]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("resolve label: response missing issue_tags field")
|
||||
}
|
||||
items, err := parseDataArray(itemsRaw)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("resolve label: parse data: %w", err)
|
||||
return 0, fmt.Errorf("resolve label: parse issue_tags: %w", err)
|
||||
}
|
||||
|
||||
// 在锁内把当前仓库的 label 全量写入按 repoKey 隔离的缓存
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ func createIssueFromRow(ctx *common.RuntimeContext, row []string, titleCol, body
|
|||
if err != nil {
|
||||
return fmt.Errorf("label %q: %w", labels, err)
|
||||
}
|
||||
body["label_ids"] = labelIDs
|
||||
body["issue_tag_ids"] = labelIDs
|
||||
}
|
||||
if pri := getCell(row, priorityCol); pri != "" {
|
||||
pid, err := strconv.Atoi(pri)
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ func manageIssueLabels(ctx *common.RuntimeContext, number string, action string,
|
|||
body := map[string]interface{}{
|
||||
"subject": current.Subject,
|
||||
"description": current.Description,
|
||||
"label_ids": finalIDs,
|
||||
"issue_tag_ids": finalIDs,
|
||||
}
|
||||
_, err = ctx.CallAPI("PATCH", fmt.Sprintf("%s/issues/%s", v1RepoPath(ctx), number), body)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ var updateFieldMapping = map[string]string{
|
|||
"state": "status_id",
|
||||
"assignee": "assigner_ids",
|
||||
"milestone": "fixed_version_id",
|
||||
"label": "label_ids",
|
||||
"label": "issue_tag_ids",
|
||||
"priority": "priority_id",
|
||||
}
|
||||
|
||||
|
|
@ -127,12 +127,12 @@ func applyIssueUpdates(ctx *common.RuntimeContext, number string, row []string,
|
|||
}
|
||||
body["fixed_version_id"] = id
|
||||
}
|
||||
case "label_ids":
|
||||
case "issue_tag_ids":
|
||||
labelIDs, err := resolveLabelArgs(ctx, val, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("issue #%s label %q: %w", number, val, err)
|
||||
}
|
||||
body["label_ids"] = labelIDs
|
||||
body["issue_tag_ids"] = labelIDs
|
||||
case "priority_id":
|
||||
pid, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ func fetchIssueData(ctx *common.RuntimeContext, number string) (*IssueData, erro
|
|||
AssignedToID: getMapInt(issueMap, "assigned_to_id"),
|
||||
FixedVersionID: getMapInt(issueMap, "fixed_version_id"),
|
||||
PriorityID: getMapInt(issueMap, "priority_id"),
|
||||
LabelIDs: getMapIntSlice(issueMap, "label_ids"),
|
||||
LabelIDs: getTagIDs(issueMap, "tags"),
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
|
@ -307,6 +307,26 @@ func getMapIntSlice(m map[string]interface{}, key string) []int {
|
|||
return ids
|
||||
}
|
||||
|
||||
// getTagIDs 从 map 中提取 tag 对象数组中每个对象的 id 字段。
|
||||
// API 返回 tags: [{id: 1, name: "bug"}, ...],需要遍历对象提取 id。
|
||||
// 类型不匹配或缺失时返回 nil。
|
||||
func getTagIDs(m map[string]interface{}, key string) []int {
|
||||
raw, ok := m[key].([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
ids := make([]int, 0, len(raw))
|
||||
for _, item := range raw {
|
||||
if tag, ok := item.(map[string]interface{}); ok {
|
||||
id := getMapInt(tag, "id")
|
||||
if id > 0 {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func normalizeIssueStatus(state string) (interface{}, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(state)) {
|
||||
case "open":
|
||||
|
|
|
|||
Loading…
Reference in New Issue