Skip to content

Allow JSON array parameters in gh api #1484

Description

@mislav

Neither --field nor --raw-field accept JSON arrays right now. To pass a JSON array or a nested object, one needs to construct the JSON payload outside of gh and pass it in via --input. E.g.

jq -n '...' | gh api repos/:owner/:repo/deployments --input -

I propose a new array syntax for fields:

# array of strings
-f labels[]=one labels[]=two

# empty array
-f required_contexts[]

# other value types
-F foo[]=true -F bar[]=null

This syntax would allow passing values of any type, including an empty array, and is fully backwards-compatible. The only theoretical drawback is that it would be impossible to pass a parameter name that includes the literal [] characters, but since no API parameters ever have [] characters in their name, I think this is not a concern.

Originally posted by @mislav in #921 (comment)

Activity

  1. mislav commented on Aug 6, 2020

    @mislav
    ContributorAuthor

    Potential additional idea: use a similar syntax to pass nested objects as well, since some APIs require them as inputs. For example, the Gist API:

    gh api gists -F files[myfile.txt][content][email protected]

    I'm not sure if this is a crossing a line into too magic or complicated 😅

  2. added
    coreThis issue is not accepting PRs from outside contributors
    on Sep 30, 2020
  3. solvaholic commented on Dec 31, 2020

    @solvaholic

    Neither --field nor --raw-field accept JSON arrays right now. To pass a JSON array or a nested object, one needs to construct the JSON payload outside of gh and pass it in via --input. E.g.

    jq -n '...' | gh api repos/:owner/:repo/deployments --input -
    

    I'm trying to GET the repos/:owner/:repo/contents endpoint with a specific ref.

    This command returns the file content as expected 🎉:

    % gh api repos/:owner/:repo/contents/action.yml
    

    When I provide the ref parameter, however, I get 404 😢:

    % jq -n '{"ref": "main"}' 
    {
      "ref": "main"
    }
    
    % jq -n '{"ref": "main"}' | gh api repos/:owner/:repo/contents/action.yml -i --input -
    HTTP/1.1 404 Not Found
    Access-Control-Allow-Origin: *
    Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
    Content-Security-Policy: default-src 'none'
    Content-Type: application/json; charset=utf-8
    Date: Thu, 31 Dec 2020 16:28:40 GMT
    Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
    Server: GitHub.com
    Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    Vary: Accept-Encoding, Accept, X-Requested-With
    X-Accepted-Oauth-Scopes: repo
    X-Content-Type-Options: nosniff
    X-Frame-Options: deny
    X-Github-Media-Type: github.v3; format=json
    X-Github-Request-Id: DC52:1CF9:6DF32A9:BBFEBB9:5FEDFC38
    X-Oauth-Scopes: gist, read:org, repo, workflow
    X-Ratelimit-Limit: 5000
    X-Ratelimit-Remaining: 4992
    X-Ratelimit-Reset: 1609433238
    X-Ratelimit-Used: 8
    X-Xss-Protection: 1; mode=block
    
    {
      "message": "Not Found",
      "documentation_url": "https://docs.github.com/rest"
    }
    gh: Not Found (HTTP 404)
    
    % gh api repos/:owner/:repo/contents/action.yml -f ref=main
    {
      "message": "Not Found",
      "documentation_url": "https://docs.github.com/rest"
    }
    gh: Not Found (HTTP 404)
    % gh api repos/:owner/:repo/contents/action.yml -F ref=main
    {
      "message": "Not Found",
      "documentation_url": "https://docs.github.com/rest"
    }
    gh: Not Found (HTTP 404)
    

    I assume I'm missing something that'll be obvious to others. @mislav do you see what I'm missing? Or have suggestions how to debug this?

  4. joe-sharp commented on Jan 22, 2021

    @joe-sharp

    @solvaholic Not sure if you solved this already but according to the doc you linked, ref is a query parameter. So you would need to do this:

    gh api repos/:owner/:repo/contents/action.yml?ref=main

    You may need to quote it:

    gh api 'repos/:owner/:repo/contents/action.yml?ref=main'
  5. mislav commented on Jan 22, 2021

    @mislav
    ContributorAuthor

    Parameters given via --field/--raw-field can also be forced to be query parameters by explicitly configuring the method to be GET:

    gh api -X GET repos/:owner/:repo/contents/action.yml -f ref=main
    
  6. solvaholic commented on Jan 25, 2021

    @solvaholic

    You may need to quote it:

    :doh: I'm near certain this was a factor when I tried adding the query parameter.

    Parameters given via --field/--raw-field can also be forced to be query parameters by explicitly configuring the method to be GET:

    And this as well. I had in mind gh would default to GET for this request.

    Of course, both methods work. Thank you @joe-sharp @mislav 🙇

  7. mislav commented on Jan 25, 2021

    @mislav
    ContributorAuthor

    I had in mind gh would default to GET for this request.

    The fact that gh automatically switches to POST once -f or -F is added is a decision I now regret for its magic-ness 🙈 but we can't back out of it easily due to backwards-compatibility.

  8. ErikSchierboom commented on Apr 7, 2021

    @ErikSchierboom

    I've managed to workaround this via the --input parameter. It would be awesome if arrays could be supported via the --field/--raw-field syntax too.

  9. embano1 commented on Apr 12, 2021

    @embano1
    Contributor

    Hit same issue and spend one hour mapping the OpenAPI spec against gh behavior and was wondering why arrays/objects are not supported, e.g.:

    # does not work
    gh api repos/:owner/:repo/issues/1/labels -f labels='["wontfix"]'
    
    # works
    jq -n '{"labels":["wontfix"]}' | gh api repos/:owner/:repo/issues/1/labels --input -

    Will file a PR because this behavior is not clear from the docs Pass one or more --raw-field values in "key=value" format to add **JSON-encoded string parameters** to the POST body..

  10. added
    discussFeature changes that require discussion primarily among the GitHub CLI team
    on May 17, 2022
  11. removed
    discussFeature changes that require discussion primarily among the GitHub CLI team
    on May 18, 2022
  12. added a commit that references this issue on May 23, 2022
  13. sammcj commented on Oct 5, 2022

    @sammcj

    This still seems to be an issue - you can't configure check contexts when setting up branch protection because of this. 😞

    I think this issue is missing a label of ~bug ?

  14. pzoomin commented on Mar 18, 2024

    @pzoomin

    This still seems to be an issue - you can't configure check contexts when setting up branch protection because of this. 😞

    I think this issue is missing a label of ~bug ?

    I was able to get this to work, but the syntax was not immediately apparent. Here is an example:

    gh api -X PUT /repos/zoomin-software/skins_foo/branches/development/protection -F restrictions=null -F enforce_admins=true -F 'required_pull_request_reviews[require_code_owner_reviews]=true' -F 'required_status_checks[strict]=true' -F 'required_status_checks[contexts][]=null'

    Note the last param I pass: -F 'required_status_checks[contexts][]=null', with the second array within the array, but the value being null. This is how I was able to pass an "empty" array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    coreThis issue is not accepting PRs from outside contributorsenhancementa request to improve CLI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions