fix(api): serialize arrays with non-lowercase elements
What does this MR do and why?
glab api -f/-F decides whether a bracketed value is an array with this regex:
^\[\s*([[:lower:]_]+(\s*,\s*[[:lower:]_]+)*)?\s*\]$Every element has to be lowercase letters and underscores, so a hyphen, an uppercase letter or a digit makes the whole value fall through and get sent as a JSON string:
glab api -X PUT projects/:id -F "topics=[my-topic, GitLab]"
# sent: {"topics":"[my-topic, GitLab]"}
# expected: {"topics":["my-topic","GitLab"]}Project topics are the common way to hit this, since they are user-authored and routinely contain hyphens and capitals.
This MR:
- Broadens an element to either a double-quoted string or a run of characters that cannot be confused with the list syntax itself.
- Splits on commas that sit outside quotes, so
["one, two", three]is two elements rather than three. - Returns an empty slice for
[], which previously produced a single empty string. Sending an empty array is how a field is cleared.
Values that only look like a list, such as a description containing nested brackets, are still sent unchanged as strings.
I went with the narrow fix rather than parsing any [/{ value as JSON. The
JSON route changes types for existing users ([1, 2] would stop being strings)
and reaches beyond this issue, so it seemed better raised separately.
The first version of this MR broke that promise by another route: the
bare-element class matched digits, so [1, 2] newly became an array anyway.
@GitLabDuo and @phikai caught it in review. A bare element must now contain at
least one non-digit character, so [1, 2] stays a string exactly as on main.
Quoting is how a caller opts numeric elements into array handling:
["1", "2"].
Test coverage
internal/commands/api/http_test.go:
- Four new
Test_httpRequestcases: hyphen/uppercase/digit elements, quoted elements containing spaces and commas,[], and a string that only looks like a list. Test_parseStringArrayFieldcovering the element shapes.Test_strArrayRegex_rejectsNonArrayspinning what must not be treated as an array, including unbalanced brackets and an unbalanced quote.
The existing [api, read_api] case is unchanged and still passes.
Related issues
Closes #8216