From f159c174dd3b19cb55f253730f08eb93fe32ab9a Mon Sep 17 00:00:00 2001 From: Roderick Dunn Date: Tue, 13 Jan 2026 15:09:34 -0500 Subject: [PATCH] feat(custom-fields): Add support for CMDB object fields CMDB (Assets/Insight) object fields require JSON array format with workspaceId, id, and objectId properties. Previously, the CLI passed these values as escaped strings, causing "expected Object" errors. This change: - Adds customFieldFormatCMDBObject constant for "cmdb-object-field" type - Parses JSON input for CMDB fields in constructCustomFields() - Handles CMDB fields in constructCustomFieldsForEdit() with proper "set" semantics for edit operations Usage: jira issue create --custom cycle='[{"workspaceId":"...","objectId":"24"}]' Co-Authored-By: Claude Opus 4.5 --- pkg/jira/create.go | 17 ++++++++++++++--- pkg/jira/customfield.go | 9 +++++---- pkg/jira/edit.go | 18 +++++++++++++++--- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/pkg/jira/create.go b/pkg/jira/create.go index bec14918..25378862 100644 --- a/pkg/jira/create.go +++ b/pkg/jira/create.go @@ -247,14 +247,25 @@ func constructCustomFields(fields map[string]string, configuredFields []IssueTyp case customFieldFormatProject: data.Fields.M.customFields[configured.Key] = customFieldTypeProject{Value: val} case customFieldFormatArray: - pieces := strings.Split(strings.TrimSpace(val), ",") - if configured.Schema.Items == customFieldFormatOption { + switch configured.Schema.Items { + case customFieldFormatCMDBObject: + // CMDB object fields require JSON array format. + var jsonVal interface{} + if err := json.Unmarshal([]byte(val), &jsonVal); err == nil { + data.Fields.M.customFields[configured.Key] = jsonVal + } else { + // If JSON parsing fails, pass as-is and let Jira API handle it. + data.Fields.M.customFields[configured.Key] = val + } + case customFieldFormatOption: + pieces := strings.Split(strings.TrimSpace(val), ",") items := make([]customFieldTypeOption, 0) for _, p := range pieces { items = append(items, customFieldTypeOption{Value: p}) } data.Fields.M.customFields[configured.Key] = items - } else { + default: + pieces := strings.Split(strings.TrimSpace(val), ",") data.Fields.M.customFields[configured.Key] = pieces } case customFieldFormatNumber: diff --git a/pkg/jira/customfield.go b/pkg/jira/customfield.go index 92f3c675..35da4f27 100644 --- a/pkg/jira/customfield.go +++ b/pkg/jira/customfield.go @@ -1,10 +1,11 @@ package jira const ( - customFieldFormatOption = "option" - customFieldFormatArray = "array" - customFieldFormatNumber = "number" - customFieldFormatProject = "project" + customFieldFormatOption = "option" + customFieldFormatArray = "array" + customFieldFormatNumber = "number" + customFieldFormatProject = "project" + customFieldFormatCMDBObject = "cmdb-object-field" ) type customField map[string]interface{} diff --git a/pkg/jira/edit.go b/pkg/jira/edit.go index a8e4bcd2..3818bd1b 100644 --- a/pkg/jira/edit.go +++ b/pkg/jira/edit.go @@ -378,8 +378,19 @@ func constructCustomFieldsForEdit(fields map[string]string, configuredFields []I case customFieldFormatProject: data.Update.M.customFields[configured.Key] = []customFieldTypeProjectSet{{Set: customFieldTypeProject{Value: val}}} case customFieldFormatArray: - pieces := strings.Split(strings.TrimSpace(val), ",") - if configured.Schema.Items == customFieldFormatOption { + switch configured.Schema.Items { + case customFieldFormatCMDBObject: + // CMDB object fields require JSON array format. + var jsonVal interface{} + if err := json.Unmarshal([]byte(val), &jsonVal); err == nil { + // For edit operations, wrap in a "set" operation. + data.Update.M.customFields[configured.Key] = []map[string]interface{}{{"set": jsonVal}} + } else { + // If JSON parsing fails, pass as-is and let Jira API handle it. + data.Update.M.customFields[configured.Key] = []customFieldTypeStringSet{{Set: val}} + } + case customFieldFormatOption: + pieces := strings.Split(strings.TrimSpace(val), ",") items := make([]customFieldTypeOptionAddRemove, 0) for _, p := range pieces { if strings.HasPrefix(p, separatorMinus) { @@ -389,7 +400,8 @@ func constructCustomFieldsForEdit(fields map[string]string, configuredFields []I } } data.Update.M.customFields[configured.Key] = items - } else { + default: + pieces := strings.Split(strings.TrimSpace(val), ",") data.Update.M.customFields[configured.Key] = pieces } case customFieldFormatNumber: